mirror of
https://github.com/xmrig/xmrig.git
synced 2025-12-08 08:23:34 -05:00
Compare commits
151 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed0972da85 | ||
|
|
815f8cbb96 | ||
|
|
ccc7fba2c4 | ||
|
|
bf56ee00bc | ||
|
|
0d4b908bfe | ||
|
|
8bd2582416 | ||
|
|
09e859d41e | ||
|
|
6fd4d99fa1 | ||
|
|
b8089e637a | ||
|
|
fed163568e | ||
|
|
4e4c54314b | ||
|
|
e759ddca49 | ||
|
|
fcb7b0fb3e | ||
|
|
d1bf9ddc3f | ||
|
|
ccc2d77592 | ||
|
|
70b0a39dc8 | ||
|
|
b34084b961 | ||
|
|
1587fb27d2 | ||
|
|
faf14f5e5a | ||
|
|
555eee8236 | ||
|
|
1bf428f8da | ||
|
|
c86f9816d3 | ||
|
|
599117abde | ||
|
|
e3689ccb1a | ||
|
|
babc48f767 | ||
|
|
33d752bcaa | ||
|
|
5af169fd7b | ||
|
|
8ebb659cd6 | ||
|
|
7c8a9677a1 | ||
|
|
981e043ada | ||
|
|
8c2951db2d | ||
|
|
2d08f59184 | ||
|
|
827e611911 | ||
|
|
de2c351a66 | ||
|
|
42bf85d10b | ||
|
|
9580c30d8a | ||
|
|
3df545cfc5 | ||
|
|
a370b8fd30 | ||
|
|
6774f86fcd | ||
|
|
a0a8711dab | ||
|
|
3ad11685cc | ||
|
|
bcef4b12ec | ||
|
|
f9c244f0aa | ||
|
|
29aa466023 | ||
|
|
b772349f69 | ||
|
|
c5fbc1a182 | ||
|
|
30642881bf | ||
|
|
ef3af1c4fd | ||
|
|
04c5d6d00a | ||
|
|
8b83a5fe2e | ||
|
|
878e021ff6 | ||
|
|
5a606be8be | ||
|
|
da02e9a3a2 | ||
|
|
b11f95d248 | ||
|
|
9797f49456 | ||
|
|
0556fd664c | ||
|
|
1cf5ad5212 | ||
|
|
c31ea00399 | ||
|
|
387524e1c5 | ||
|
|
5f1f901649 | ||
|
|
c29dc8bcf4 | ||
|
|
b8cc1136a4 | ||
|
|
4c06d8b080 | ||
|
|
1ecee56eb6 | ||
|
|
26b8206332 | ||
|
|
7deee3240b | ||
|
|
668b23c5b0 | ||
|
|
7741c341c7 | ||
|
|
8a70202a98 | ||
|
|
bc2b7d1895 | ||
|
|
ebb0f81f2f | ||
|
|
eb3e2b8868 | ||
|
|
583d892eb5 | ||
|
|
b145f14ad8 | ||
|
|
ce19edf36c | ||
|
|
108fd5690e | ||
|
|
c19fe3cea7 | ||
|
|
187c7680cc | ||
|
|
20061e1b8b | ||
|
|
2baccab0f9 | ||
|
|
44782befea | ||
|
|
5b7a1bc6dc | ||
|
|
e67a95bd8b | ||
|
|
88dd218ad8 | ||
|
|
ee9ba778f8 | ||
|
|
6080f292e7 | ||
|
|
cf8f81f5fa | ||
|
|
aab48fde96 | ||
|
|
bf25b4e5d4 | ||
|
|
0c2bda9aa5 | ||
|
|
d71a15e8da | ||
|
|
c4bccf410b | ||
|
|
719601f92b | ||
|
|
ff7be00f6f | ||
|
|
d3b0038bda | ||
|
|
3b46f5eb64 | ||
|
|
03dbb85c82 | ||
|
|
a2574e1b1b | ||
|
|
15b4244ea8 | ||
|
|
0dcf127c26 | ||
|
|
9964952c92 | ||
|
|
90648771c0 | ||
|
|
985adcbc13 | ||
|
|
16f3338e42 | ||
|
|
2650545916 | ||
|
|
c107547c6c | ||
|
|
60f7f93408 | ||
|
|
dfbfde5b22 | ||
|
|
0c752ee018 | ||
|
|
f329410940 | ||
|
|
0a6d70c499 | ||
|
|
1678dc1d6d | ||
|
|
caf7cda1d5 | ||
|
|
3de7983826 | ||
|
|
8dda8d293b | ||
|
|
e71e9486c6 | ||
|
|
b35ecef06f | ||
|
|
454c78cf0a | ||
|
|
c97693cd51 | ||
|
|
d855ae2e36 | ||
|
|
42d2ab18ee | ||
|
|
97a8d448c0 | ||
|
|
54cef68aa9 | ||
|
|
3492670839 | ||
|
|
c43c667fed | ||
|
|
361394be21 | ||
|
|
8235ae0fa6 | ||
|
|
ac89023a79 | ||
|
|
f92b5ed9f6 | ||
|
|
7ce21d458a | ||
|
|
5513fab59b | ||
|
|
5e6560cb07 | ||
|
|
25d76626c1 | ||
|
|
cad15069c8 | ||
|
|
8ab4c1c8bd | ||
|
|
f29d05bdde | ||
|
|
1474d3fe53 | ||
|
|
d2fd43ca03 | ||
|
|
95f48fd058 | ||
|
|
f8bda3a6b3 | ||
|
|
21c243ed8f | ||
|
|
1013aa5004 | ||
|
|
44875b0a94 | ||
|
|
b1f1474438 | ||
|
|
4eb7e5bbfd | ||
|
|
d874ede49e | ||
|
|
add10c829c | ||
|
|
4acfb213b8 | ||
|
|
78a4b9de0f | ||
|
|
9fe2bbcd81 | ||
|
|
adb778de8a |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
/build
|
/build
|
||||||
|
/CMakeLists.txt.user
|
||||||
|
|||||||
41
CHANGELOG.md
Normal file
41
CHANGELOG.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# 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).
|
||||||
|
- Added new option `--print-time=N`, print hashrate report every N seconds.
|
||||||
|
- New hashrate reports, by default every 60 secons.
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
# v0.8.2
|
||||||
|
- Fixed L2 cache size detection for AMD CPUs (Bulldozer/Piledriver/Steamroller/Excavator architecture).
|
||||||
|
|
||||||
|
# v0.8.2
|
||||||
|
- Fixed L2 cache size detection for AMD CPUs (Bulldozer/Piledriver/Steamroller/Excavator architecture).
|
||||||
|
- 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`.
|
||||||
|
|
||||||
|
# v0.8.0
|
||||||
|
- Added double hash mode, also known as lower power mode. `--av=2` and `--av=4`.
|
||||||
|
- Added smart automatic CPU configuration. Default threads count now depends on size of the L3 cache of CPU.
|
||||||
|
- Added CryptoNight-Lite support for AEON `-a cryptonight-lite`.
|
||||||
|
- Added `--max-cpu-usage` option for auto CPU configuration mode.
|
||||||
|
- Added `--safe` option for adjust threads and algorithm variations to current CPU.
|
||||||
|
- No more manual steps to enable huge pages on Windows. XMRig will do it automatically.
|
||||||
|
- Removed BMI2 algorithm variation.
|
||||||
|
- Removed default pool URL.
|
||||||
|
|
||||||
|
# v0.6.0
|
||||||
|
- Added automatic cryptonight self test.
|
||||||
|
- New software AES algorithm variation. Will be automatically selected if cpu not support AES-NI.
|
||||||
|
- Added 32 bit builds.
|
||||||
|
- Documented [algorithm variations](https://github.com/xmrig/xmrig#algorithm-variations).
|
||||||
|
|
||||||
|
# v0.5.0
|
||||||
|
- Initial public release.
|
||||||
237
CMakeLists.txt
237
CMakeLists.txt
@@ -1,127 +1,172 @@
|
|||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
project(xmrig C)
|
project(xmrig)
|
||||||
|
|
||||||
|
option(WITH_LIBCPUID "Use Libcpuid" ON)
|
||||||
|
option(WITH_AEON "CryptoNight-Lite support" ON)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
compat.h
|
src/3rdparty/align.h
|
||||||
algo/cryptonight/cryptonight.h
|
src/App.h
|
||||||
elist.h
|
src/Console.h
|
||||||
xmrig.h
|
src/Cpu.h
|
||||||
version.h
|
src/interfaces/IClientListener.h
|
||||||
options.h
|
src/interfaces/IJobResultListener.h
|
||||||
cpu.h
|
src/interfaces/IWorker.h
|
||||||
persistent_memory.h
|
src/Mem.h
|
||||||
stratum.h
|
src/net/Client.h
|
||||||
stats.h
|
src/net/Job.h
|
||||||
util.h
|
src/net/JobResult.h
|
||||||
donate.h
|
src/net/Network.h
|
||||||
|
src/net/Url.h
|
||||||
|
src/Options.h
|
||||||
|
src/Summary.h
|
||||||
|
src/version.h
|
||||||
|
src/workers/DoubleWorker.h
|
||||||
|
src/workers/Handle.h
|
||||||
|
src/workers/Hashrate.h
|
||||||
|
src/workers/SingleWorker.h
|
||||||
|
src/workers/Worker.h
|
||||||
|
src/workers/Workers.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADERS_CRYPTO
|
set(HEADERS_CRYPTO
|
||||||
crypto/c_groestl.h
|
src/crypto/c_blake256.h
|
||||||
crypto/c_blake256.h
|
src/crypto/c_groestl.h
|
||||||
crypto/c_jh.h
|
src/crypto/c_jh.h
|
||||||
crypto/c_skein.h
|
src/crypto/c_keccak.h
|
||||||
crypto/oaes_lib.h
|
src/crypto/c_skein.h
|
||||||
crypto/oaes_config.h
|
src/crypto/CryptoNight.h
|
||||||
crypto/aesb.h
|
src/crypto/CryptoNight_p.h
|
||||||
)
|
src/crypto/CryptoNight_test.h
|
||||||
|
src/crypto/groestl_tables.h
|
||||||
set(HEADERS_COMPAT
|
src/crypto/hash.h
|
||||||
compat/winansi.h
|
src/crypto/skein_port.h
|
||||||
)
|
|
||||||
|
|
||||||
set(HEADERS_UTILS
|
|
||||||
utils/applog.h
|
|
||||||
utils/threads.h
|
|
||||||
utils/summary.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
xmrig.c
|
src/App.cpp
|
||||||
algo/cryptonight/cryptonight_common.c
|
src/Console.cpp
|
||||||
util.c
|
src/Mem.cpp
|
||||||
options.c
|
src/net/Client.cpp
|
||||||
cpu.c
|
src/net/Job.cpp
|
||||||
stratum.c
|
src/net/Network.cpp
|
||||||
stats.c
|
src/net/Url.cpp
|
||||||
memory.c
|
src/Options.cpp
|
||||||
|
src/Summary.cpp
|
||||||
|
src/workers/DoubleWorker.cpp
|
||||||
|
src/workers/Handle.cpp
|
||||||
|
src/workers/Hashrate.cpp
|
||||||
|
src/workers/SingleWorker.cpp
|
||||||
|
src/workers/Worker.cpp
|
||||||
|
src/workers/Workers.cpp
|
||||||
|
src/xmrig.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES_CRYPTO
|
set(SOURCES_CRYPTO
|
||||||
crypto/c_keccak.c
|
src/crypto/c_keccak.c
|
||||||
crypto/c_groestl.c
|
src/crypto/c_groestl.c
|
||||||
crypto/c_blake256.c
|
src/crypto/c_blake256.c
|
||||||
crypto/c_jh.c
|
src/crypto/c_jh.c
|
||||||
crypto/c_skein.c
|
src/crypto/c_skein.c
|
||||||
crypto/oaes_lib.c
|
src/crypto/soft_aes.c
|
||||||
crypto/aesb.c
|
src/crypto/soft_aes.c
|
||||||
)
|
src/crypto/CryptoNight.cpp
|
||||||
|
|
||||||
set(SOURCES_UTILS
|
|
||||||
utils/applog.c
|
|
||||||
utils/summary.c
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(SOURCES_OS win/cpu_win.c win/memory_win.c win/xmrig_win.c compat/winansi.c)
|
set(SOURCES_OS
|
||||||
set(EXTRA_LIBS ws2_32)
|
res/app.rc
|
||||||
add_definitions(/D_WIN32_WINNT=0x600)
|
src/3rdparty/winansi.cpp
|
||||||
|
src/3rdparty/winansi.h
|
||||||
|
src/App_win.cpp
|
||||||
|
src/Cpu_win.cpp
|
||||||
|
src/Mem_win.cpp
|
||||||
|
src/net/Network_win.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_definitions(/DWIN32)
|
||||||
|
set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv)
|
||||||
|
elseif (APPLE)
|
||||||
|
set(SOURCES_OS
|
||||||
|
src/App_unix.cpp
|
||||||
|
src/Cpu_mac.cpp
|
||||||
|
src/Mem_unix.cpp
|
||||||
|
src/net/Network_mac.cpp
|
||||||
|
)
|
||||||
else()
|
else()
|
||||||
set(SOURCES_OS unix/cpu_unix.c unix/memory_unix.c unix/xmrig_unix.c)
|
set(SOURCES_OS
|
||||||
|
src/App_unix.cpp
|
||||||
|
src/Cpu_unix.cpp
|
||||||
|
src/Mem_unix.cpp
|
||||||
|
src/net/Network_unix.cpp
|
||||||
|
)
|
||||||
|
|
||||||
set(EXTRA_LIBS pthread)
|
set(EXTRA_LIBS pthread)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(.)
|
add_definitions(/DUNICODE)
|
||||||
add_definitions(/DUSE_NATIVE_THREADS)
|
#add_definitions(/DAPP_DEBUG)
|
||||||
add_definitions(/D_GNU_SOURCE)
|
|
||||||
add_definitions(/DDEBUG_THREADS)
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
find_package(UV REQUIRED)
|
||||||
|
|
||||||
if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
||||||
set(CMAKE_BUILD_TYPE Release)
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -mbmi2")
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wno-pointer-to-int-cast")
|
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
|
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-2")
|
|
||||||
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-generate")
|
|
||||||
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-use -fprofile-correction")
|
|
||||||
|
|
||||||
if (WIN32)
|
# https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||||
|
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall")
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -std=c++14 -fno-exceptions -fno-rtti")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
||||||
|
else()
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_definitions(/D_GNU_SOURCE)
|
||||||
|
|
||||||
|
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2")
|
||||||
|
|
||||||
|
elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||||
|
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Ox /Ot /Oi /MT /GL")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox /Ot /Oi /MT /GL")
|
||||||
|
|
||||||
|
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||||
|
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall")
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants")
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -std=c++14 -fno-exceptions -fno-rtti")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants")
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(compat/jansson)
|
if (WITH_LIBCPUID)
|
||||||
add_subdirectory(compat/jansson)
|
add_subdirectory(src/3rdparty/libcpuid)
|
||||||
|
|
||||||
find_package(CURL REQUIRED)
|
include_directories(src/3rdparty/libcpuid)
|
||||||
|
set(CPUID_LIB cpuid)
|
||||||
if (CURL_FOUND)
|
set(SOURCES_CPUID src/Cpu.cpp)
|
||||||
include_directories(${CURL_INCLUDE_DIRS})
|
|
||||||
add_definitions(/DCURL_STATICLIB)
|
|
||||||
link_directories(${CURL_LIBRARIES})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
add_subdirectory(algo/cryptonight/bmi2)
|
|
||||||
|
|
||||||
set(CRYPTONIGHT64
|
|
||||||
algo/cryptonight/cryptonight_av1_aesni.c
|
|
||||||
algo/cryptonight/cryptonight_av2_aesni_wolf.c
|
|
||||||
algo/cryptonight/cryptonight_av4_legacy.c
|
|
||||||
algo/cryptonight/cryptonight_av5_aesni_experimental.c
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(xmrig ${HEADERS} ${HEADERS_CRYPTO} ${SOURCES} ${SOURCES_CRYPTO} ${HEADERS_UTILS} ${SOURCES_UTILS} ${HEADERS_COMPAT} ${SOURCES_COMPAT} ${SOURCES_OS} ${CRYPTONIGHT64})
|
|
||||||
target_link_libraries(xmrig jansson curl cryptonight_av3_aesni_bmi2 ${EXTRA_LIBS})
|
|
||||||
else()
|
else()
|
||||||
set(CRYPTONIGHT32
|
add_definitions(/DXMRIG_NO_LIBCPUID)
|
||||||
algo/cryptonight/cryptonight_av1_aesni32.c
|
set(SOURCES_CPUID src/Cpu_stub.cpp)
|
||||||
algo/cryptonight/cryptonight_av4_legacy.c
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(xmrig32 ${HEADERS} ${HEADERS_CRYPTO} ${SOURCES} ${SOURCES_CRYPTO} ${HEADERS_UTILS} ${SOURCES_UTILS} ${HEADERS_COMPAT} ${SOURCES_COMPAT} ${SOURCES_OS} ${CRYPTONIGHT32})
|
|
||||||
target_link_libraries(xmrig32 jansson -L${CURL_LIBRARIES} ${EXTRA_LIBS})
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
source_group("HEADERS" FILES ${HEADERS})
|
include_directories(src)
|
||||||
|
include_directories(src/3rdparty)
|
||||||
|
include_directories(src/3rdparty/jansson)
|
||||||
|
include_directories(${UV_INCLUDE_DIR})
|
||||||
|
|
||||||
|
add_subdirectory(src/3rdparty/jansson)
|
||||||
|
|
||||||
|
add_executable(xmrig ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO})
|
||||||
|
target_link_libraries(xmrig jansson ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB})
|
||||||
|
|||||||
57
README.md
57
README.md
@@ -2,24 +2,29 @@
|
|||||||
XMRig is high performance Monero (XMR) CPU miner, with the official full Windows support.
|
XMRig is high performance Monero (XMR) CPU miner, with the official full Windows support.
|
||||||
Based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code.
|
Based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code.
|
||||||
|
|
||||||
<img src="https://i.imgur.com/GhmdK2f.png" width="480">
|
<img src="http://i.imgur.com/GdRDnAu.png" width="596" >
|
||||||
|
|
||||||
#### Table of contents
|
#### Table of contents
|
||||||
* [Features](#features)
|
* [Features](#features)
|
||||||
* [Download](#download)
|
* [Download](#download)
|
||||||
* [Usage](#usage)
|
* [Usage](#usage)
|
||||||
* [Build](#build)
|
* [Algorithm variations](#algorithm-variations)
|
||||||
|
* [Build](https://github.com/xmrig/xmrig/wiki/Build)
|
||||||
* [Common Issues](#common-issues)
|
* [Common Issues](#common-issues)
|
||||||
* [Other information](#other-information)
|
* [Other information](#other-information)
|
||||||
* [Donations](#Donations)
|
* [Donations](#donations)
|
||||||
|
* [Contacts](#contacts)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
* High performance, faster than others (290+ H/s on i7 6700).
|
* High performance (290+ H/s on i7 6700).
|
||||||
* Official Windows support.
|
* Official Windows support.
|
||||||
* Small Windows executable, only 350 KB without dependencies.
|
* Small Windows executable, only 535 KB without dependencies.
|
||||||
* Support for backup (failover) mining server.
|
* Support for backup (failover) mining server.
|
||||||
* keepalived support.
|
* keepalived support.
|
||||||
* Command line options compatible with cpuminer.
|
* Command line options compatible with cpuminer.
|
||||||
|
* CryptoNight-Lite support for AEON.
|
||||||
|
* Smart automatic [CPU configuration](https://github.com/xmrig/xmrig/wiki/Threads).
|
||||||
|
* Nicehash support
|
||||||
* It's open source software.
|
* It's open source software.
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
@@ -30,11 +35,12 @@ Based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of
|
|||||||
## Usage
|
## Usage
|
||||||
### Basic example
|
### Basic example
|
||||||
```
|
```
|
||||||
xmrig.exe -o xmr-eu.dwarfpool.com:8005 -b xmr-usa.dwarfpool.com:8005 -u YOUR_WALLET -p x -k
|
xmrig.exe -o xmr-eu.dwarfpool.com:8005 -u YOUR_WALLET -p x -k
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
```
|
```
|
||||||
|
-a, --algo=ALGO cryptonight (default) or cryptonight-lite
|
||||||
-o, --url=URL URL of mining server
|
-o, --url=URL URL of mining server
|
||||||
-b, --backup-url=URL URL of backup mining server
|
-b, --backup-url=URL URL of backup mining server
|
||||||
-O, --userpass=U:P username:password pair for mining server
|
-O, --userpass=U:P username:password pair for mining server
|
||||||
@@ -50,40 +56,27 @@ xmrig.exe -o xmr-eu.dwarfpool.com:8005 -b xmr-usa.dwarfpool.com:8005 -u YOUR_WAL
|
|||||||
--donate-level=N donate level, default 5% (5 minutes in 100 minutes)
|
--donate-level=N donate level, default 5% (5 minutes in 100 minutes)
|
||||||
-B, --background run the miner in the background
|
-B, --background run the miner in the background
|
||||||
-c, --config=FILE load a JSON-format configuration file
|
-c, --config=FILE load a JSON-format configuration file
|
||||||
|
--max-cpu-usage=N maximum cpu usage for automatic threads mode (default 75)
|
||||||
|
--safe safe adjust threads and av settings for current cpu
|
||||||
|
--nicehash enable nicehash support
|
||||||
|
--print-time=N print hashrate report every N seconds
|
||||||
-h, --help display this help and exit
|
-h, --help display this help and exit
|
||||||
-V, --version output version information and exit
|
-V, --version output version information and exit
|
||||||
```
|
```
|
||||||
|
|
||||||
## Build
|
## Algorithm variations
|
||||||
### Ubuntu (Debian-based distros)
|
Since version 0.8.0.
|
||||||
```
|
* `--av=1` For CPUs with hardware AES.
|
||||||
sudo apt-get install git build-essential cmake libcurl4-openssl-dev
|
* `--av=2` Lower power mode (double hash) of `1`.
|
||||||
git clone https://github.com/xmrig/xmrig.git
|
* `--av=3` Software AES implementation.
|
||||||
cd xmrig
|
* `--av=4` Lower power mode (double hash) of `3`.
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
make
|
|
||||||
```
|
|
||||||
|
|
||||||
### Windows
|
|
||||||
It's complicated, you need [MSYS2](http://www.msys2.org/), custom libcurl build, and of course CMake too.
|
|
||||||
Configure options for libcurl:
|
|
||||||
```
|
|
||||||
./configure --disable-shared --enable-optimize --enable-threaded-resolver --disable-libcurl-option --disable-ares --disable-rt --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-manual --disable-ipv6 --disable-sspi --disable-crypto-auth --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --without-zlib --without-winssl --without-ssl --without-libssh2 --without-nghttp2 --disable-cookies --without-ca-bundle
|
|
||||||
```
|
|
||||||
CMake options:
|
|
||||||
```
|
|
||||||
cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCURL_INCLUDE_DIR="c:\<path>\curl-7.53.1\include" -DCURL_LIBRARY="c:\<path>\curl-7.53.1\lib\.libs"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Common Issues
|
## Common Issues
|
||||||
### HUGE PAGES unavailable
|
### HUGE PAGES unavailable
|
||||||
* Run XMRig as Administrator.
|
* Run XMRig as Administrator.
|
||||||
* Enable SeLockMemoryPrivilege. For Windows 7 pro, or Windows 8 and above see [this article](https://msdn.microsoft.com/en-gb/library/ms190730.aspx).
|
* Since version 0.8.0 XMRig automatically enable SeLockMemoryPrivilege for current user, but reboot or sign out still required. [Manual instruction](https://msdn.microsoft.com/en-gb/library/ms190730.aspx).
|
||||||
|
|
||||||
## Other information
|
## Other information
|
||||||
* Now only support 64 bit operating systems (Windows/Linux).
|
|
||||||
* No HTTP support, only stratum protocol support.
|
* No HTTP support, only stratum protocol support.
|
||||||
* No TLS support.
|
* No TLS support.
|
||||||
* Default donation 5% (5 minutes in 100 minutes) can be reduced to 1% via command line option `--donate-level`.
|
* Default donation 5% (5 minutes in 100 minutes) can be reduced to 1% via command line option `--donate-level`.
|
||||||
@@ -105,3 +98,7 @@ Please note performance is highly dependent on system load. The numbers above ar
|
|||||||
## Donations
|
## Donations
|
||||||
* XMR: `48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD`
|
* XMR: `48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD`
|
||||||
* BTC: `1P7ujsXeX7GxQwHNnJsRMgAdNkFZmNVqJT`
|
* BTC: `1P7ujsXeX7GxQwHNnJsRMgAdNkFZmNVqJT`
|
||||||
|
|
||||||
|
## Contacts
|
||||||
|
* support@xmrig.com
|
||||||
|
* [reddit](https://www.reddit.com/user/XMRig/)
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mbmi2")
|
|
||||||
add_library(cryptonight_av3_aesni_bmi2 STATIC ../cryptonight_av3_aesni_bmi2.c)
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
/* XMRig
|
|
||||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
|
||||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
|
||||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
|
||||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
|
||||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __CRYPTONIGHT_H__
|
|
||||||
#define __CRYPTONIGHT_H__
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define MEMORY (1 << 21) /* 2 MiB */
|
|
||||||
#define MEMORY_M128I (MEMORY >> 4) // 2 MiB / 16 = 128 ki * __m128i
|
|
||||||
#define ITER (1 << 20)
|
|
||||||
#define AES_BLOCK_SIZE 16
|
|
||||||
#define AES_KEY_SIZE 32 /*16*/
|
|
||||||
#define INIT_SIZE_BLK 8
|
|
||||||
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE) // 128
|
|
||||||
#define INIT_SIZE_M128I (INIT_SIZE_BYTE >> 4) // 8
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
union hash_state {
|
|
||||||
uint8_t b[200];
|
|
||||||
uint64_t w[25];
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
union cn_slow_hash_state {
|
|
||||||
union hash_state hs;
|
|
||||||
struct {
|
|
||||||
uint8_t k[64];
|
|
||||||
uint8_t init[INIT_SIZE_BYTE];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
|
|
||||||
struct cryptonight_ctx {
|
|
||||||
union cn_slow_hash_state state;
|
|
||||||
uint8_t text[INIT_SIZE_BYTE] __attribute((aligned(16)));
|
|
||||||
uint64_t a[2] __attribute__((aligned(16)));
|
|
||||||
uint64_t b[2] __attribute__((aligned(16)));
|
|
||||||
uint64_t c[2] __attribute__((aligned(16)));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
extern void (* const extra_hashes[4])(const void *, size_t, char *);
|
|
||||||
|
|
||||||
void cryptonight_init(int variant);
|
|
||||||
void cryptonight_hash(void* output, const void* input, size_t input_len);
|
|
||||||
int scanhash_cryptonight(int thr_id, uint32_t *hash, uint32_t *restrict pdata, const uint32_t *restrict ptarget, uint32_t max_nonce, unsigned long *restrict hashes_done, const char *memory, struct cryptonight_ctx *persistentctx);
|
|
||||||
|
|
||||||
#endif /* __CRYPTONIGHT_H__ */
|
|
||||||
@@ -1,216 +0,0 @@
|
|||||||
/* XMRig
|
|
||||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
|
||||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
|
||||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
|
||||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
|
||||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <x86intrin.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "cryptonight.h"
|
|
||||||
#include "crypto/c_keccak.h"
|
|
||||||
|
|
||||||
|
|
||||||
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2)
|
|
||||||
{
|
|
||||||
__m128i tmp4;
|
|
||||||
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF);
|
|
||||||
tmp4 = _mm_slli_si128(*tmp1, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, *tmp2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3)
|
|
||||||
{
|
|
||||||
__m128i tmp2, tmp4;
|
|
||||||
|
|
||||||
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00);
|
|
||||||
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA);
|
|
||||||
tmp4 = _mm_slli_si128(*tmp3, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special thanks to Intel for helping me
|
|
||||||
// with ExpandAESKey256() and its subroutines
|
|
||||||
static inline void ExpandAESKey256(char *keybuf)
|
|
||||||
{
|
|
||||||
__m128i tmp1, tmp2, tmp3, *keys;
|
|
||||||
|
|
||||||
keys = (__m128i *)keybuf;
|
|
||||||
|
|
||||||
tmp1 = _mm_load_si128((__m128i *)keybuf);
|
|
||||||
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10));
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[2] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[3] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[4] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[5] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[6] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[7] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[8] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[9] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[10] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[11] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[12] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[13] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[14] = tmp1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cryptonight_av1_aesni(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx)
|
|
||||||
{
|
|
||||||
keccak((const uint8_t *)input, 76, (uint8_t *) &ctx->state.hs, 200);
|
|
||||||
uint8_t ExpandedKey[256];
|
|
||||||
size_t i, j;
|
|
||||||
|
|
||||||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
|
||||||
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE);
|
|
||||||
ExpandAESKey256(ExpandedKey);
|
|
||||||
|
|
||||||
__m128i *longoutput, *expkey, *xmminput;
|
|
||||||
longoutput = (__m128i *) memory;
|
|
||||||
expkey = (__m128i *)ExpandedKey;
|
|
||||||
xmminput = (__m128i *)ctx->text;
|
|
||||||
|
|
||||||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE)
|
|
||||||
{
|
|
||||||
for(j = 0; j < 10; j++)
|
|
||||||
{
|
|
||||||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
|
||||||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
|
||||||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
|
||||||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
|
||||||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
|
||||||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
|
||||||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
|
||||||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
|
||||||
}
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4)]), xmminput[0]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 1]), xmminput[1]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 2]), xmminput[2]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 3]), xmminput[3]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 4]), xmminput[4]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 5]), xmminput[5]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 6]), xmminput[6]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 7]), xmminput[7]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 2; i++)
|
|
||||||
{
|
|
||||||
ctx->a[i] = ((uint64_t *)ctx->state.k)[i] ^ ((uint64_t *)ctx->state.k)[i+4];
|
|
||||||
ctx->b[i] = ((uint64_t *)ctx->state.k)[i+2] ^ ((uint64_t *)ctx->state.k)[i+6];
|
|
||||||
}
|
|
||||||
|
|
||||||
__m128i a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
|
||||||
__m128i b_x = _mm_load_si128((__m128i *) ctx->b);
|
|
||||||
|
|
||||||
uint64_t c[2] __attribute((aligned(16)));
|
|
||||||
uint64_t d[2] __attribute((aligned(16)));
|
|
||||||
|
|
||||||
for (i = 0; __builtin_expect(i < 0x80000, 1); i++) {
|
|
||||||
__m128i c_x = _mm_aesenc_si128(a_x, _mm_load_si128((__m128i *) ctx->a));
|
|
||||||
_mm_store_si128((__m128i *) c, c_x);
|
|
||||||
|
|
||||||
uint64_t *restrict d_ptr = (uint64_t *) &memory[c[0] & 0x1FFFF0];
|
|
||||||
_mm_store_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0], _mm_xor_si128(b_x, c_x));
|
|
||||||
b_x = c_x;
|
|
||||||
|
|
||||||
d[0] = d_ptr[0];
|
|
||||||
d[1] = d_ptr[1];
|
|
||||||
|
|
||||||
{
|
|
||||||
unsigned __int128 res = (unsigned __int128) c[0] * d[0];
|
|
||||||
|
|
||||||
d_ptr[0] = ctx->a[0] += res >> 64;
|
|
||||||
d_ptr[1] = ctx->a[1] += (uint64_t) res;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->a[0] ^= d[0];
|
|
||||||
ctx->a[1] ^= d[1];
|
|
||||||
|
|
||||||
a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
|
||||||
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE);
|
|
||||||
ExpandAESKey256(ExpandedKey);
|
|
||||||
|
|
||||||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) {
|
|
||||||
xmminput[0] = _mm_xor_si128(longoutput[(i >> 4)], xmminput[0]);
|
|
||||||
xmminput[1] = _mm_xor_si128(longoutput[(i >> 4) + 1], xmminput[1]);
|
|
||||||
xmminput[2] = _mm_xor_si128(longoutput[(i >> 4) + 2], xmminput[2]);
|
|
||||||
xmminput[3] = _mm_xor_si128(longoutput[(i >> 4) + 3], xmminput[3]);
|
|
||||||
xmminput[4] = _mm_xor_si128(longoutput[(i >> 4) + 4], xmminput[4]);
|
|
||||||
xmminput[5] = _mm_xor_si128(longoutput[(i >> 4) + 5], xmminput[5]);
|
|
||||||
xmminput[6] = _mm_xor_si128(longoutput[(i >> 4) + 6], xmminput[6]);
|
|
||||||
xmminput[7] = _mm_xor_si128(longoutput[(i >> 4) + 7], xmminput[7]);
|
|
||||||
|
|
||||||
for(j = 0; j < 10; j++)
|
|
||||||
{
|
|
||||||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
|
||||||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
|
||||||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
|
||||||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
|
||||||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
|
||||||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
|
||||||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
|
||||||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
|
|
||||||
keccakf((uint64_t *) &ctx->state.hs, 24);
|
|
||||||
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
|
|
||||||
}
|
|
||||||
@@ -1,239 +0,0 @@
|
|||||||
/* XMRig
|
|
||||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
|
||||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
|
||||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
|
||||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
|
||||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <x86intrin.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "cryptonight.h"
|
|
||||||
#include "crypto/c_keccak.h"
|
|
||||||
|
|
||||||
|
|
||||||
static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
|
|
||||||
// multiplier = ab = a * 2^32 + b
|
|
||||||
// multiplicand = cd = c * 2^32 + d
|
|
||||||
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
|
||||||
uint64_t a = multiplier >> 32;
|
|
||||||
uint64_t b = multiplier & 0xFFFFFFFF;
|
|
||||||
uint64_t c = multiplicand >> 32;
|
|
||||||
uint64_t d = multiplicand & 0xFFFFFFFF;
|
|
||||||
|
|
||||||
//uint64_t ac = a * c;
|
|
||||||
uint64_t ad = a * d;
|
|
||||||
//uint64_t bc = b * c;
|
|
||||||
uint64_t bd = b * d;
|
|
||||||
|
|
||||||
uint64_t adbc = ad + (b * c);
|
|
||||||
uint64_t adbc_carry = adbc < ad ? 1 : 0;
|
|
||||||
|
|
||||||
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
|
||||||
uint64_t product_lo = bd + (adbc << 32);
|
|
||||||
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
|
|
||||||
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
|
|
||||||
|
|
||||||
return product_lo;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2)
|
|
||||||
{
|
|
||||||
__m128i tmp4;
|
|
||||||
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF);
|
|
||||||
tmp4 = _mm_slli_si128(*tmp1, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, *tmp2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3)
|
|
||||||
{
|
|
||||||
__m128i tmp2, tmp4;
|
|
||||||
|
|
||||||
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00);
|
|
||||||
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA);
|
|
||||||
tmp4 = _mm_slli_si128(*tmp3, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special thanks to Intel for helping me
|
|
||||||
// with ExpandAESKey256() and its subroutines
|
|
||||||
static inline void ExpandAESKey256(char *keybuf)
|
|
||||||
{
|
|
||||||
__m128i tmp1, tmp2, tmp3, *keys;
|
|
||||||
|
|
||||||
keys = (__m128i *)keybuf;
|
|
||||||
|
|
||||||
tmp1 = _mm_load_si128((__m128i *)keybuf);
|
|
||||||
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10));
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[2] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[3] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[4] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[5] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[6] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[7] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[8] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[9] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[10] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[11] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[12] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[13] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[14] = tmp1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cryptonight_av1_aesni32(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx)
|
|
||||||
{
|
|
||||||
keccak((const uint8_t *)input, 76, (uint8_t *) &ctx->state.hs, 200);
|
|
||||||
uint8_t ExpandedKey[256];
|
|
||||||
size_t i, j;
|
|
||||||
|
|
||||||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
|
||||||
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE);
|
|
||||||
ExpandAESKey256(ExpandedKey);
|
|
||||||
|
|
||||||
__m128i *longoutput, *expkey, *xmminput;
|
|
||||||
longoutput = (__m128i *) memory;
|
|
||||||
expkey = (__m128i *)ExpandedKey;
|
|
||||||
xmminput = (__m128i *)ctx->text;
|
|
||||||
|
|
||||||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE)
|
|
||||||
{
|
|
||||||
for(j = 0; j < 10; j++)
|
|
||||||
{
|
|
||||||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
|
||||||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
|
||||||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
|
||||||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
|
||||||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
|
||||||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
|
||||||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
|
||||||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
|
||||||
}
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4)]), xmminput[0]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 1]), xmminput[1]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 2]), xmminput[2]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 3]), xmminput[3]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 4]), xmminput[4]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 5]), xmminput[5]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 6]), xmminput[6]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 7]), xmminput[7]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 2; i++)
|
|
||||||
{
|
|
||||||
ctx->a[i] = ((uint64_t *)ctx->state.k)[i] ^ ((uint64_t *)ctx->state.k)[i+4];
|
|
||||||
ctx->b[i] = ((uint64_t *)ctx->state.k)[i+2] ^ ((uint64_t *)ctx->state.k)[i+6];
|
|
||||||
}
|
|
||||||
|
|
||||||
__m128i a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
|
||||||
__m128i b_x = _mm_load_si128((__m128i *) ctx->b);
|
|
||||||
|
|
||||||
uint64_t c[2] __attribute((aligned(16)));
|
|
||||||
uint64_t d[2] __attribute((aligned(16)));
|
|
||||||
uint64_t hi;
|
|
||||||
|
|
||||||
for (i = 0; __builtin_expect(i < 0x80000, 1); i++) {
|
|
||||||
__m128i c_x = _mm_aesenc_si128(a_x, _mm_load_si128((__m128i *) ctx->a));
|
|
||||||
_mm_store_si128((__m128i *) c, c_x);
|
|
||||||
|
|
||||||
uint64_t *restrict d_ptr = (uint64_t *) &memory[c[0] & 0x1FFFF0];
|
|
||||||
_mm_store_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0], _mm_xor_si128(b_x, c_x));
|
|
||||||
b_x = c_x;
|
|
||||||
|
|
||||||
d[0] = d_ptr[0];
|
|
||||||
d[1] = d_ptr[1];
|
|
||||||
|
|
||||||
d_ptr[1] = ctx->a[1] += mul128(c[0], d[0], &hi);
|
|
||||||
d_ptr[0] = ctx->a[0] += hi;
|
|
||||||
|
|
||||||
ctx->a[0] ^= d[0];
|
|
||||||
ctx->a[1] ^= d[1];
|
|
||||||
|
|
||||||
a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
|
||||||
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE);
|
|
||||||
ExpandAESKey256(ExpandedKey);
|
|
||||||
|
|
||||||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) {
|
|
||||||
xmminput[0] = _mm_xor_si128(longoutput[(i >> 4)], xmminput[0]);
|
|
||||||
xmminput[1] = _mm_xor_si128(longoutput[(i >> 4) + 1], xmminput[1]);
|
|
||||||
xmminput[2] = _mm_xor_si128(longoutput[(i >> 4) + 2], xmminput[2]);
|
|
||||||
xmminput[3] = _mm_xor_si128(longoutput[(i >> 4) + 3], xmminput[3]);
|
|
||||||
xmminput[4] = _mm_xor_si128(longoutput[(i >> 4) + 4], xmminput[4]);
|
|
||||||
xmminput[5] = _mm_xor_si128(longoutput[(i >> 4) + 5], xmminput[5]);
|
|
||||||
xmminput[6] = _mm_xor_si128(longoutput[(i >> 4) + 6], xmminput[6]);
|
|
||||||
xmminput[7] = _mm_xor_si128(longoutput[(i >> 4) + 7], xmminput[7]);
|
|
||||||
|
|
||||||
for(j = 0; j < 10; j++)
|
|
||||||
{
|
|
||||||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
|
||||||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
|
||||||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
|
||||||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
|
||||||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
|
||||||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
|
||||||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
|
||||||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
|
|
||||||
keccakf((uint64_t *) &ctx->state.hs, 24);
|
|
||||||
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
|
|
||||||
}
|
|
||||||
@@ -1,237 +0,0 @@
|
|||||||
/* XMRig
|
|
||||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
|
||||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
|
||||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
|
||||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
|
||||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <x86intrin.h>
|
|
||||||
|
|
||||||
#include "cryptonight.h"
|
|
||||||
#include "crypto/c_keccak.h"
|
|
||||||
|
|
||||||
|
|
||||||
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2)
|
|
||||||
{
|
|
||||||
__m128i tmp4;
|
|
||||||
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF);
|
|
||||||
tmp4 = _mm_slli_si128(*tmp1, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, *tmp2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3)
|
|
||||||
{
|
|
||||||
__m128i tmp2, tmp4;
|
|
||||||
|
|
||||||
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00);
|
|
||||||
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA);
|
|
||||||
tmp4 = _mm_slli_si128(*tmp3, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special thanks to Intel for helping me
|
|
||||||
// with ExpandAESKey256() and its subroutines
|
|
||||||
static inline void ExpandAESKey256(char *keybuf)
|
|
||||||
{
|
|
||||||
__m128i tmp1, tmp2, tmp3, *keys;
|
|
||||||
|
|
||||||
keys = (__m128i *)keybuf;
|
|
||||||
|
|
||||||
tmp1 = _mm_load_si128((__m128i *)keybuf);
|
|
||||||
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10));
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[2] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[3] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[4] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[5] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[6] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[7] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[8] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[9] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[10] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[11] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[12] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[13] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[14] = tmp1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cryptonight_av2_aesni_wolf(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx)
|
|
||||||
{
|
|
||||||
keccak((const uint8_t *) input, 76, (uint8_t *) &ctx->state.hs, 200);
|
|
||||||
uint8_t ExpandedKey[256];
|
|
||||||
size_t i, j;
|
|
||||||
|
|
||||||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
|
||||||
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE);
|
|
||||||
ExpandAESKey256(ExpandedKey);
|
|
||||||
|
|
||||||
__m128i *longoutput, *expkey, *xmminput;
|
|
||||||
longoutput = (__m128i *)memory;
|
|
||||||
expkey = (__m128i *)ExpandedKey;
|
|
||||||
xmminput = (__m128i *)ctx->text;
|
|
||||||
|
|
||||||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE)
|
|
||||||
{
|
|
||||||
for(j = 0; j < 10; j++)
|
|
||||||
{
|
|
||||||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
|
||||||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
|
||||||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
|
||||||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
|
||||||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
|
||||||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
|
||||||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
|
||||||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
|
||||||
}
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4)]), xmminput[0]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 1]), xmminput[1]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 2]), xmminput[2]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 3]), xmminput[3]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 4]), xmminput[4]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 5]), xmminput[5]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 6]), xmminput[6]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 7]), xmminput[7]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 2; i++)
|
|
||||||
{
|
|
||||||
ctx->a[i] = ((uint64_t *)ctx->state.k)[i] ^ ((uint64_t *)ctx->state.k)[i+4];
|
|
||||||
ctx->b[i] = ((uint64_t *)ctx->state.k)[i+2] ^ ((uint64_t *)ctx->state.k)[i+6];
|
|
||||||
}
|
|
||||||
|
|
||||||
__m128i b_x = _mm_load_si128((__m128i *)ctx->b);
|
|
||||||
uint64_t a[2] __attribute((aligned(16))), b[2] __attribute((aligned(16)));
|
|
||||||
a[0] = ctx->a[0];
|
|
||||||
a[1] = ctx->a[1];
|
|
||||||
|
|
||||||
for(i = 0; __builtin_expect(i < 0x80000, 1); i++)
|
|
||||||
{
|
|
||||||
__m128i c_x = _mm_load_si128((__m128i *)&memory[a[0] & 0x1FFFF0]);
|
|
||||||
__m128i a_x = _mm_load_si128((__m128i *)a);
|
|
||||||
uint64_t c[2];
|
|
||||||
c_x = _mm_aesenc_si128(c_x, a_x);
|
|
||||||
|
|
||||||
_mm_store_si128((__m128i *)c, c_x);
|
|
||||||
__builtin_prefetch(&memory[c[0] & 0x1FFFF0], 0, 1);
|
|
||||||
|
|
||||||
b_x = _mm_xor_si128(b_x, c_x);
|
|
||||||
_mm_store_si128((__m128i *)&memory[a[0] & 0x1FFFF0], b_x);
|
|
||||||
|
|
||||||
uint64_t *nextblock = (uint64_t *)&memory[c[0] & 0x1FFFF0];
|
|
||||||
uint64_t b[2];
|
|
||||||
b[0] = nextblock[0];
|
|
||||||
b[1] = nextblock[1];
|
|
||||||
|
|
||||||
{
|
|
||||||
uint64_t hi, lo;
|
|
||||||
// hi,lo = 64bit x 64bit multiply of c[0] and b[0]
|
|
||||||
|
|
||||||
__asm__("mulq %3\n\t"
|
|
||||||
: "=d" (hi),
|
|
||||||
"=a" (lo)
|
|
||||||
: "%a" (c[0]),
|
|
||||||
"rm" (b[0])
|
|
||||||
: "cc" );
|
|
||||||
|
|
||||||
a[0] += hi;
|
|
||||||
a[1] += lo;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t *dst = (uint64_t *) &memory[c[0] & 0x1FFFF0];
|
|
||||||
dst[0] = a[0];
|
|
||||||
dst[1] = a[1];
|
|
||||||
|
|
||||||
a[0] ^= b[0];
|
|
||||||
a[1] ^= b[1];
|
|
||||||
b_x = c_x;
|
|
||||||
__builtin_prefetch(&memory[a[0] & 0x1FFFF0], 0, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
|
||||||
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE);
|
|
||||||
ExpandAESKey256(ExpandedKey);
|
|
||||||
|
|
||||||
//for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE)
|
|
||||||
// aesni_parallel_xor(&ctx->text, ExpandedKey, &ctx->long_state[i]);
|
|
||||||
|
|
||||||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE)
|
|
||||||
{
|
|
||||||
xmminput[0] = _mm_xor_si128(longoutput[(i >> 4)], xmminput[0]);
|
|
||||||
xmminput[1] = _mm_xor_si128(longoutput[(i >> 4) + 1], xmminput[1]);
|
|
||||||
xmminput[2] = _mm_xor_si128(longoutput[(i >> 4) + 2], xmminput[2]);
|
|
||||||
xmminput[3] = _mm_xor_si128(longoutput[(i >> 4) + 3], xmminput[3]);
|
|
||||||
xmminput[4] = _mm_xor_si128(longoutput[(i >> 4) + 4], xmminput[4]);
|
|
||||||
xmminput[5] = _mm_xor_si128(longoutput[(i >> 4) + 5], xmminput[5]);
|
|
||||||
xmminput[6] = _mm_xor_si128(longoutput[(i >> 4) + 6], xmminput[6]);
|
|
||||||
xmminput[7] = _mm_xor_si128(longoutput[(i >> 4) + 7], xmminput[7]);
|
|
||||||
|
|
||||||
for(j = 0; j < 10; j++)
|
|
||||||
{
|
|
||||||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
|
||||||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
|
||||||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
|
||||||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
|
||||||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
|
||||||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
|
||||||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
|
||||||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
|
|
||||||
keccakf((uint64_t *) &ctx->state.hs, 24);
|
|
||||||
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
|
|
||||||
}
|
|
||||||
@@ -1,214 +0,0 @@
|
|||||||
/* XMRig
|
|
||||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
|
||||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
|
||||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
|
||||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
|
||||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <x86intrin.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "cryptonight.h"
|
|
||||||
#include "crypto/c_keccak.h"
|
|
||||||
|
|
||||||
|
|
||||||
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2)
|
|
||||||
{
|
|
||||||
__m128i tmp4;
|
|
||||||
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF);
|
|
||||||
tmp4 = _mm_slli_si128(*tmp1, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, *tmp2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3)
|
|
||||||
{
|
|
||||||
__m128i tmp2, tmp4;
|
|
||||||
|
|
||||||
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00);
|
|
||||||
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA);
|
|
||||||
tmp4 = _mm_slli_si128(*tmp3, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special thanks to Intel for helping me
|
|
||||||
// with ExpandAESKey256() and its subroutines
|
|
||||||
static inline void ExpandAESKey256(char *keybuf)
|
|
||||||
{
|
|
||||||
__m128i tmp1, tmp2, tmp3, *keys;
|
|
||||||
|
|
||||||
keys = (__m128i *)keybuf;
|
|
||||||
|
|
||||||
tmp1 = _mm_load_si128((__m128i *)keybuf);
|
|
||||||
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10));
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[2] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[3] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[4] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[5] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[6] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[7] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[8] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[9] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[10] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[11] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[12] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[13] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[14] = tmp1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cryptonight_av3_aesni_bmi2(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx)
|
|
||||||
{
|
|
||||||
keccak((const uint8_t *) input, 76, (uint8_t *) &ctx->state.hs, 200);
|
|
||||||
uint8_t ExpandedKey[256];
|
|
||||||
size_t i, j;
|
|
||||||
|
|
||||||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
|
||||||
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE);
|
|
||||||
ExpandAESKey256(ExpandedKey);
|
|
||||||
|
|
||||||
__m128i *longoutput, *expkey, *xmminput;
|
|
||||||
longoutput = (__m128i *) memory;
|
|
||||||
expkey = (__m128i *)ExpandedKey;
|
|
||||||
xmminput = (__m128i *)ctx->text;
|
|
||||||
|
|
||||||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE)
|
|
||||||
{
|
|
||||||
for(j = 0; j < 10; j++)
|
|
||||||
{
|
|
||||||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
|
||||||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
|
||||||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
|
||||||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
|
||||||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
|
||||||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
|
||||||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
|
||||||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
|
||||||
}
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4)]), xmminput[0]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 1]), xmminput[1]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 2]), xmminput[2]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 3]), xmminput[3]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 4]), xmminput[4]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 5]), xmminput[5]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 6]), xmminput[6]);
|
|
||||||
_mm_store_si128(&(longoutput[(i >> 4) + 7]), xmminput[7]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 2; i++)
|
|
||||||
{
|
|
||||||
ctx->a[i] = ((uint64_t *)ctx->state.k)[i] ^ ((uint64_t *)ctx->state.k)[i+4];
|
|
||||||
ctx->b[i] = ((uint64_t *)ctx->state.k)[i+2] ^ ((uint64_t *)ctx->state.k)[i+6];
|
|
||||||
}
|
|
||||||
|
|
||||||
__m128i a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
|
||||||
__m128i b_x = _mm_load_si128((__m128i *) ctx->b);
|
|
||||||
|
|
||||||
uint64_t c[2] __attribute((aligned(16)));
|
|
||||||
uint64_t d[2] __attribute((aligned(16)));
|
|
||||||
uint64_t hi;
|
|
||||||
|
|
||||||
for (i = 0; __builtin_expect(i < 0x80000, 1); i++) {
|
|
||||||
__m128i c_x = _mm_aesenc_si128(a_x, _mm_load_si128((__m128i *) ctx->a));
|
|
||||||
_mm_store_si128((__m128i *) c, c_x);
|
|
||||||
|
|
||||||
uint64_t *restrict d_ptr = (uint64_t *) &memory[c[0] & 0x1FFFF0];
|
|
||||||
_mm_store_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0], _mm_xor_si128(b_x, c_x));
|
|
||||||
b_x = c_x;
|
|
||||||
|
|
||||||
d[0] = d_ptr[0];
|
|
||||||
d[1] = d_ptr[1];
|
|
||||||
|
|
||||||
d_ptr[1] = ctx->a[1] += _mulx_u64(c[0], d[0], &hi);
|
|
||||||
d_ptr[0] = ctx->a[0] += hi;
|
|
||||||
|
|
||||||
ctx->a[0] ^= d[0];
|
|
||||||
ctx->a[1] ^= d[1];
|
|
||||||
|
|
||||||
a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
|
||||||
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE);
|
|
||||||
ExpandAESKey256(ExpandedKey);
|
|
||||||
|
|
||||||
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) {
|
|
||||||
xmminput[0] = _mm_xor_si128(longoutput[(i >> 4)], xmminput[0]);
|
|
||||||
xmminput[1] = _mm_xor_si128(longoutput[(i >> 4) + 1], xmminput[1]);
|
|
||||||
xmminput[2] = _mm_xor_si128(longoutput[(i >> 4) + 2], xmminput[2]);
|
|
||||||
xmminput[3] = _mm_xor_si128(longoutput[(i >> 4) + 3], xmminput[3]);
|
|
||||||
xmminput[4] = _mm_xor_si128(longoutput[(i >> 4) + 4], xmminput[4]);
|
|
||||||
xmminput[5] = _mm_xor_si128(longoutput[(i >> 4) + 5], xmminput[5]);
|
|
||||||
xmminput[6] = _mm_xor_si128(longoutput[(i >> 4) + 6], xmminput[6]);
|
|
||||||
xmminput[7] = _mm_xor_si128(longoutput[(i >> 4) + 7], xmminput[7]);
|
|
||||||
|
|
||||||
for(j = 0; j < 10; j++)
|
|
||||||
{
|
|
||||||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
|
||||||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
|
||||||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
|
||||||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
|
||||||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
|
||||||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
|
||||||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
|
||||||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
|
|
||||||
keccakf((uint64_t *) &ctx->state.hs, 24);
|
|
||||||
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
|
|
||||||
}
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
/* XMRig
|
|
||||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
|
||||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
|
||||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
|
||||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
|
||||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <x86intrin.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "cryptonight.h"
|
|
||||||
#include "compat.h"
|
|
||||||
#include "crypto/c_keccak.h"
|
|
||||||
#include "crypto/aesb.h"
|
|
||||||
#include "crypto/oaes_lib.h"
|
|
||||||
|
|
||||||
|
|
||||||
static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
|
|
||||||
// multiplier = ab = a * 2^32 + b
|
|
||||||
// multiplicand = cd = c * 2^32 + d
|
|
||||||
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
|
||||||
uint64_t a = multiplier >> 32;
|
|
||||||
uint64_t b = multiplier & 0xFFFFFFFF;
|
|
||||||
uint64_t c = multiplicand >> 32;
|
|
||||||
uint64_t d = multiplicand & 0xFFFFFFFF;
|
|
||||||
|
|
||||||
//uint64_t ac = a * c;
|
|
||||||
uint64_t ad = a * d;
|
|
||||||
//uint64_t bc = b * c;
|
|
||||||
uint64_t bd = b * d;
|
|
||||||
|
|
||||||
uint64_t adbc = ad + (b * c);
|
|
||||||
uint64_t adbc_carry = adbc < ad ? 1 : 0;
|
|
||||||
|
|
||||||
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
|
||||||
uint64_t product_lo = bd + (adbc << 32);
|
|
||||||
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
|
|
||||||
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
|
|
||||||
|
|
||||||
return product_lo;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void mul_sum_xor_dst(const uint8_t* a, uint8_t* c, uint8_t* dst) {
|
|
||||||
uint64_t hi, lo = mul128(((uint64_t*) a)[0], ((uint64_t*) dst)[0], &hi) + ((uint64_t*) c)[1];
|
|
||||||
hi += ((uint64_t*) c)[0];
|
|
||||||
|
|
||||||
((uint64_t*) c)[0] = ((uint64_t*) dst)[0] ^ hi;
|
|
||||||
((uint64_t*) c)[1] = ((uint64_t*) dst)[1] ^ lo;
|
|
||||||
((uint64_t*) dst)[0] = hi;
|
|
||||||
((uint64_t*) dst)[1] = lo;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void xor_blocks(uint8_t* a, const uint8_t* b) {
|
|
||||||
((uint64_t*) a)[0] ^= ((uint64_t*) b)[0];
|
|
||||||
((uint64_t*) a)[1] ^= ((uint64_t*) b)[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void xor_blocks_dst(const uint8_t* a, const uint8_t* b, uint8_t* dst) {
|
|
||||||
((uint64_t*) dst)[0] = ((uint64_t*) a)[0] ^ ((uint64_t*) b)[0];
|
|
||||||
((uint64_t*) dst)[1] = ((uint64_t*) a)[1] ^ ((uint64_t*) b)[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void cryptonight_av4_legacy(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx) {
|
|
||||||
oaes_ctx *aes_ctx = (oaes_ctx*) oaes_alloc();
|
|
||||||
size_t i, j;
|
|
||||||
keccak((const uint8_t *)input, 76, (uint8_t *) &ctx->state.hs, 200);
|
|
||||||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
|
||||||
|
|
||||||
oaes_key_import_data(aes_ctx, ctx->state.hs.b, AES_KEY_SIZE);
|
|
||||||
|
|
||||||
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) {
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 0], aes_ctx->key->exp_data);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 1], aes_ctx->key->exp_data);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 2], aes_ctx->key->exp_data);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 3], aes_ctx->key->exp_data);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 4], aes_ctx->key->exp_data);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 5], aes_ctx->key->exp_data);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 6], aes_ctx->key->exp_data);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 7], aes_ctx->key->exp_data);
|
|
||||||
memcpy((void *) &memory[i], ctx->text, INIT_SIZE_BYTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
xor_blocks_dst(&ctx->state.k[0], &ctx->state.k[32], (uint8_t*) ctx->a);
|
|
||||||
xor_blocks_dst(&ctx->state.k[16], &ctx->state.k[48], (uint8_t*) ctx->b);
|
|
||||||
|
|
||||||
for (i = 0; likely(i < ITER / 4); ++i) {
|
|
||||||
/* Dependency chain: address -> read value ------+
|
|
||||||
* written value <-+ hard function (AES or MUL) <+
|
|
||||||
* next address <-+
|
|
||||||
*/
|
|
||||||
/* Iteration 1 */
|
|
||||||
j = ctx->a[0] & 0x1FFFF0;
|
|
||||||
aesb_single_round((const uint8_t*) &memory[j], (uint8_t *) ctx->c, (const uint8_t *) ctx->a);
|
|
||||||
xor_blocks_dst((const uint8_t*) ctx->c, (const uint8_t*) ctx->b, (uint8_t*) &memory[j]);
|
|
||||||
/* Iteration 2 */
|
|
||||||
mul_sum_xor_dst((const uint8_t*) ctx->c, (uint8_t*) ctx->a, (uint8_t*) &memory[ctx->c[0] & 0x1FFFF0]);
|
|
||||||
/* Iteration 3 */
|
|
||||||
j = ctx->a[0] & 0x1FFFF0;
|
|
||||||
aesb_single_round(&memory[j], (uint8_t *) ctx->b, (uint8_t *) ctx->a);
|
|
||||||
xor_blocks_dst((const uint8_t*) ctx->b, (const uint8_t*) ctx->c, (uint8_t*) &memory[j]);
|
|
||||||
/* Iteration 4 */
|
|
||||||
mul_sum_xor_dst((const uint8_t*) ctx->b, (uint8_t*) ctx->a, (uint8_t*) &memory[ctx->b[0] & 0x1FFFF0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
|
||||||
oaes_key_import_data(aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE);
|
|
||||||
|
|
||||||
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) {
|
|
||||||
xor_blocks(&ctx->text[0 * AES_BLOCK_SIZE], &memory[i + 0 * AES_BLOCK_SIZE]);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[0 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
|
||||||
xor_blocks(&ctx->text[1 * AES_BLOCK_SIZE], &memory[i + 1 * AES_BLOCK_SIZE]);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[1 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
|
||||||
xor_blocks(&ctx->text[2 * AES_BLOCK_SIZE], &memory[i + 2 * AES_BLOCK_SIZE]);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[2 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
|
||||||
xor_blocks(&ctx->text[3 * AES_BLOCK_SIZE], &memory[i + 3 * AES_BLOCK_SIZE]);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[3 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
|
||||||
xor_blocks(&ctx->text[4 * AES_BLOCK_SIZE], &memory[i + 4 * AES_BLOCK_SIZE]);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[4 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
|
||||||
xor_blocks(&ctx->text[5 * AES_BLOCK_SIZE], &memory[i + 5 * AES_BLOCK_SIZE]);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[5 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
|
||||||
xor_blocks(&ctx->text[6 * AES_BLOCK_SIZE], &memory[i + 6 * AES_BLOCK_SIZE]);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[6 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
|
||||||
xor_blocks(&ctx->text[7 * AES_BLOCK_SIZE], &memory[i + 7 * AES_BLOCK_SIZE]);
|
|
||||||
aesb_pseudo_round_mut(&ctx->text[7 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
|
|
||||||
keccakf((uint64_t *) &ctx->state.hs, 24);
|
|
||||||
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
|
|
||||||
oaes_free((OAES_CTX **) &aes_ctx);
|
|
||||||
}
|
|
||||||
@@ -1,248 +0,0 @@
|
|||||||
/* XMRig
|
|
||||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
|
||||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
|
||||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
|
||||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
|
||||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <x86intrin.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "cryptonight.h"
|
|
||||||
#include "crypto/c_keccak.h"
|
|
||||||
|
|
||||||
|
|
||||||
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2)
|
|
||||||
{
|
|
||||||
__m128i tmp4;
|
|
||||||
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF);
|
|
||||||
tmp4 = _mm_slli_si128(*tmp1, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
|
||||||
*tmp1 = _mm_xor_si128(*tmp1, *tmp2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3)
|
|
||||||
{
|
|
||||||
__m128i tmp2, tmp4;
|
|
||||||
|
|
||||||
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00);
|
|
||||||
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA);
|
|
||||||
tmp4 = _mm_slli_si128(*tmp3, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
|
||||||
*tmp3 = _mm_xor_si128(*tmp3, tmp2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special thanks to Intel for helping me
|
|
||||||
// with ExpandAESKey256() and its subroutines
|
|
||||||
static inline void ExpandAESKey256(char *keybuf)
|
|
||||||
{
|
|
||||||
__m128i tmp1, tmp2, tmp3, *keys;
|
|
||||||
|
|
||||||
keys = (__m128i *)keybuf;
|
|
||||||
|
|
||||||
tmp1 = _mm_load_si128((__m128i *)keybuf);
|
|
||||||
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10));
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[2] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[3] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[4] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[5] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[6] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[7] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[8] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[9] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[10] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[11] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[12] = tmp1;
|
|
||||||
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
|
||||||
keys[13] = tmp3;
|
|
||||||
|
|
||||||
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40);
|
|
||||||
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
|
||||||
keys[14] = tmp1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cryptonight_av5_aesni_experimental(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx)
|
|
||||||
{
|
|
||||||
keccak((const uint8_t *)input, 76, (uint8_t *) &ctx->state.hs, 200);
|
|
||||||
uint8_t ExpandedKey[256];
|
|
||||||
size_t i, j;
|
|
||||||
|
|
||||||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
|
||||||
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE);
|
|
||||||
ExpandAESKey256(ExpandedKey);
|
|
||||||
|
|
||||||
__m128i *longoutput, *expkey, *xmminput;
|
|
||||||
longoutput = (__m128i *) memory;
|
|
||||||
expkey = (__m128i *) ExpandedKey;
|
|
||||||
xmminput = (__m128i *)ctx->text;
|
|
||||||
|
|
||||||
// prefetch expkey, all of xmminput and enough longoutput for 4 loops
|
|
||||||
_mm_prefetch(xmminput, _MM_HINT_T0 );
|
|
||||||
_mm_prefetch(xmminput + 4, _MM_HINT_T0 );
|
|
||||||
|
|
||||||
for (i = 0; i < 64; i += 16) {
|
|
||||||
_mm_prefetch(longoutput + i, _MM_HINT_T0);
|
|
||||||
_mm_prefetch(longoutput + i + 4, _MM_HINT_T0);
|
|
||||||
_mm_prefetch(longoutput + i + 8, _MM_HINT_T0);
|
|
||||||
_mm_prefetch(longoutput + i + 12, _MM_HINT_T0);
|
|
||||||
}
|
|
||||||
|
|
||||||
_mm_prefetch(expkey, _MM_HINT_T0);
|
|
||||||
_mm_prefetch(expkey + 4, _MM_HINT_T0);
|
|
||||||
_mm_prefetch(expkey + 8, _MM_HINT_T0);
|
|
||||||
|
|
||||||
for (i = 0; __builtin_expect(i < MEMORY_M128I, 1); i += INIT_SIZE_M128I) {
|
|
||||||
__builtin_prefetch(longoutput + i + 64, 1, 0);
|
|
||||||
__builtin_prefetch(longoutput + i + 68, 1, 0);
|
|
||||||
|
|
||||||
for(j = 0; j < 10; j++) {
|
|
||||||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
|
||||||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
|
||||||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
|
||||||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
|
||||||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
|
||||||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
|
||||||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
|
||||||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
_mm_store_si128(&(longoutput[i ]), xmminput[0]);
|
|
||||||
_mm_store_si128(&(longoutput[i + 1 ]), xmminput[1]);
|
|
||||||
_mm_store_si128(&(longoutput[i + 2 ]), xmminput[2]);
|
|
||||||
_mm_store_si128(&(longoutput[i + 3 ]), xmminput[3]);
|
|
||||||
_mm_store_si128(&(longoutput[i + 4 ]), xmminput[4]);
|
|
||||||
_mm_store_si128(&(longoutput[i + 5 ]), xmminput[5]);
|
|
||||||
_mm_store_si128(&(longoutput[i + 6 ]), xmminput[6]);
|
|
||||||
_mm_store_si128(&(longoutput[i + 7 ]), xmminput[7]);
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->a[0] = ((uint64_t *) ctx->state.k)[0] ^ ((uint64_t *) ctx->state.k)[4];
|
|
||||||
ctx->b[0] = ((uint64_t *) ctx->state.k)[2] ^ ((uint64_t *) ctx->state.k)[6];
|
|
||||||
ctx->a[1] = ((uint64_t *) ctx->state.k)[1] ^ ((uint64_t *) ctx->state.k)[5];
|
|
||||||
ctx->b[1] = ((uint64_t *) ctx->state.k)[3] ^ ((uint64_t *) ctx->state.k)[7];
|
|
||||||
|
|
||||||
__m128i a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
|
||||||
__m128i b_x = _mm_load_si128((__m128i *) ctx->b);
|
|
||||||
|
|
||||||
uint64_t c[2] __attribute((aligned(16)));
|
|
||||||
uint64_t d[2] __attribute((aligned(16)));
|
|
||||||
|
|
||||||
for (i = 0; __builtin_expect(i < 0x80000, 1); i++) {
|
|
||||||
__m128i c_x = _mm_aesenc_si128(a_x, _mm_load_si128((__m128i *) ctx->a));
|
|
||||||
_mm_store_si128((__m128i *) c, c_x);
|
|
||||||
|
|
||||||
uint64_t *restrict d_ptr = (uint64_t *) &memory[c[0] & 0x1FFFF0];
|
|
||||||
_mm_store_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0], _mm_xor_si128(b_x, c_x));
|
|
||||||
b_x = c_x;
|
|
||||||
|
|
||||||
d[0] = d_ptr[0];
|
|
||||||
d[1] = d_ptr[1];
|
|
||||||
|
|
||||||
{
|
|
||||||
unsigned __int128 res = (unsigned __int128) c[0] * d[0];
|
|
||||||
|
|
||||||
d_ptr[0] = ctx->a[0] += res >> 64;
|
|
||||||
d_ptr[1] = ctx->a[1] += (uint64_t) res;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->a[0] ^= d[0];
|
|
||||||
ctx->a[1] ^= d[1];
|
|
||||||
|
|
||||||
a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
|
||||||
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE);
|
|
||||||
ExpandAESKey256(ExpandedKey);
|
|
||||||
|
|
||||||
_mm_prefetch(xmminput, _MM_HINT_T0 );
|
|
||||||
_mm_prefetch(xmminput + 4, _MM_HINT_T0 );
|
|
||||||
|
|
||||||
for (i = 0; i < 64; i += 16) {
|
|
||||||
_mm_prefetch(longoutput + i, _MM_HINT_T0);
|
|
||||||
_mm_prefetch(longoutput + i + 4, _MM_HINT_T0);
|
|
||||||
_mm_prefetch(longoutput + i + 8, _MM_HINT_T0);
|
|
||||||
_mm_prefetch(longoutput + i + 12, _MM_HINT_T0);
|
|
||||||
}
|
|
||||||
|
|
||||||
_mm_prefetch(expkey, _MM_HINT_T0);
|
|
||||||
_mm_prefetch(expkey + 4, _MM_HINT_T0);
|
|
||||||
_mm_prefetch(expkey + 8, _MM_HINT_T0);
|
|
||||||
|
|
||||||
for (i = 0; __builtin_expect(i < MEMORY_M128I, 1); i += INIT_SIZE_M128I) {
|
|
||||||
_mm_prefetch(longoutput + i + 64, _MM_HINT_T0);
|
|
||||||
_mm_prefetch(longoutput + i + 68, _MM_HINT_T0);
|
|
||||||
|
|
||||||
xmminput[0] = _mm_xor_si128(longoutput[i ], xmminput[0]);
|
|
||||||
xmminput[1] = _mm_xor_si128(longoutput[i + 1], xmminput[1]);
|
|
||||||
xmminput[2] = _mm_xor_si128(longoutput[i + 2], xmminput[2]);
|
|
||||||
xmminput[3] = _mm_xor_si128(longoutput[i + 3], xmminput[3]);
|
|
||||||
xmminput[4] = _mm_xor_si128(longoutput[i + 4], xmminput[4]);
|
|
||||||
xmminput[5] = _mm_xor_si128(longoutput[i + 5], xmminput[5]);
|
|
||||||
xmminput[6] = _mm_xor_si128(longoutput[i + 6], xmminput[6]);
|
|
||||||
xmminput[7] = _mm_xor_si128(longoutput[i + 7], xmminput[7]);
|
|
||||||
|
|
||||||
for(j = 0; j < 10; j++) {
|
|
||||||
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
|
||||||
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
|
||||||
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
|
||||||
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
|
||||||
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
|
||||||
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
|
||||||
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
|
||||||
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
|
|
||||||
keccakf((uint64_t *) &ctx->state.hs, 24);
|
|
||||||
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
|
|
||||||
}
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
/* XMRig
|
|
||||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
|
||||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
|
||||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
|
||||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
|
||||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#ifndef BUILD_TEST
|
|
||||||
# include "xmrig.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "crypto/c_groestl.h"
|
|
||||||
#include "crypto/c_blake256.h"
|
|
||||||
#include "crypto/c_jh.h"
|
|
||||||
#include "crypto/c_skein.h"
|
|
||||||
#include "cryptonight.h"
|
|
||||||
#include "options.h"
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
void cryptonight_av1_aesni(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx);
|
|
||||||
void cryptonight_av2_aesni_wolf(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx);
|
|
||||||
void cryptonight_av3_aesni_bmi2(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx);
|
|
||||||
void cryptonight_av5_aesni_experimental(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx);
|
|
||||||
#elif defined(__i386__)
|
|
||||||
void cryptonight_av1_aesni32(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void cryptonight_av4_legacy(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx);
|
|
||||||
|
|
||||||
void (*cryptonight_hash_ctx)(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx) = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
void cryptonight_init(int variant)
|
|
||||||
{
|
|
||||||
switch (variant) {
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
case XMR_VARIANT_AESNI:
|
|
||||||
cryptonight_hash_ctx = cryptonight_av1_aesni;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XMR_VARIANT_AESNI_WOLF:
|
|
||||||
cryptonight_hash_ctx = cryptonight_av2_aesni_wolf;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XMR_VARIANT_AESNI_BMI2:
|
|
||||||
cryptonight_hash_ctx = cryptonight_av3_aesni_bmi2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XMR_VARIANT_EXPERIMENTAL:
|
|
||||||
cryptonight_hash_ctx = cryptonight_av5_aesni_experimental;
|
|
||||||
break;
|
|
||||||
#elif defined(__i386__)
|
|
||||||
case XMR_VARIANT_AESNI:
|
|
||||||
cryptonight_hash_ctx = cryptonight_av1_aesni32;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case XMR_VARIANT_LEGACY:
|
|
||||||
cryptonight_hash_ctx = cryptonight_av4_legacy;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void do_blake_hash(const void* input, size_t len, char* output) {
|
|
||||||
blake256_hash((uint8_t*)output, input, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void do_groestl_hash(const void* input, size_t len, char* output) {
|
|
||||||
groestl(input, len * 8, (uint8_t*)output);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void do_jh_hash(const void* input, size_t len, char* output) {
|
|
||||||
jh_hash(32 * 8, input, 8 * len, (uint8_t*)output);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void do_skein_hash(const void* input, size_t len, char* output) {
|
|
||||||
skein_hash(8 * 32, input, 8 * len, (uint8_t*)output);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
|
|
||||||
|
|
||||||
|
|
||||||
void cryptonight_hash(void* output, const void* input, size_t len) {
|
|
||||||
uint8_t *memory __attribute((aligned(16))) = (uint8_t *) malloc(MEMORY);
|
|
||||||
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx));
|
|
||||||
|
|
||||||
cryptonight_hash_ctx(output, input, memory, ctx);
|
|
||||||
|
|
||||||
free(memory);
|
|
||||||
free(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef BUILD_TEST
|
|
||||||
int scanhash_cryptonight(int thr_id, uint32_t *hash, uint32_t *restrict pdata, const uint32_t *restrict ptarget, uint32_t max_nonce, unsigned long *restrict hashes_done, const char *restrict memory, struct cryptonight_ctx *persistentctx) {
|
|
||||||
uint32_t *nonceptr = (uint32_t*) (((char*)pdata) + 39);
|
|
||||||
uint32_t n = *nonceptr - 1;
|
|
||||||
const uint32_t first_nonce = n + 1;
|
|
||||||
|
|
||||||
do {
|
|
||||||
*nonceptr = ++n;
|
|
||||||
cryptonight_hash_ctx(hash, pdata, memory, persistentctx);
|
|
||||||
|
|
||||||
if (unlikely(hash[7] < ptarget[7])) {
|
|
||||||
*hashes_done = n - first_nonce + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} while (likely((n <= max_nonce && !work_restart[thr_id].restart)));
|
|
||||||
|
|
||||||
*hashes_done = n - first_nonce + 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
8
cmake/FindUV.cmake
Normal file
8
cmake/FindUV.cmake
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
find_path(UV_INCLUDE_DIR NAMES uv.h)
|
||||||
|
find_library(UV_LIBRARY NAMES uv libuv)
|
||||||
|
|
||||||
|
set(UV_LIBRARIES ${UV_LIBRARY})
|
||||||
|
set(UV_INCLUDE_DIRS ${UV_INCLUDE_DIR})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(UV DEFAULT_MSG UV_LIBRARY UV_INCLUDE_DIR)
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#ifndef __AESB_H__
|
|
||||||
#define __AESB_H__
|
|
||||||
|
|
||||||
void aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey);
|
|
||||||
void aesb_pseudo_round_mut(uint8_t *val, const uint8_t *expandedKey);
|
|
||||||
|
|
||||||
#define fast_aesb_single_round aesb_single_round
|
|
||||||
#define fast_aesb_pseudo_round_mut aesb_pseudo_round_mut
|
|
||||||
|
|
||||||
#endif /* __AESB_H__ */
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "hash-ops.h"
|
|
||||||
#include "c_keccak.h"
|
|
||||||
|
|
||||||
void hash_permutation(union hash_state *state) {
|
|
||||||
keccakf((uint64_t*)state, 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
void hash_process(union hash_state *state, const uint8_t *buf, size_t count) {
|
|
||||||
keccak1600(buf, count, (uint8_t*)state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cn_fast_hash(const void *data, size_t length, char *hash) {
|
|
||||||
union hash_state state;
|
|
||||||
hash_process(&state, data, length);
|
|
||||||
memcpy(hash, &state, HASH_SIZE);
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* ---------------------------------------------------------------------------
|
|
||||||
* OpenAES License
|
|
||||||
* ---------------------------------------------------------------------------
|
|
||||||
* Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.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.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
* ---------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _OAES_CONFIG_H
|
|
||||||
#define _OAES_CONFIG_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//#ifndef OAES_HAVE_ISAAC
|
|
||||||
//#define OAES_HAVE_ISAAC 1
|
|
||||||
//#endif // OAES_HAVE_ISAAC
|
|
||||||
|
|
||||||
//#ifndef OAES_DEBUG
|
|
||||||
//#define OAES_DEBUG 0
|
|
||||||
//#endif // OAES_DEBUG
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // _OAES_CONFIG_H
|
|
||||||
1417
crypto/oaes_lib.c
1417
crypto/oaes_lib.c
File diff suppressed because it is too large
Load Diff
@@ -1,214 +0,0 @@
|
|||||||
/*
|
|
||||||
* ---------------------------------------------------------------------------
|
|
||||||
* OpenAES License
|
|
||||||
* ---------------------------------------------------------------------------
|
|
||||||
* Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.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.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
* ---------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _OAES_LIB_H
|
|
||||||
#define _OAES_LIB_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
# ifdef OAES_SHARED
|
|
||||||
# ifdef oaes_lib_EXPORTS
|
|
||||||
# define OAES_API __declspec(dllexport)
|
|
||||||
# else
|
|
||||||
# define OAES_API __declspec(dllimport)
|
|
||||||
# endif
|
|
||||||
# else
|
|
||||||
# define OAES_API
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# define OAES_API
|
|
||||||
#endif // WIN32
|
|
||||||
|
|
||||||
#define OAES_VERSION "0.8.1"
|
|
||||||
#define OAES_BLOCK_SIZE 16
|
|
||||||
|
|
||||||
typedef void OAES_CTX;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
OAES_RET_FIRST = 0,
|
|
||||||
OAES_RET_SUCCESS = 0,
|
|
||||||
OAES_RET_UNKNOWN,
|
|
||||||
OAES_RET_ARG1,
|
|
||||||
OAES_RET_ARG2,
|
|
||||||
OAES_RET_ARG3,
|
|
||||||
OAES_RET_ARG4,
|
|
||||||
OAES_RET_ARG5,
|
|
||||||
OAES_RET_NOKEY,
|
|
||||||
OAES_RET_MEM,
|
|
||||||
OAES_RET_BUF,
|
|
||||||
OAES_RET_HEADER,
|
|
||||||
OAES_RET_COUNT
|
|
||||||
} OAES_RET;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* oaes_set_option() takes one of these values for its [option] parameter
|
|
||||||
* some options accept either an optional or a required [value] parameter
|
|
||||||
*/
|
|
||||||
// no option
|
|
||||||
#define OAES_OPTION_NONE 0
|
|
||||||
// enable ECB mode, disable CBC mode
|
|
||||||
#define OAES_OPTION_ECB 1
|
|
||||||
// enable CBC mode, disable ECB mode
|
|
||||||
// value is optional, may pass uint8_t iv[OAES_BLOCK_SIZE] to specify
|
|
||||||
// the value of the initialization vector, iv
|
|
||||||
#define OAES_OPTION_CBC 2
|
|
||||||
|
|
||||||
#ifdef OAES_DEBUG
|
|
||||||
typedef int ( * oaes_step_cb ) (
|
|
||||||
const uint8_t state[OAES_BLOCK_SIZE],
|
|
||||||
const char * step_name,
|
|
||||||
int step_count,
|
|
||||||
void * user_data );
|
|
||||||
// enable state stepping mode
|
|
||||||
// value is required, must pass oaes_step_cb to receive the state at each step
|
|
||||||
#define OAES_OPTION_STEP_ON 4
|
|
||||||
// disable state stepping mode
|
|
||||||
#define OAES_OPTION_STEP_OFF 8
|
|
||||||
#endif // OAES_DEBUG
|
|
||||||
|
|
||||||
typedef uint16_t OAES_OPTION;
|
|
||||||
|
|
||||||
typedef struct _oaes_key
|
|
||||||
{
|
|
||||||
size_t data_len;
|
|
||||||
uint8_t *data;
|
|
||||||
size_t exp_data_len;
|
|
||||||
uint8_t *exp_data;
|
|
||||||
size_t num_keys;
|
|
||||||
size_t key_base;
|
|
||||||
} oaes_key;
|
|
||||||
|
|
||||||
typedef struct _oaes_ctx
|
|
||||||
{
|
|
||||||
#ifdef OAES_HAVE_ISAAC
|
|
||||||
randctx * rctx;
|
|
||||||
#endif // OAES_HAVE_ISAAC
|
|
||||||
|
|
||||||
#ifdef OAES_DEBUG
|
|
||||||
oaes_step_cb step_cb;
|
|
||||||
#endif // OAES_DEBUG
|
|
||||||
|
|
||||||
oaes_key * key;
|
|
||||||
OAES_OPTION options;
|
|
||||||
uint8_t iv[OAES_BLOCK_SIZE];
|
|
||||||
} oaes_ctx;
|
|
||||||
/*
|
|
||||||
* // usage:
|
|
||||||
*
|
|
||||||
* OAES_CTX * ctx = oaes_alloc();
|
|
||||||
* .
|
|
||||||
* .
|
|
||||||
* .
|
|
||||||
* {
|
|
||||||
* oaes_gen_key_xxx( ctx );
|
|
||||||
* {
|
|
||||||
* oaes_key_export( ctx, _buf, &_buf_len );
|
|
||||||
* // or
|
|
||||||
* oaes_key_export_data( ctx, _buf, &_buf_len );\
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* // or
|
|
||||||
* {
|
|
||||||
* oaes_key_import( ctx, _buf, _buf_len );
|
|
||||||
* // or
|
|
||||||
* oaes_key_import_data( ctx, _buf, _buf_len );
|
|
||||||
* }
|
|
||||||
* .
|
|
||||||
* .
|
|
||||||
* .
|
|
||||||
* oaes_encrypt( ctx, m, m_len, c, &c_len );
|
|
||||||
* .
|
|
||||||
* .
|
|
||||||
* .
|
|
||||||
* oaes_decrypt( ctx, c, c_len, m, &m_len );
|
|
||||||
* .
|
|
||||||
* .
|
|
||||||
* .
|
|
||||||
* oaes_free( &ctx );
|
|
||||||
*/
|
|
||||||
|
|
||||||
OAES_API OAES_CTX * oaes_alloc(void);
|
|
||||||
|
|
||||||
OAES_API OAES_RET oaes_free( OAES_CTX ** ctx );
|
|
||||||
|
|
||||||
OAES_API OAES_RET oaes_set_option( OAES_CTX * ctx,
|
|
||||||
OAES_OPTION option, const void * value );
|
|
||||||
|
|
||||||
OAES_API OAES_RET oaes_key_gen_128( OAES_CTX * ctx );
|
|
||||||
|
|
||||||
OAES_API OAES_RET oaes_key_gen_192( OAES_CTX * ctx );
|
|
||||||
|
|
||||||
OAES_API OAES_RET oaes_key_gen_256( OAES_CTX * ctx );
|
|
||||||
|
|
||||||
// export key with header information
|
|
||||||
// set data == NULL to get the required data_len
|
|
||||||
OAES_API OAES_RET oaes_key_export( OAES_CTX * ctx,
|
|
||||||
uint8_t * data, size_t * data_len );
|
|
||||||
|
|
||||||
// directly export the data from key
|
|
||||||
// set data == NULL to get the required data_len
|
|
||||||
OAES_API OAES_RET oaes_key_export_data( OAES_CTX * ctx,
|
|
||||||
uint8_t * data, size_t * data_len );
|
|
||||||
|
|
||||||
// import key with header information
|
|
||||||
OAES_API OAES_RET oaes_key_import( OAES_CTX * ctx,
|
|
||||||
const uint8_t * data, size_t data_len );
|
|
||||||
|
|
||||||
// directly import data into key
|
|
||||||
OAES_API OAES_RET oaes_key_import_data( OAES_CTX * ctx,
|
|
||||||
const uint8_t * data, size_t data_len );
|
|
||||||
|
|
||||||
// set c == NULL to get the required c_len
|
|
||||||
OAES_API OAES_RET oaes_encrypt( OAES_CTX * ctx,
|
|
||||||
const uint8_t * m, size_t m_len, uint8_t * c, size_t * c_len );
|
|
||||||
|
|
||||||
// set m == NULL to get the required m_len
|
|
||||||
OAES_API OAES_RET oaes_decrypt( OAES_CTX * ctx,
|
|
||||||
const uint8_t * c, size_t c_len, uint8_t * m, size_t * m_len );
|
|
||||||
|
|
||||||
// set buf == NULL to get the required buf_len
|
|
||||||
OAES_API OAES_RET oaes_sprintf(
|
|
||||||
char * buf, size_t * buf_len, const uint8_t * data, size_t data_len );
|
|
||||||
|
|
||||||
OAES_API OAES_RET oaes_encryption_round( const uint8_t * key, uint8_t * c );
|
|
||||||
|
|
||||||
OAES_API OAES_RET oaes_pseudo_encrypt_ecb( OAES_CTX * ctx, uint8_t * c );
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // _OAES_LIB_H
|
|
||||||
274
elist.h
274
elist.h
@@ -1,274 +0,0 @@
|
|||||||
/* XMRig
|
|
||||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
|
||||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
|
||||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
|
||||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
|
||||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _LINUX_LIST_H
|
|
||||||
#define _LINUX_LIST_H
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Simple doubly linked list implementation.
|
|
||||||
*
|
|
||||||
* Some of the internal functions ("__xxx") are useful when
|
|
||||||
* manipulating whole lists rather than single entries, as
|
|
||||||
* sometimes we already know the next/prev entries and we can
|
|
||||||
* generate better code by using them directly rather than
|
|
||||||
* using the generic single-entry routines.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct list_head {
|
|
||||||
struct list_head *next, *prev;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
|
||||||
|
|
||||||
#define LIST_HEAD(name) \
|
|
||||||
struct list_head name = LIST_HEAD_INIT(name)
|
|
||||||
|
|
||||||
#define INIT_LIST_HEAD(ptr) do { \
|
|
||||||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Insert a new entry between two known consecutive entries.
|
|
||||||
*
|
|
||||||
* This is only for internal list manipulation where we know
|
|
||||||
* the prev/next entries already!
|
|
||||||
*/
|
|
||||||
static inline void __list_add(struct list_head *new,
|
|
||||||
struct list_head *prev,
|
|
||||||
struct list_head *next)
|
|
||||||
{
|
|
||||||
next->prev = new;
|
|
||||||
new->next = next;
|
|
||||||
new->prev = prev;
|
|
||||||
prev->next = new;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_add - add a new entry
|
|
||||||
* @new: new entry to be added
|
|
||||||
* @head: list head to add it after
|
|
||||||
*
|
|
||||||
* Insert a new entry after the specified head.
|
|
||||||
* This is good for implementing stacks.
|
|
||||||
*/
|
|
||||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
|
||||||
{
|
|
||||||
__list_add(new, head, head->next);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_add_tail - add a new entry
|
|
||||||
* @new: new entry to be added
|
|
||||||
* @head: list head to add it before
|
|
||||||
*
|
|
||||||
* Insert a new entry before the specified head.
|
|
||||||
* This is useful for implementing queues.
|
|
||||||
*/
|
|
||||||
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
|
||||||
{
|
|
||||||
__list_add(new, head->prev, head);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Delete a list entry by making the prev/next entries
|
|
||||||
* point to each other.
|
|
||||||
*
|
|
||||||
* This is only for internal list manipulation where we know
|
|
||||||
* the prev/next entries already!
|
|
||||||
*/
|
|
||||||
static inline void __list_del(struct list_head *prev, struct list_head *next)
|
|
||||||
{
|
|
||||||
next->prev = prev;
|
|
||||||
prev->next = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_del - deletes entry from list.
|
|
||||||
* @entry: the element to delete from the list.
|
|
||||||
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
|
|
||||||
*/
|
|
||||||
static inline void list_del(struct list_head *entry)
|
|
||||||
{
|
|
||||||
__list_del(entry->prev, entry->next);
|
|
||||||
entry->next = (void *) 0;
|
|
||||||
entry->prev = (void *) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_del_init - deletes entry from list and reinitialize it.
|
|
||||||
* @entry: the element to delete from the list.
|
|
||||||
*/
|
|
||||||
static inline void list_del_init(struct list_head *entry)
|
|
||||||
{
|
|
||||||
__list_del(entry->prev, entry->next);
|
|
||||||
INIT_LIST_HEAD(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_move - delete from one list and add as another's head
|
|
||||||
* @list: the entry to move
|
|
||||||
* @head: the head that will precede our entry
|
|
||||||
*/
|
|
||||||
static inline void list_move(struct list_head *list, struct list_head *head)
|
|
||||||
{
|
|
||||||
__list_del(list->prev, list->next);
|
|
||||||
list_add(list, head);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_move_tail - delete from one list and add as another's tail
|
|
||||||
* @list: the entry to move
|
|
||||||
* @head: the head that will follow our entry
|
|
||||||
*/
|
|
||||||
static inline void list_move_tail(struct list_head *list,
|
|
||||||
struct list_head *head)
|
|
||||||
{
|
|
||||||
__list_del(list->prev, list->next);
|
|
||||||
list_add_tail(list, head);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_empty - tests whether a list is empty
|
|
||||||
* @head: the list to test.
|
|
||||||
*/
|
|
||||||
static inline int list_empty(struct list_head *head)
|
|
||||||
{
|
|
||||||
return head->next == head;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void __list_splice(struct list_head *list,
|
|
||||||
struct list_head *head)
|
|
||||||
{
|
|
||||||
struct list_head *first = list->next;
|
|
||||||
struct list_head *last = list->prev;
|
|
||||||
struct list_head *at = head->next;
|
|
||||||
|
|
||||||
first->prev = head;
|
|
||||||
head->next = first;
|
|
||||||
|
|
||||||
last->next = at;
|
|
||||||
at->prev = last;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_splice - join two lists
|
|
||||||
* @list: the new list to add.
|
|
||||||
* @head: the place to add it in the first list.
|
|
||||||
*/
|
|
||||||
static inline void list_splice(struct list_head *list, struct list_head *head)
|
|
||||||
{
|
|
||||||
if (!list_empty(list))
|
|
||||||
__list_splice(list, head);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_splice_init - join two lists and reinitialise the emptied list.
|
|
||||||
* @list: the new list to add.
|
|
||||||
* @head: the place to add it in the first list.
|
|
||||||
*
|
|
||||||
* The list at @list is reinitialised
|
|
||||||
*/
|
|
||||||
static inline void list_splice_init(struct list_head *list,
|
|
||||||
struct list_head *head)
|
|
||||||
{
|
|
||||||
if (!list_empty(list)) {
|
|
||||||
__list_splice(list, head);
|
|
||||||
INIT_LIST_HEAD(list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_entry - get the struct for this entry
|
|
||||||
* @ptr: the &struct list_head pointer.
|
|
||||||
* @type: the type of the struct this is embedded in.
|
|
||||||
* @member: the name of the list_struct within the struct.
|
|
||||||
*/
|
|
||||||
#define list_entry(ptr, type, member) \
|
|
||||||
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_for_each - iterate over a list
|
|
||||||
* @pos: the &struct list_head to use as a loop counter.
|
|
||||||
* @head: the head for your list.
|
|
||||||
*/
|
|
||||||
#define list_for_each(pos, head) \
|
|
||||||
for (pos = (head)->next; pos != (head); \
|
|
||||||
pos = pos->next)
|
|
||||||
/**
|
|
||||||
* list_for_each_prev - iterate over a list backwards
|
|
||||||
* @pos: the &struct list_head to use as a loop counter.
|
|
||||||
* @head: the head for your list.
|
|
||||||
*/
|
|
||||||
#define list_for_each_prev(pos, head) \
|
|
||||||
for (pos = (head)->prev; pos != (head); \
|
|
||||||
pos = pos->prev)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_for_each_safe - iterate over a list safe against removal of list entry
|
|
||||||
* @pos: the &struct list_head to use as a loop counter.
|
|
||||||
* @n: another &struct list_head to use as temporary storage
|
|
||||||
* @head: the head for your list.
|
|
||||||
*/
|
|
||||||
#define list_for_each_safe(pos, n, head) \
|
|
||||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
|
||||||
pos = n, n = pos->next)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_for_each_entry - iterate over list of given type
|
|
||||||
* @pos: the type * to use as a loop counter.
|
|
||||||
* @head: the head for your list.
|
|
||||||
* @member: the name of the list_struct within the struct.
|
|
||||||
*/
|
|
||||||
#define list_for_each_entry(pos, head, member) \
|
|
||||||
for (pos = list_entry((head)->next, typeof(*pos), member); \
|
|
||||||
&pos->member != (head); \
|
|
||||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
|
||||||
* @pos: the type * to use as a loop counter.
|
|
||||||
* @n: another type * to use as temporary storage
|
|
||||||
* @head: the head for your list.
|
|
||||||
* @member: the name of the list_struct within the struct.
|
|
||||||
*/
|
|
||||||
#define list_for_each_entry_safe(pos, n, head, member) \
|
|
||||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
|
||||||
n = list_entry(pos->member.next, typeof(*pos), member); \
|
|
||||||
&pos->member != (head); \
|
|
||||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_for_each_entry_continue - iterate over list of given type
|
|
||||||
* continuing after existing point
|
|
||||||
* @pos: the type * to use as a loop counter.
|
|
||||||
* @head: the head for your list.
|
|
||||||
* @member: the name of the list_struct within the struct.
|
|
||||||
*/
|
|
||||||
#define list_for_each_entry_continue(pos, head, member) \
|
|
||||||
for (pos = list_entry(pos->member.next, typeof(*pos), member), \
|
|
||||||
prefetch(pos->member.next); \
|
|
||||||
&pos->member != (head); \
|
|
||||||
pos = list_entry(pos->member.next, typeof(*pos), member), \
|
|
||||||
prefetch(pos->member.next))
|
|
||||||
|
|
||||||
#endif
|
|
||||||
441
options.c
441
options.c
@@ -1,441 +0,0 @@
|
|||||||
/* XMRig
|
|
||||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
|
||||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
|
||||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
|
||||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
|
||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
|
||||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <jansson.h>
|
|
||||||
#include <curl/curl.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
|
|
||||||
#include "version.h"
|
|
||||||
#include "utils/applog.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "donate.h"
|
|
||||||
#include "algo/cryptonight/cryptonight.h"
|
|
||||||
|
|
||||||
|
|
||||||
int64_t opt_affinity = -1L;
|
|
||||||
int opt_n_threads = 0;
|
|
||||||
int opt_algo_variant = 0;
|
|
||||||
int opt_retries = 5;
|
|
||||||
int opt_retry_pause = 5;
|
|
||||||
int opt_donate_level = DONATE_LEVEL;
|
|
||||||
bool opt_colors = true;
|
|
||||||
bool opt_keepalive = false;
|
|
||||||
bool opt_background = false;
|
|
||||||
char *opt_url = NULL;
|
|
||||||
char *opt_backup_url = NULL;
|
|
||||||
char *opt_userpass = NULL;
|
|
||||||
char *opt_user = NULL;
|
|
||||||
char *opt_pass = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
static char const usage[] = "\
|
|
||||||
Usage: " APP_ID " [OPTIONS]\n\
|
|
||||||
Options:\n\
|
|
||||||
-o, --url=URL URL of mining server\n\
|
|
||||||
-b, --backup-url=URL URL of backup mining server\n\
|
|
||||||
-O, --userpass=U:P username:password pair for mining server\n\
|
|
||||||
-u, --user=USERNAME username for mining server\n\
|
|
||||||
-p, --pass=PASSWORD password for mining server\n\
|
|
||||||
-t, --threads=N number of miner threads\n\
|
|
||||||
-v, --av=N algorithm variation, 0 auto select\n\
|
|
||||||
-k, --keepalive send keepalived for prevent timeout (need pool support)\n\
|
|
||||||
-r, --retries=N number of times to retry before switch to backup server (default: 5)\n\
|
|
||||||
-R, --retry-pause=N time to pause between retries (default: 5)\n\
|
|
||||||
--cpu-affinity set process affinity to cpu core(s), mask 0x3 for cores 0 and 1\n\
|
|
||||||
--no-color disable colored output\n\
|
|
||||||
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\
|
|
||||||
-B, --background run the miner in the background\n\
|
|
||||||
-c, --config=FILE load a JSON-format configuration file\n\
|
|
||||||
-h, --help display this help and exit\n\
|
|
||||||
-V, --version output version information and exit\n\
|
|
||||||
";
|
|
||||||
|
|
||||||
|
|
||||||
static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vb:";
|
|
||||||
|
|
||||||
|
|
||||||
static struct option const options[] = {
|
|
||||||
{ "algo", 1, NULL, 'a' },
|
|
||||||
{ "av", 1, NULL, 'v' },
|
|
||||||
{ "background", 0, NULL, 'B' },
|
|
||||||
{ "backup-url", 1, NULL, 'b' },
|
|
||||||
{ "config", 1, NULL, 'c' },
|
|
||||||
{ "cpu-affinity", 1, NULL, 1020 },
|
|
||||||
{ "donate-level", 1, NULL, 1003 },
|
|
||||||
{ "help", 0, NULL, 'h' },
|
|
||||||
{ "keepalive", 0, NULL ,'k' },
|
|
||||||
{ "no-color", 0, NULL, 1002 },
|
|
||||||
{ "pass", 1, NULL, 'p' },
|
|
||||||
{ "retries", 1, NULL, 'r' },
|
|
||||||
{ "retry-pause", 1, NULL, 'R' },
|
|
||||||
{ "threads", 1, NULL, 't' },
|
|
||||||
{ "url", 1, NULL, 'o' },
|
|
||||||
{ "user", 1, NULL, 'u' },
|
|
||||||
{ "userpass", 1, NULL, 'O' },
|
|
||||||
{ "version", 0, NULL, 'V' },
|
|
||||||
{ 0, 0, 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static int get_algo_variant(int variant) {
|
|
||||||
if (variant > XMR_VARIANT_AUTO && variant < XMR_VARIANT_MAX) {
|
|
||||||
return variant;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cpu_info.flags & CPU_FLAG_AES) {
|
|
||||||
if (cpu_info.flags & CPU_FLAG_BMI2) {
|
|
||||||
return XMR_VARIANT_AESNI_BMI2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return XMR_VARIANT_AESNI;
|
|
||||||
}
|
|
||||||
|
|
||||||
return XMR_VARIANT_LEGACY;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void parse_config(json_t *config, char *ref);
|
|
||||||
static char *parse_url(const char *arg);
|
|
||||||
|
|
||||||
|
|
||||||
static void parse_arg(int key, char *arg) {
|
|
||||||
char *p;
|
|
||||||
int v;
|
|
||||||
uint64_t ul;
|
|
||||||
|
|
||||||
switch (key)
|
|
||||||
{
|
|
||||||
case 'a':
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'O': /* --userpass */
|
|
||||||
p = strchr(arg, ':');
|
|
||||||
if (!p) {
|
|
||||||
show_usage_and_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(opt_userpass);
|
|
||||||
opt_userpass = strdup(arg);
|
|
||||||
free(opt_user);
|
|
||||||
opt_user = calloc(p - arg + 1, 1);
|
|
||||||
strncpy(opt_user, arg, p - arg);
|
|
||||||
free(opt_pass);
|
|
||||||
opt_pass = strdup(p + 1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'o': /* --url */
|
|
||||||
p = parse_url(arg);
|
|
||||||
if (p) {
|
|
||||||
free(opt_url);
|
|
||||||
opt_url = p;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'b': /* --backup-url */
|
|
||||||
p = parse_url(arg);
|
|
||||||
if (p) {
|
|
||||||
free(opt_backup_url);
|
|
||||||
opt_backup_url = p;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'u': /* --user */
|
|
||||||
free(opt_user);
|
|
||||||
opt_user = strdup(arg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p': /* --pass */
|
|
||||||
free(opt_pass);
|
|
||||||
opt_pass = strdup(arg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'r': /* --retries */
|
|
||||||
v = atoi(arg);
|
|
||||||
if (v < 1 || v > 1000) {
|
|
||||||
show_usage_and_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
opt_retries = v;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'R': /* --retry-pause */
|
|
||||||
v = atoi(arg);
|
|
||||||
if (v < 1 || v > 3600) {
|
|
||||||
show_usage_and_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
opt_retry_pause = v;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 't': /* --threads */
|
|
||||||
v = atoi(arg);
|
|
||||||
if (v < 1 || v > 1024) {
|
|
||||||
show_usage_and_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
opt_n_threads = v;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'k':
|
|
||||||
opt_keepalive = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'V': /* --version */
|
|
||||||
show_version_and_exit();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'h': /* --help */
|
|
||||||
show_usage_and_exit(0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'c': { /* --config */
|
|
||||||
json_error_t err;
|
|
||||||
json_t *config = json_load_file(arg, 0, &err);
|
|
||||||
|
|
||||||
if (!json_is_object(config)) {
|
|
||||||
if (err.line < 0) {
|
|
||||||
applog(LOG_ERR, "%s\n", err.text);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
applog(LOG_ERR, "%s:%d: %s\n", arg, err.line, err.text);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
parse_config(config, arg);
|
|
||||||
json_decref(config);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'B':
|
|
||||||
opt_background = true;
|
|
||||||
opt_colors = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'v': /* --av */
|
|
||||||
v = atoi(arg);
|
|
||||||
if (v < 0 || v > XMR_VARIANT_MAX) {
|
|
||||||
show_usage_and_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
opt_algo_variant = v;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1020: /* --cpu-affinity */
|
|
||||||
p = strstr(arg, "0x");
|
|
||||||
ul = p ? strtoul(p, NULL, 16) : atol(arg);
|
|
||||||
if (ul > (1UL << cpu_info.count) -1) {
|
|
||||||
ul = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
opt_affinity = ul;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1002: /* --no-color */
|
|
||||||
opt_colors = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1003:
|
|
||||||
v = atoi(arg);
|
|
||||||
if (v < 1 || v > 99) {
|
|
||||||
show_usage_and_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
opt_donate_level = v;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
show_usage_and_exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void parse_config(json_t *config, char *ref)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char buf[16];
|
|
||||||
json_t *val;
|
|
||||||
|
|
||||||
applog(LOG_ERR, ref);
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(options); i++) {
|
|
||||||
if (!options[i].name) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
val = json_object_get(config, options[i].name);
|
|
||||||
if (!val) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options[i].has_arg && json_is_string(val)) {
|
|
||||||
char *s = strdup(json_string_value(val));
|
|
||||||
if (!s) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_arg(options[i].val, s);
|
|
||||||
free(s);
|
|
||||||
}
|
|
||||||
else if (options[i].has_arg && json_is_integer(val)) {
|
|
||||||
sprintf(buf, "%d", (int) json_integer_value(val));
|
|
||||||
parse_arg(options[i].val, buf);
|
|
||||||
}
|
|
||||||
else if (options[i].has_arg && json_is_real(val)) {
|
|
||||||
sprintf(buf, "%f", json_real_value(val));
|
|
||||||
parse_arg(options[i].val, buf);
|
|
||||||
}
|
|
||||||
else if (!options[i].has_arg) {
|
|
||||||
if (json_is_true(val)) {
|
|
||||||
parse_arg(options[i].val, "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
applog(LOG_ERR, "JSON option %s invalid", options[i].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static char *parse_url(const char *arg)
|
|
||||||
{
|
|
||||||
char *p = strstr(arg, "://");
|
|
||||||
if (p) {
|
|
||||||
if (strncasecmp(arg, "stratum+tcp://", 14)) {
|
|
||||||
show_usage_and_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return strdup(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (!strlen(arg) || *arg == '/') {
|
|
||||||
show_usage_and_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *dest = malloc(strlen(arg) + 14);
|
|
||||||
sprintf(dest, "stratum+tcp://%s", arg);
|
|
||||||
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse application command line via getopt.
|
|
||||||
*/
|
|
||||||
void parse_cmdline(int argc, char *argv[]) {
|
|
||||||
opt_user = strdup("x");
|
|
||||||
opt_pass = strdup("x");
|
|
||||||
|
|
||||||
int key;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
key = getopt_long(argc, argv, short_options, options, NULL);
|
|
||||||
if (key < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_arg(key, optarg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optind < argc) {
|
|
||||||
fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]);
|
|
||||||
show_usage_and_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!opt_url) {
|
|
||||||
opt_url = strdup("stratum+tcp://proxy.xmrig.com:443");
|
|
||||||
opt_keepalive = true;
|
|
||||||
|
|
||||||
if (!opt_backup_url) {
|
|
||||||
opt_backup_url = strdup("stratum+tcp://failover.xmrig.com:80");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!opt_userpass) {
|
|
||||||
opt_userpass = malloc(strlen(opt_user) + strlen(opt_pass) + 2);
|
|
||||||
if (!opt_userpass) {
|
|
||||||
proper_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(opt_userpass, "%s:%s", opt_user, opt_pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!opt_n_threads) {
|
|
||||||
opt_n_threads = get_optimal_threads_count();
|
|
||||||
}
|
|
||||||
|
|
||||||
opt_algo_variant = get_algo_variant(opt_algo_variant);
|
|
||||||
if (!opt_algo_variant) {
|
|
||||||
opt_algo_variant = get_algo_variant(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt_donate_level < 1 || opt_donate_level > 99) {
|
|
||||||
opt_donate_level = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cryptonight_init(opt_algo_variant);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void show_usage_and_exit(int status) {
|
|
||||||
if (status) {
|
|
||||||
fprintf(stderr, "Try \"" APP_ID "\" --help' for more information.\n");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
printf(usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
proper_exit(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void show_version_and_exit(void) {
|
|
||||||
printf(APP_NAME " " APP_VERSION "\n built on " __DATE__
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
" with GCC");
|
|
||||||
printf(" %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
printf("\n features:"
|
|
||||||
#ifdef __i386__
|
|
||||||
" i386"
|
|
||||||
#endif
|
|
||||||
#ifdef __x86_64__
|
|
||||||
" x86_64"
|
|
||||||
#endif
|
|
||||||
#ifdef __AES__
|
|
||||||
" AES-NI"
|
|
||||||
#endif
|
|
||||||
"\n");
|
|
||||||
|
|
||||||
printf("\n%s\n", curl_version());
|
|
||||||
#ifdef JANSSON_VERSION
|
|
||||||
printf("libjansson/%s\n", JANSSON_VERSION);
|
|
||||||
#endif
|
|
||||||
proper_exit(0);
|
|
||||||
}
|
|
||||||
BIN
res/app.ico
Normal file
BIN
res/app.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
37
res/app.rc
Normal file
37
res/app.rc
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include "../src/version.h"
|
||||||
|
|
||||||
|
IDI_ICON1 ICON DISCARDABLE "app.ico"
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION APP_VER_MAJOR,APP_VER_MINOR,APP_VER_BUILD,APP_VER_REV
|
||||||
|
PRODUCTVERSION APP_VER_MAJOR,APP_VER_MINOR,APP_VER_BUILD,APP_VER_REV
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS VS_FF_DEBUG
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS VOS__WINDOWS32
|
||||||
|
FILETYPE VFT_APP
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "000004b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", APP_SITE
|
||||||
|
VALUE "FileDescription", APP_DESC
|
||||||
|
VALUE "FileVersion", APP_VERSION
|
||||||
|
VALUE "LegalCopyright", APP_COPYRIGHT
|
||||||
|
VALUE "OriginalFilename", "xmrig.exe"
|
||||||
|
VALUE "ProductName", APP_NAME
|
||||||
|
VALUE "ProductVersion", APP_VERSION
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x0, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
21
memory.c → src/3rdparty/align.h
vendored
21
memory.c → src/3rdparty/align.h
vendored
@@ -21,18 +21,13 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#ifndef __ALIGN_H__
|
||||||
|
#define __ALIGN_H__
|
||||||
|
|
||||||
#include "persistent_memory.h"
|
#ifdef _MSC_VER
|
||||||
|
# define VAR_ALIGN(x, decl) __declspec(align(x)) decl
|
||||||
|
#else
|
||||||
|
# define VAR_ALIGN(x, decl) decl __attribute__ ((aligned(x)))
|
||||||
|
#endif
|
||||||
|
|
||||||
static size_t offset = 0;
|
#endif /* __ALIGN_H__ */
|
||||||
|
|
||||||
|
|
||||||
void * persistent_calloc(size_t num, size_t size) {
|
|
||||||
void *mem = &persistent_memory[offset];
|
|
||||||
offset += (num * size);
|
|
||||||
|
|
||||||
memset(mem, 0, num * size);
|
|
||||||
|
|
||||||
return mem;
|
|
||||||
}
|
|
||||||
653
src/3rdparty/getopt/getopt.h
vendored
Normal file
653
src/3rdparty/getopt/getopt.h
vendored
Normal file
@@ -0,0 +1,653 @@
|
|||||||
|
#ifndef __GETOPT_H__
|
||||||
|
/**
|
||||||
|
* DISCLAIMER
|
||||||
|
* This file is part of the mingw-w64 runtime package.
|
||||||
|
*
|
||||||
|
* The mingw-w64 runtime package and its code is distributed in the hope that it
|
||||||
|
* will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
|
||||||
|
* IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
|
||||||
|
* warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* Sponsored in part by the Defense Advanced Research Projects
|
||||||
|
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||||
|
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||||
|
*/
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Dieter Baron and Thomas Klausner.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 warning(disable:4996);
|
||||||
|
|
||||||
|
#define __GETOPT_H__
|
||||||
|
|
||||||
|
/* All the headers include this file. */
|
||||||
|
#include <crtdefs.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
|
||||||
|
|
||||||
|
#ifdef REPLACE_GETOPT
|
||||||
|
int opterr = 1; /* if error message should be printed */
|
||||||
|
int optind = 1; /* index into parent argv vector */
|
||||||
|
int optopt = '?'; /* character checked for validity */
|
||||||
|
#undef optreset /* see getopt.h */
|
||||||
|
#define optreset __mingw_optreset
|
||||||
|
int optreset; /* reset getopt */
|
||||||
|
char *optarg; /* argument associated with option */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//extern int optind; /* index of first non-option in argv */
|
||||||
|
//extern int optopt; /* single option character, as parsed */
|
||||||
|
//extern int opterr; /* flag to enable built-in diagnostics... */
|
||||||
|
// /* (user may set to zero, to suppress) */
|
||||||
|
//
|
||||||
|
//extern char *optarg; /* pointer to argument of current option */
|
||||||
|
|
||||||
|
#define PRINT_ERROR ((opterr) && (*options != ':'))
|
||||||
|
|
||||||
|
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
|
||||||
|
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
|
||||||
|
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
|
||||||
|
|
||||||
|
/* return values */
|
||||||
|
#define BADCH (int)'?'
|
||||||
|
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
|
||||||
|
#define INORDER (int)1
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
#define __progname __argv[0]
|
||||||
|
#else
|
||||||
|
extern char __declspec(dllimport) *__progname;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
static char EMSG[] = "";
|
||||||
|
#else
|
||||||
|
#define EMSG ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int getopt_internal(int, char * const *, const char *,
|
||||||
|
const struct option *, int *, int);
|
||||||
|
static int parse_long_options(char * const *, const char *,
|
||||||
|
const struct option *, int *, int);
|
||||||
|
static int gcd(int, int);
|
||||||
|
static void permute_args(int, int, int, char * const *);
|
||||||
|
|
||||||
|
static char *place = EMSG; /* option letter processing */
|
||||||
|
|
||||||
|
/* XXX: set optreset to 1 rather than these two */
|
||||||
|
static int nonopt_start = -1; /* first non option argument (for permute) */
|
||||||
|
static int nonopt_end = -1; /* first option after non options (for permute) */
|
||||||
|
|
||||||
|
/* Error messages */
|
||||||
|
static const char recargchar[] = "option requires an argument -- %c";
|
||||||
|
static const char recargstring[] = "option requires an argument -- %s";
|
||||||
|
static const char ambig[] = "ambiguous option -- %.*s";
|
||||||
|
static const char noarg[] = "option doesn't take an argument -- %.*s";
|
||||||
|
static const char illoptchar[] = "unknown option -- %c";
|
||||||
|
static const char illoptstring[] = "unknown option -- %s";
|
||||||
|
|
||||||
|
static void
|
||||||
|
_vwarnx(const char *fmt,va_list ap)
|
||||||
|
{
|
||||||
|
(void)fprintf(stderr,"%s: ",__progname);
|
||||||
|
if (fmt != NULL)
|
||||||
|
(void)vfprintf(stderr,fmt,ap);
|
||||||
|
(void)fprintf(stderr,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
warnx(const char *fmt,...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,fmt);
|
||||||
|
_vwarnx(fmt,ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute the greatest common divisor of a and b.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
gcd(int a, int b)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
c = a % b;
|
||||||
|
while (c != 0) {
|
||||||
|
a = b;
|
||||||
|
b = c;
|
||||||
|
c = a % b;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exchange the block from nonopt_start to nonopt_end with the block
|
||||||
|
* from nonopt_end to opt_end (keeping the same order of arguments
|
||||||
|
* in each block).
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
permute_args(int panonopt_start, int panonopt_end, int opt_end,
|
||||||
|
char * const *nargv)
|
||||||
|
{
|
||||||
|
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
|
||||||
|
char *swap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* compute lengths of blocks and number and size of cycles
|
||||||
|
*/
|
||||||
|
nnonopts = panonopt_end - panonopt_start;
|
||||||
|
nopts = opt_end - panonopt_end;
|
||||||
|
ncycle = gcd(nnonopts, nopts);
|
||||||
|
cyclelen = (opt_end - panonopt_start) / ncycle;
|
||||||
|
|
||||||
|
for (i = 0; i < ncycle; i++) {
|
||||||
|
cstart = panonopt_end+i;
|
||||||
|
pos = cstart;
|
||||||
|
for (j = 0; j < cyclelen; j++) {
|
||||||
|
if (pos >= panonopt_end)
|
||||||
|
pos -= nnonopts;
|
||||||
|
else
|
||||||
|
pos += nopts;
|
||||||
|
swap = nargv[pos];
|
||||||
|
/* LINTED const cast */
|
||||||
|
((char **) nargv)[pos] = nargv[cstart];
|
||||||
|
/* LINTED const cast */
|
||||||
|
((char **)nargv)[cstart] = swap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef REPLACE_GETOPT
|
||||||
|
/*
|
||||||
|
* getopt --
|
||||||
|
* Parse argc/argv argument vector.
|
||||||
|
*
|
||||||
|
* [eventually this will replace the BSD getopt]
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
getopt(int nargc, char * const *nargv, const char *options)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't pass FLAG_PERMUTE to getopt_internal() since
|
||||||
|
* the BSD getopt(3) (unlike GNU) has never done this.
|
||||||
|
*
|
||||||
|
* Furthermore, since many privileged programs call getopt()
|
||||||
|
* before dropping privileges it makes sense to keep things
|
||||||
|
* as simple (and bug-free) as possible.
|
||||||
|
*/
|
||||||
|
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
|
||||||
|
}
|
||||||
|
#endif /* REPLACE_GETOPT */
|
||||||
|
|
||||||
|
//extern int getopt(int nargc, char * const *nargv, const char *options);
|
||||||
|
|
||||||
|
#ifdef _BSD_SOURCE
|
||||||
|
/*
|
||||||
|
* BSD adds the non-standard `optreset' feature, for reinitialisation
|
||||||
|
* of `getopt' parsing. We support this feature, for applications which
|
||||||
|
* proclaim their BSD heritage, before including this header; however,
|
||||||
|
* to maintain portability, developers are advised to avoid it.
|
||||||
|
*/
|
||||||
|
# define optreset __mingw_optreset
|
||||||
|
extern int optreset;
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* POSIX requires the `getopt' API to be specified in `unistd.h';
|
||||||
|
* thus, `unistd.h' includes this header. However, we do not want
|
||||||
|
* to expose the `getopt_long' or `getopt_long_only' APIs, when
|
||||||
|
* included in this manner. Thus, close the standard __GETOPT_H__
|
||||||
|
* declarations block, and open an additional __GETOPT_LONG_H__
|
||||||
|
* specific block, only when *not* __UNISTD_H_SOURCED__, in which
|
||||||
|
* to declare the extended API.
|
||||||
|
*/
|
||||||
|
#endif /* !defined(__GETOPT_H__) */
|
||||||
|
|
||||||
|
#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
|
||||||
|
#define __GETOPT_LONG_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct option /* specification for a long form option... */
|
||||||
|
{
|
||||||
|
const char *name; /* option name, without leading hyphens */
|
||||||
|
int has_arg; /* does it take an argument? */
|
||||||
|
int *flag; /* where to save its status, or NULL */
|
||||||
|
int val; /* its associated status value */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum /* permitted values for its `has_arg' field... */
|
||||||
|
{
|
||||||
|
no_argument = 0, /* option never takes an argument */
|
||||||
|
required_argument, /* option always requires an argument */
|
||||||
|
optional_argument /* option may take an argument */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* parse_long_options --
|
||||||
|
* Parse long options in argc/argv argument vector.
|
||||||
|
* Returns -1 if short_too is set and the option does not match long_options.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
parse_long_options(char * const *nargv, const char *options,
|
||||||
|
const struct option *long_options, int *idx, int short_too)
|
||||||
|
{
|
||||||
|
char *current_argv, *has_equal;
|
||||||
|
size_t current_argv_len;
|
||||||
|
int i, ambiguous, match;
|
||||||
|
|
||||||
|
#define IDENTICAL_INTERPRETATION(_x, _y) \
|
||||||
|
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
|
||||||
|
long_options[(_x)].flag == long_options[(_y)].flag && \
|
||||||
|
long_options[(_x)].val == long_options[(_y)].val)
|
||||||
|
|
||||||
|
current_argv = place;
|
||||||
|
match = -1;
|
||||||
|
ambiguous = 0;
|
||||||
|
|
||||||
|
optind++;
|
||||||
|
|
||||||
|
if ((has_equal = strchr(current_argv, '=')) != NULL) {
|
||||||
|
/* argument found (--option=arg) */
|
||||||
|
current_argv_len = has_equal - current_argv;
|
||||||
|
has_equal++;
|
||||||
|
} else
|
||||||
|
current_argv_len = strlen(current_argv);
|
||||||
|
|
||||||
|
for (i = 0; long_options[i].name; i++) {
|
||||||
|
/* find matching long option */
|
||||||
|
if (strncmp(current_argv, long_options[i].name,
|
||||||
|
current_argv_len))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strlen(long_options[i].name) == current_argv_len) {
|
||||||
|
/* exact match */
|
||||||
|
match = i;
|
||||||
|
ambiguous = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If this is a known short option, don't allow
|
||||||
|
* a partial match of a single character.
|
||||||
|
*/
|
||||||
|
if (short_too && current_argv_len == 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (match == -1) /* partial match */
|
||||||
|
match = i;
|
||||||
|
else if (!IDENTICAL_INTERPRETATION(i, match))
|
||||||
|
ambiguous = 1;
|
||||||
|
}
|
||||||
|
if (ambiguous) {
|
||||||
|
/* ambiguous abbreviation */
|
||||||
|
if (PRINT_ERROR)
|
||||||
|
warnx(ambig, (int)current_argv_len,
|
||||||
|
current_argv);
|
||||||
|
optopt = 0;
|
||||||
|
return (BADCH);
|
||||||
|
}
|
||||||
|
if (match != -1) { /* option found */
|
||||||
|
if (long_options[match].has_arg == no_argument
|
||||||
|
&& has_equal) {
|
||||||
|
if (PRINT_ERROR)
|
||||||
|
warnx(noarg, (int)current_argv_len,
|
||||||
|
current_argv);
|
||||||
|
/*
|
||||||
|
* XXX: GNU sets optopt to val regardless of flag
|
||||||
|
*/
|
||||||
|
if (long_options[match].flag == NULL)
|
||||||
|
optopt = long_options[match].val;
|
||||||
|
else
|
||||||
|
optopt = 0;
|
||||||
|
return (BADARG);
|
||||||
|
}
|
||||||
|
if (long_options[match].has_arg == required_argument ||
|
||||||
|
long_options[match].has_arg == optional_argument) {
|
||||||
|
if (has_equal)
|
||||||
|
optarg = has_equal;
|
||||||
|
else if (long_options[match].has_arg ==
|
||||||
|
required_argument) {
|
||||||
|
/*
|
||||||
|
* optional argument doesn't use next nargv
|
||||||
|
*/
|
||||||
|
optarg = nargv[optind++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((long_options[match].has_arg == required_argument)
|
||||||
|
&& (optarg == NULL)) {
|
||||||
|
/*
|
||||||
|
* Missing argument; leading ':' indicates no error
|
||||||
|
* should be generated.
|
||||||
|
*/
|
||||||
|
if (PRINT_ERROR)
|
||||||
|
warnx(recargstring,
|
||||||
|
current_argv);
|
||||||
|
/*
|
||||||
|
* XXX: GNU sets optopt to val regardless of flag
|
||||||
|
*/
|
||||||
|
if (long_options[match].flag == NULL)
|
||||||
|
optopt = long_options[match].val;
|
||||||
|
else
|
||||||
|
optopt = 0;
|
||||||
|
--optind;
|
||||||
|
return (BADARG);
|
||||||
|
}
|
||||||
|
} else { /* unknown option */
|
||||||
|
if (short_too) {
|
||||||
|
--optind;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (PRINT_ERROR)
|
||||||
|
warnx(illoptstring, current_argv);
|
||||||
|
optopt = 0;
|
||||||
|
return (BADCH);
|
||||||
|
}
|
||||||
|
if (idx)
|
||||||
|
*idx = match;
|
||||||
|
if (long_options[match].flag) {
|
||||||
|
*long_options[match].flag = long_options[match].val;
|
||||||
|
return (0);
|
||||||
|
} else
|
||||||
|
return (long_options[match].val);
|
||||||
|
#undef IDENTICAL_INTERPRETATION
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getopt_internal --
|
||||||
|
* Parse argc/argv argument vector. Called by user level routines.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
getopt_internal(int nargc, char * const *nargv, const char *options,
|
||||||
|
const struct option *long_options, int *idx, int flags)
|
||||||
|
{
|
||||||
|
char *oli; /* option letter list index */
|
||||||
|
int optchar, short_too;
|
||||||
|
static int posixly_correct = -1;
|
||||||
|
|
||||||
|
if (options == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX Some GNU programs (like cvs) set optind to 0 instead of
|
||||||
|
* XXX using optreset. Work around this braindamage.
|
||||||
|
*/
|
||||||
|
if (optind == 0)
|
||||||
|
optind = optreset = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable GNU extensions if POSIXLY_CORRECT is set or options
|
||||||
|
* string begins with a '+'.
|
||||||
|
*
|
||||||
|
* CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
|
||||||
|
* optreset != 0 for GNU compatibility.
|
||||||
|
*/
|
||||||
|
if (posixly_correct == -1 || optreset != 0)
|
||||||
|
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
|
||||||
|
if (*options == '-')
|
||||||
|
flags |= FLAG_ALLARGS;
|
||||||
|
else if (posixly_correct || *options == '+')
|
||||||
|
flags &= ~FLAG_PERMUTE;
|
||||||
|
if (*options == '+' || *options == '-')
|
||||||
|
options++;
|
||||||
|
|
||||||
|
optarg = NULL;
|
||||||
|
if (optreset)
|
||||||
|
nonopt_start = nonopt_end = -1;
|
||||||
|
start:
|
||||||
|
if (optreset || !*place) { /* update scanning pointer */
|
||||||
|
optreset = 0;
|
||||||
|
if (optind >= nargc) { /* end of argument vector */
|
||||||
|
place = EMSG;
|
||||||
|
if (nonopt_end != -1) {
|
||||||
|
/* do permutation, if we have to */
|
||||||
|
permute_args(nonopt_start, nonopt_end,
|
||||||
|
optind, nargv);
|
||||||
|
optind -= nonopt_end - nonopt_start;
|
||||||
|
}
|
||||||
|
else if (nonopt_start != -1) {
|
||||||
|
/*
|
||||||
|
* If we skipped non-options, set optind
|
||||||
|
* to the first of them.
|
||||||
|
*/
|
||||||
|
optind = nonopt_start;
|
||||||
|
}
|
||||||
|
nonopt_start = nonopt_end = -1;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (*(place = nargv[optind]) != '-' ||
|
||||||
|
(place[1] == '\0' && strchr(options, '-') == NULL)) {
|
||||||
|
place = EMSG; /* found non-option */
|
||||||
|
if (flags & FLAG_ALLARGS) {
|
||||||
|
/*
|
||||||
|
* GNU extension:
|
||||||
|
* return non-option as argument to option 1
|
||||||
|
*/
|
||||||
|
optarg = nargv[optind++];
|
||||||
|
return (INORDER);
|
||||||
|
}
|
||||||
|
if (!(flags & FLAG_PERMUTE)) {
|
||||||
|
/*
|
||||||
|
* If no permutation wanted, stop parsing
|
||||||
|
* at first non-option.
|
||||||
|
*/
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
/* do permutation */
|
||||||
|
if (nonopt_start == -1)
|
||||||
|
nonopt_start = optind;
|
||||||
|
else if (nonopt_end != -1) {
|
||||||
|
permute_args(nonopt_start, nonopt_end,
|
||||||
|
optind, nargv);
|
||||||
|
nonopt_start = optind -
|
||||||
|
(nonopt_end - nonopt_start);
|
||||||
|
nonopt_end = -1;
|
||||||
|
}
|
||||||
|
optind++;
|
||||||
|
/* process next argument */
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
|
if (nonopt_start != -1 && nonopt_end == -1)
|
||||||
|
nonopt_end = optind;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we have "-" do nothing, if "--" we are done.
|
||||||
|
*/
|
||||||
|
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
|
||||||
|
optind++;
|
||||||
|
place = EMSG;
|
||||||
|
/*
|
||||||
|
* We found an option (--), so if we skipped
|
||||||
|
* non-options, we have to permute.
|
||||||
|
*/
|
||||||
|
if (nonopt_end != -1) {
|
||||||
|
permute_args(nonopt_start, nonopt_end,
|
||||||
|
optind, nargv);
|
||||||
|
optind -= nonopt_end - nonopt_start;
|
||||||
|
}
|
||||||
|
nonopt_start = nonopt_end = -1;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check long options if:
|
||||||
|
* 1) we were passed some
|
||||||
|
* 2) the arg is not just "-"
|
||||||
|
* 3) either the arg starts with -- we are getopt_long_only()
|
||||||
|
*/
|
||||||
|
if (long_options != NULL && place != nargv[optind] &&
|
||||||
|
(*place == '-' || (flags & FLAG_LONGONLY))) {
|
||||||
|
short_too = 0;
|
||||||
|
if (*place == '-')
|
||||||
|
place++; /* --foo long option */
|
||||||
|
else if (*place != ':' && strchr(options, *place) != NULL)
|
||||||
|
short_too = 1; /* could be short option too */
|
||||||
|
|
||||||
|
optchar = parse_long_options(nargv, options, long_options,
|
||||||
|
idx, short_too);
|
||||||
|
if (optchar != -1) {
|
||||||
|
place = EMSG;
|
||||||
|
return (optchar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((optchar = (int)*place++) == (int)':' ||
|
||||||
|
(optchar == (int)'-' && *place != '\0') ||
|
||||||
|
(oli = (char*)strchr(options, optchar)) == NULL) {
|
||||||
|
/*
|
||||||
|
* If the user specified "-" and '-' isn't listed in
|
||||||
|
* options, return -1 (non-option) as per POSIX.
|
||||||
|
* Otherwise, it is an unknown option character (or ':').
|
||||||
|
*/
|
||||||
|
if (optchar == (int)'-' && *place == '\0')
|
||||||
|
return (-1);
|
||||||
|
if (!*place)
|
||||||
|
++optind;
|
||||||
|
if (PRINT_ERROR)
|
||||||
|
warnx(illoptchar, optchar);
|
||||||
|
optopt = optchar;
|
||||||
|
return (BADCH);
|
||||||
|
}
|
||||||
|
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
|
||||||
|
/* -W long-option */
|
||||||
|
if (*place) /* no space */
|
||||||
|
/* NOTHING */;
|
||||||
|
else if (++optind >= nargc) { /* no arg */
|
||||||
|
place = EMSG;
|
||||||
|
if (PRINT_ERROR)
|
||||||
|
warnx(recargchar, optchar);
|
||||||
|
optopt = optchar;
|
||||||
|
return (BADARG);
|
||||||
|
} else /* white space */
|
||||||
|
place = nargv[optind];
|
||||||
|
optchar = parse_long_options(nargv, options, long_options,
|
||||||
|
idx, 0);
|
||||||
|
place = EMSG;
|
||||||
|
return (optchar);
|
||||||
|
}
|
||||||
|
if (*++oli != ':') { /* doesn't take argument */
|
||||||
|
if (!*place)
|
||||||
|
++optind;
|
||||||
|
} else { /* takes (optional) argument */
|
||||||
|
optarg = NULL;
|
||||||
|
if (*place) /* no white space */
|
||||||
|
optarg = place;
|
||||||
|
else if (oli[1] != ':') { /* arg not optional */
|
||||||
|
if (++optind >= nargc) { /* no arg */
|
||||||
|
place = EMSG;
|
||||||
|
if (PRINT_ERROR)
|
||||||
|
warnx(recargchar, optchar);
|
||||||
|
optopt = optchar;
|
||||||
|
return (BADARG);
|
||||||
|
} else
|
||||||
|
optarg = nargv[optind];
|
||||||
|
}
|
||||||
|
place = EMSG;
|
||||||
|
++optind;
|
||||||
|
}
|
||||||
|
/* dump back option letter */
|
||||||
|
return (optchar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getopt_long --
|
||||||
|
* Parse argc/argv argument vector.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
getopt_long(int nargc, char * const *nargv, const char *options,
|
||||||
|
const struct option *long_options, int *idx)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (getopt_internal(nargc, nargv, options, long_options, idx,
|
||||||
|
FLAG_PERMUTE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getopt_long_only --
|
||||||
|
* Parse argc/argv argument vector.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
getopt_long_only(int nargc, char * const *nargv, const char *options,
|
||||||
|
const struct option *long_options, int *idx)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (getopt_internal(nargc, nargv, options, long_options, idx,
|
||||||
|
FLAG_PERMUTE|FLAG_LONGONLY));
|
||||||
|
}
|
||||||
|
|
||||||
|
//extern int getopt_long(int nargc, char * const *nargv, const char *options,
|
||||||
|
// const struct option *long_options, int *idx);
|
||||||
|
//extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
|
||||||
|
// const struct option *long_options, int *idx);
|
||||||
|
/*
|
||||||
|
* Previous MinGW implementation had...
|
||||||
|
*/
|
||||||
|
#ifndef HAVE_DECL_GETOPT
|
||||||
|
/*
|
||||||
|
* ...for the long form API only; keep this for compatibility.
|
||||||
|
*/
|
||||||
|
# define HAVE_DECL_GETOPT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */
|
||||||
@@ -6,6 +6,8 @@ add_definitions(-DHAVE_CONFIG_H)
|
|||||||
# Add the lib sources.
|
# Add the lib sources.
|
||||||
file(GLOB JANSSON_SRC *.c)
|
file(GLOB JANSSON_SRC *.c)
|
||||||
|
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Os")
|
||||||
|
|
||||||
set(JANSSON_HDR_PRIVATE
|
set(JANSSON_HDR_PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/hashtable.h
|
${CMAKE_CURRENT_SOURCE_DIR}/hashtable.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/jansson_private.h
|
${CMAKE_CURRENT_SOURCE_DIR}/jansson_private.h
|
||||||
@@ -9,13 +9,17 @@
|
|||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "jansson_private.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "jansson.h"
|
#include "jansson.h"
|
||||||
#include "jansson_private.h"
|
|
||||||
#include "strbuffer.h"
|
#include "strbuffer.h"
|
||||||
#include "utf.h"
|
#include "utf.h"
|
||||||
|
|
||||||
@@ -25,11 +29,28 @@
|
|||||||
#define FLAGS_TO_INDENT(f) ((f) & 0x1F)
|
#define FLAGS_TO_INDENT(f) ((f) & 0x1F)
|
||||||
#define FLAGS_TO_PRECISION(f) (((f) >> 11) & 0x1F)
|
#define FLAGS_TO_PRECISION(f) (((f) >> 11) & 0x1F)
|
||||||
|
|
||||||
|
struct buffer {
|
||||||
|
const size_t size;
|
||||||
|
size_t used;
|
||||||
|
char *data;
|
||||||
|
};
|
||||||
|
|
||||||
static int dump_to_strbuffer(const char *buffer, size_t size, void *data)
|
static int dump_to_strbuffer(const char *buffer, size_t size, void *data)
|
||||||
{
|
{
|
||||||
return strbuffer_append_bytes((strbuffer_t *)data, buffer, size);
|
return strbuffer_append_bytes((strbuffer_t *)data, buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dump_to_buffer(const char *buffer, size_t size, void *data)
|
||||||
|
{
|
||||||
|
struct buffer *buf = (struct buffer *)data;
|
||||||
|
|
||||||
|
if(buf->used + size <= buf->size)
|
||||||
|
memcpy(&buf->data[buf->used], buffer, size);
|
||||||
|
|
||||||
|
buf->used += size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int dump_to_file(const char *buffer, size_t size, void *data)
|
static int dump_to_file(const char *buffer, size_t size, void *data)
|
||||||
{
|
{
|
||||||
FILE *dest = (FILE *)data;
|
FILE *dest = (FILE *)data;
|
||||||
@@ -38,6 +59,16 @@ static int dump_to_file(const char *buffer, size_t size, void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dump_to_fd(const char *buffer, size_t size, void *data)
|
||||||
|
{
|
||||||
|
int *dest = (int *)data;
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
if(write(*dest, buffer, size) == (ssize_t)size)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* 32 spaces (the maximum indentation size) */
|
/* 32 spaces (the maximum indentation size) */
|
||||||
static const char whitespace[] = " ";
|
static const char whitespace[] = " ";
|
||||||
|
|
||||||
@@ -168,6 +199,10 @@ static int compare_keys(const void *key1, const void *key2)
|
|||||||
static int do_dump(const json_t *json, size_t flags, int depth,
|
static int do_dump(const json_t *json, size_t flags, int depth,
|
||||||
json_dump_callback_t dump, void *data)
|
json_dump_callback_t dump, void *data)
|
||||||
{
|
{
|
||||||
|
int embed = flags & JSON_EMBED;
|
||||||
|
|
||||||
|
flags &= ~JSON_EMBED;
|
||||||
|
|
||||||
if(!json)
|
if(!json)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -227,11 +262,11 @@ static int do_dump(const json_t *json, size_t flags, int depth,
|
|||||||
|
|
||||||
n = json_array_size(json);
|
n = json_array_size(json);
|
||||||
|
|
||||||
if(dump("[", 1, data))
|
if(!embed && dump("[", 1, data))
|
||||||
goto array_error;
|
goto array_error;
|
||||||
if(n == 0) {
|
if(n == 0) {
|
||||||
array->visited = 0;
|
array->visited = 0;
|
||||||
return dump("]", 1, data);
|
return embed ? 0 : dump("]", 1, data);
|
||||||
}
|
}
|
||||||
if(dump_indent(flags, depth + 1, 0, dump, data))
|
if(dump_indent(flags, depth + 1, 0, dump, data))
|
||||||
goto array_error;
|
goto array_error;
|
||||||
@@ -255,7 +290,7 @@ static int do_dump(const json_t *json, size_t flags, int depth,
|
|||||||
}
|
}
|
||||||
|
|
||||||
array->visited = 0;
|
array->visited = 0;
|
||||||
return dump("]", 1, data);
|
return embed ? 0 : dump("]", 1, data);
|
||||||
|
|
||||||
array_error:
|
array_error:
|
||||||
array->visited = 0;
|
array->visited = 0;
|
||||||
@@ -286,11 +321,11 @@ static int do_dump(const json_t *json, size_t flags, int depth,
|
|||||||
|
|
||||||
iter = json_object_iter((json_t *)json);
|
iter = json_object_iter((json_t *)json);
|
||||||
|
|
||||||
if(dump("{", 1, data))
|
if(!embed && dump("{", 1, data))
|
||||||
goto object_error;
|
goto object_error;
|
||||||
if(!iter) {
|
if(!iter) {
|
||||||
object->visited = 0;
|
object->visited = 0;
|
||||||
return dump("}", 1, data);
|
return embed ? 0 : dump("}", 1, data);
|
||||||
}
|
}
|
||||||
if(dump_indent(flags, depth + 1, 0, dump, data))
|
if(dump_indent(flags, depth + 1, 0, dump, data))
|
||||||
goto object_error;
|
goto object_error;
|
||||||
@@ -386,7 +421,7 @@ static int do_dump(const json_t *json, size_t flags, int depth,
|
|||||||
}
|
}
|
||||||
|
|
||||||
object->visited = 0;
|
object->visited = 0;
|
||||||
return dump("}", 1, data);
|
return embed ? 0 : dump("}", 1, data);
|
||||||
|
|
||||||
object_error:
|
object_error:
|
||||||
object->visited = 0;
|
object->visited = 0;
|
||||||
@@ -416,11 +451,26 @@ char *json_dumps(const json_t *json, size_t flags)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags)
|
||||||
|
{
|
||||||
|
struct buffer buf = { size, 0, buffer };
|
||||||
|
|
||||||
|
if(json_dump_callback(json, dump_to_buffer, (void *)&buf, flags))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return buf.used;
|
||||||
|
}
|
||||||
|
|
||||||
int json_dumpf(const json_t *json, FILE *output, size_t flags)
|
int json_dumpf(const json_t *json, FILE *output, size_t flags)
|
||||||
{
|
{
|
||||||
return json_dump_callback(json, dump_to_file, (void *)output, flags);
|
return json_dump_callback(json, dump_to_file, (void *)output, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int json_dumpfd(const json_t *json, int output, size_t flags)
|
||||||
|
{
|
||||||
|
return json_dump_callback(json, dump_to_fd, (void *)&output, flags);
|
||||||
|
}
|
||||||
|
|
||||||
int json_dump_file(const json_t *json, const char *path, size_t flags)
|
int json_dump_file(const json_t *json, const char *path, size_t flags)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
@@ -168,12 +168,12 @@ static uint32_t generate_seed() {
|
|||||||
int done = 0;
|
int done = 0;
|
||||||
|
|
||||||
#if !defined(_WIN32) && defined(USE_URANDOM)
|
#if !defined(_WIN32) && defined(USE_URANDOM)
|
||||||
if (!done && seed_from_urandom(&seed) == 0)
|
if (seed_from_urandom(&seed) == 0)
|
||||||
done = 1;
|
done = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI)
|
#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI)
|
||||||
if (!done && seed_from_windows_cryptoapi(&seed) == 0)
|
if (seed_from_windows_cryptoapi(&seed) == 0)
|
||||||
done = 1;
|
done = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -21,11 +21,11 @@ extern "C" {
|
|||||||
/* version */
|
/* version */
|
||||||
|
|
||||||
#define JANSSON_MAJOR_VERSION 2
|
#define JANSSON_MAJOR_VERSION 2
|
||||||
#define JANSSON_MINOR_VERSION 9
|
#define JANSSON_MINOR_VERSION 10
|
||||||
#define JANSSON_MICRO_VERSION 0
|
#define JANSSON_MICRO_VERSION 0
|
||||||
|
|
||||||
/* Micro version is omitted if it's 0 */
|
/* Micro version is omitted if it's 0 */
|
||||||
#define JANSSON_VERSION "2.9"
|
#define JANSSON_VERSION "2.10"
|
||||||
|
|
||||||
/* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this
|
/* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this
|
||||||
for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */
|
for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */
|
||||||
@@ -273,6 +273,7 @@ typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data);
|
|||||||
json_t *json_loads(const char *input, size_t flags, json_error_t *error);
|
json_t *json_loads(const char *input, size_t flags, json_error_t *error);
|
||||||
json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error);
|
json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error);
|
||||||
json_t *json_loadf(FILE *input, size_t flags, json_error_t *error);
|
json_t *json_loadf(FILE *input, size_t flags, json_error_t *error);
|
||||||
|
json_t *json_loadfd(int input, size_t flags, json_error_t *error);
|
||||||
json_t *json_load_file(const char *path, size_t flags, json_error_t *error);
|
json_t *json_load_file(const char *path, size_t flags, json_error_t *error);
|
||||||
json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error);
|
json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error);
|
||||||
|
|
||||||
@@ -288,11 +289,14 @@ json_t *json_load_callback(json_load_callback_t callback, void *data, size_t fla
|
|||||||
#define JSON_ENCODE_ANY 0x200
|
#define JSON_ENCODE_ANY 0x200
|
||||||
#define JSON_ESCAPE_SLASH 0x400
|
#define JSON_ESCAPE_SLASH 0x400
|
||||||
#define JSON_REAL_PRECISION(n) (((n) & 0x1F) << 11)
|
#define JSON_REAL_PRECISION(n) (((n) & 0x1F) << 11)
|
||||||
|
#define JSON_EMBED 0x10000
|
||||||
|
|
||||||
typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data);
|
typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data);
|
||||||
|
|
||||||
char *json_dumps(const json_t *json, size_t flags);
|
char *json_dumps(const json_t *json, size_t flags);
|
||||||
|
size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags);
|
||||||
int json_dumpf(const json_t *json, FILE *output, size_t flags);
|
int json_dumpf(const json_t *json, FILE *output, size_t flags);
|
||||||
|
int json_dumpfd(const json_t *json, int output, size_t flags);
|
||||||
int json_dump_file(const json_t *json, const char *path, size_t flags);
|
int json_dump_file(const json_t *json, const char *path, size_t flags);
|
||||||
int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags);
|
int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags);
|
||||||
|
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#ifndef JANSSON_PRIVATE_H
|
#ifndef JANSSON_PRIVATE_H
|
||||||
#define JANSSON_PRIVATE_H
|
#define JANSSON_PRIVATE_H
|
||||||
|
|
||||||
|
#include "jansson_private_config.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "jansson.h"
|
#include "jansson.h"
|
||||||
#include "hashtable.h"
|
#include "hashtable.h"
|
||||||
@@ -2,7 +2,9 @@
|
|||||||
/* jansson_private_config.h.in. Generated from configure.ac by autoheader. */
|
/* jansson_private_config.h.in. Generated from configure.ac by autoheader. */
|
||||||
|
|
||||||
/* Define to 1 if gcc's __atomic builtins are available */
|
/* Define to 1 if gcc's __atomic builtins are available */
|
||||||
#define HAVE_ATOMIC_BUILTINS 1
|
#ifndef _MSC_VER
|
||||||
|
# define HAVE_ATOMIC_BUILTINS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Define to 1 if you have the `close' function. */
|
/* Define to 1 if you have the `close' function. */
|
||||||
#define HAVE_CLOSE 1
|
#define HAVE_CLOSE 1
|
||||||
@@ -20,7 +22,9 @@
|
|||||||
#define HAVE_GETPID 1
|
#define HAVE_GETPID 1
|
||||||
|
|
||||||
/* Define to 1 if you have the `gettimeofday' function. */
|
/* Define to 1 if you have the `gettimeofday' function. */
|
||||||
#define HAVE_GETTIMEOFDAY 1
|
#ifndef _MSC_VER
|
||||||
|
# define HAVE_GETTIMEOFDAY 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
#define HAVE_INTTYPES_H 1
|
#define HAVE_INTTYPES_H 1
|
||||||
@@ -44,10 +48,14 @@
|
|||||||
#define HAVE_READ 1
|
#define HAVE_READ 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <sched.h> header file. */
|
/* Define to 1 if you have the <sched.h> header file. */
|
||||||
#define HAVE_SCHED_H 1
|
#ifndef _MSC_VER
|
||||||
|
# define HAVE_SCHED_H 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Define to 1 if you have the `sched_yield' function. */
|
/* Define to 1 if you have the `sched_yield' function. */
|
||||||
#define HAVE_SCHED_YIELD 1
|
#ifndef _MSC_VER
|
||||||
|
# define HAVE_SCHED_YIELD 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
#define HAVE_STDINT_H 1
|
#define HAVE_STDINT_H 1
|
||||||
@@ -68,19 +76,25 @@
|
|||||||
#define HAVE_SYNC_BUILTINS 1
|
#define HAVE_SYNC_BUILTINS 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||||
#define HAVE_SYS_PARAM_H 1
|
#ifndef _MSC_VER
|
||||||
|
# define HAVE_SYS_PARAM_H 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
#define HAVE_SYS_STAT_H 1
|
#define HAVE_SYS_STAT_H 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
#define HAVE_SYS_TIME_H 1
|
#ifndef _MSC_VER
|
||||||
|
# define HAVE_SYS_TIME_H 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
#define HAVE_SYS_TYPES_H 1
|
#define HAVE_SYS_TYPES_H 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
#define HAVE_UNISTD_H 1
|
#ifndef _MSC_VER
|
||||||
|
# define HAVE_UNISTD_H 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Define to 1 if the system has the type 'unsigned long long int'. */
|
/* Define to 1 if the system has the type 'unsigned long long int'. */
|
||||||
#define HAVE_UNSIGNED_LONG_LONG_INT 1
|
#define HAVE_UNSIGNED_LONG_LONG_INT 1
|
||||||
@@ -9,15 +9,19 @@
|
|||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "jansson_private.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "jansson.h"
|
#include "jansson.h"
|
||||||
#include "jansson_private.h"
|
|
||||||
#include "strbuffer.h"
|
#include "strbuffer.h"
|
||||||
#include "utf.h"
|
#include "utf.h"
|
||||||
|
|
||||||
@@ -340,7 +344,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
|
|||||||
/* control character */
|
/* control character */
|
||||||
lex_unget_unsave(lex, c);
|
lex_unget_unsave(lex, c);
|
||||||
if(c == '\n')
|
if(c == '\n')
|
||||||
error_set(error, lex, "unexpected newline", c);
|
error_set(error, lex, "unexpected newline");
|
||||||
else
|
else
|
||||||
error_set(error, lex, "control character 0x%x", c);
|
error_set(error, lex, "control character 0x%x", c);
|
||||||
goto out;
|
goto out;
|
||||||
@@ -914,7 +918,7 @@ static json_t *parse_json(lex_t *lex, size_t flags, json_error_t *error)
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const char *data;
|
const char *data;
|
||||||
int pos;
|
size_t pos;
|
||||||
} string_data_t;
|
} string_data_t;
|
||||||
|
|
||||||
static int string_get(void *data)
|
static int string_get(void *data)
|
||||||
@@ -1028,6 +1032,45 @@ json_t *json_loadf(FILE *input, size_t flags, json_error_t *error)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fd_get_func(int *fd)
|
||||||
|
{
|
||||||
|
uint8_t c;
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
if (read(*fd, &c, 1) == 1)
|
||||||
|
return c;
|
||||||
|
#endif
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_t *json_loadfd(int input, size_t flags, json_error_t *error)
|
||||||
|
{
|
||||||
|
lex_t lex;
|
||||||
|
const char *source;
|
||||||
|
json_t *result;
|
||||||
|
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
if(input == STDIN_FILENO)
|
||||||
|
source = "<stdin>";
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
source = "<stream>";
|
||||||
|
|
||||||
|
jsonp_error_init(error, source);
|
||||||
|
|
||||||
|
if (input < 0) {
|
||||||
|
error_set(error, NULL, "wrong arguments");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lex_init(&lex, (get_func)fd_get_func, flags, &input))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
result = parse_json(&lex, flags, error);
|
||||||
|
|
||||||
|
lex_close(&lex);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
json_t *json_load_file(const char *path, size_t flags, json_error_t *error)
|
json_t *json_load_file(const char *path, size_t flags, json_error_t *error)
|
||||||
{
|
{
|
||||||
json_t *result;
|
json_t *result;
|
||||||
38
src/3rdparty/libcpuid/CMakeLists.txt
vendored
Normal file
38
src/3rdparty/libcpuid/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
cmake_minimum_required (VERSION 2.8)
|
||||||
|
project (cpuid C)
|
||||||
|
|
||||||
|
add_definitions(/DVERSION="0.4.0")
|
||||||
|
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Os")
|
||||||
|
|
||||||
|
set(HEADERS
|
||||||
|
libcpuid.h
|
||||||
|
libcpuid_types.h
|
||||||
|
libcpuid_constants.h
|
||||||
|
libcpuid_internal.h
|
||||||
|
amd_code_t.h
|
||||||
|
intel_code_t.h
|
||||||
|
recog_amd.h
|
||||||
|
recog_intel.h
|
||||||
|
asm-bits.h
|
||||||
|
libcpuid_util.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SOURCES
|
||||||
|
cpuid_main.c
|
||||||
|
asm-bits.c
|
||||||
|
recog_amd.c
|
||||||
|
recog_intel.c
|
||||||
|
libcpuid_util.c
|
||||||
|
)
|
||||||
|
|
||||||
|
if (CMAKE_CL_64)
|
||||||
|
enable_language(ASM_MASM)
|
||||||
|
set(SOURCES_ASM masm-x64.asm)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(cpuid STATIC
|
||||||
|
${HEADERS}
|
||||||
|
${SOURCES}
|
||||||
|
${SOURCES_ASM}
|
||||||
|
)
|
||||||
39
src/3rdparty/libcpuid/amd_code_t.h
vendored
Normal file
39
src/3rdparty/libcpuid/amd_code_t.h
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file contains a list of internal codes we use in detection. It is
|
||||||
|
* of no external use and isn't a complete list of AMD products.
|
||||||
|
*/
|
||||||
|
CODE2(OPTERON_800, 1000),
|
||||||
|
CODE(PHENOM),
|
||||||
|
CODE(PHENOM2),
|
||||||
|
CODE(FUSION_C),
|
||||||
|
CODE(FUSION_E),
|
||||||
|
CODE(FUSION_EA),
|
||||||
|
CODE(FUSION_Z),
|
||||||
|
CODE(FUSION_A),
|
||||||
|
|
||||||
825
src/3rdparty/libcpuid/asm-bits.c
vendored
Normal file
825
src/3rdparty/libcpuid/asm-bits.c
vendored
Normal file
@@ -0,0 +1,825 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "libcpuid.h"
|
||||||
|
#include "asm-bits.h"
|
||||||
|
|
||||||
|
int cpuid_exists_by_eflags(void)
|
||||||
|
{
|
||||||
|
#if defined(PLATFORM_X64)
|
||||||
|
return 1; /* CPUID is always present on the x86_64 */
|
||||||
|
#elif defined(PLATFORM_X86)
|
||||||
|
# if defined(COMPILER_GCC)
|
||||||
|
int result;
|
||||||
|
__asm __volatile(
|
||||||
|
" pushfl\n"
|
||||||
|
" pop %%eax\n"
|
||||||
|
" mov %%eax, %%ecx\n"
|
||||||
|
" xor $0x200000, %%eax\n"
|
||||||
|
" push %%eax\n"
|
||||||
|
" popfl\n"
|
||||||
|
" pushfl\n"
|
||||||
|
" pop %%eax\n"
|
||||||
|
" xor %%ecx, %%eax\n"
|
||||||
|
" mov %%eax, %0\n"
|
||||||
|
" push %%ecx\n"
|
||||||
|
" popfl\n"
|
||||||
|
: "=m"(result)
|
||||||
|
: :"eax", "ecx", "memory");
|
||||||
|
return (result != 0);
|
||||||
|
# elif defined(COMPILER_MICROSOFT)
|
||||||
|
int result;
|
||||||
|
__asm {
|
||||||
|
pushfd
|
||||||
|
pop eax
|
||||||
|
mov ecx, eax
|
||||||
|
xor eax, 0x200000
|
||||||
|
push eax
|
||||||
|
popfd
|
||||||
|
pushfd
|
||||||
|
pop eax
|
||||||
|
xor eax, ecx
|
||||||
|
mov result, eax
|
||||||
|
push ecx
|
||||||
|
popfd
|
||||||
|
};
|
||||||
|
return (result != 0);
|
||||||
|
# else
|
||||||
|
return 0;
|
||||||
|
# endif /* COMPILER_MICROSOFT */
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif /* PLATFORM_X86 */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef INLINE_ASM_SUPPORTED
|
||||||
|
/*
|
||||||
|
* with MSVC/AMD64, the exec_cpuid() and cpu_rdtsc() functions
|
||||||
|
* are implemented in separate .asm files. Otherwise, use inline assembly
|
||||||
|
*/
|
||||||
|
void exec_cpuid(uint32_t *regs)
|
||||||
|
{
|
||||||
|
#ifdef COMPILER_GCC
|
||||||
|
# ifdef PLATFORM_X64
|
||||||
|
__asm __volatile(
|
||||||
|
" mov %0, %%rdi\n"
|
||||||
|
|
||||||
|
" push %%rbx\n"
|
||||||
|
" push %%rcx\n"
|
||||||
|
" push %%rdx\n"
|
||||||
|
|
||||||
|
" mov (%%rdi), %%eax\n"
|
||||||
|
" mov 4(%%rdi), %%ebx\n"
|
||||||
|
" mov 8(%%rdi), %%ecx\n"
|
||||||
|
" mov 12(%%rdi), %%edx\n"
|
||||||
|
|
||||||
|
" cpuid\n"
|
||||||
|
|
||||||
|
" movl %%eax, (%%rdi)\n"
|
||||||
|
" movl %%ebx, 4(%%rdi)\n"
|
||||||
|
" movl %%ecx, 8(%%rdi)\n"
|
||||||
|
" movl %%edx, 12(%%rdi)\n"
|
||||||
|
" pop %%rdx\n"
|
||||||
|
" pop %%rcx\n"
|
||||||
|
" pop %%rbx\n"
|
||||||
|
:
|
||||||
|
:"m"(regs)
|
||||||
|
:"memory", "eax", "rdi"
|
||||||
|
);
|
||||||
|
# else
|
||||||
|
__asm __volatile(
|
||||||
|
" mov %0, %%edi\n"
|
||||||
|
|
||||||
|
" push %%ebx\n"
|
||||||
|
" push %%ecx\n"
|
||||||
|
" push %%edx\n"
|
||||||
|
|
||||||
|
" mov (%%edi), %%eax\n"
|
||||||
|
" mov 4(%%edi), %%ebx\n"
|
||||||
|
" mov 8(%%edi), %%ecx\n"
|
||||||
|
" mov 12(%%edi), %%edx\n"
|
||||||
|
|
||||||
|
" cpuid\n"
|
||||||
|
|
||||||
|
" mov %%eax, (%%edi)\n"
|
||||||
|
" mov %%ebx, 4(%%edi)\n"
|
||||||
|
" mov %%ecx, 8(%%edi)\n"
|
||||||
|
" mov %%edx, 12(%%edi)\n"
|
||||||
|
" pop %%edx\n"
|
||||||
|
" pop %%ecx\n"
|
||||||
|
" pop %%ebx\n"
|
||||||
|
:
|
||||||
|
:"m"(regs)
|
||||||
|
:"memory", "eax", "edi"
|
||||||
|
);
|
||||||
|
# endif /* COMPILER_GCC */
|
||||||
|
#else
|
||||||
|
# ifdef COMPILER_MICROSOFT
|
||||||
|
__asm {
|
||||||
|
push ebx
|
||||||
|
push ecx
|
||||||
|
push edx
|
||||||
|
push edi
|
||||||
|
mov edi, regs
|
||||||
|
|
||||||
|
mov eax, [edi]
|
||||||
|
mov ebx, [edi+4]
|
||||||
|
mov ecx, [edi+8]
|
||||||
|
mov edx, [edi+12]
|
||||||
|
|
||||||
|
cpuid
|
||||||
|
|
||||||
|
mov [edi], eax
|
||||||
|
mov [edi+4], ebx
|
||||||
|
mov [edi+8], ecx
|
||||||
|
mov [edi+12], edx
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop edx
|
||||||
|
pop ecx
|
||||||
|
pop ebx
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
# error "Unsupported compiler"
|
||||||
|
# endif /* COMPILER_MICROSOFT */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif /* INLINE_ASSEMBLY_SUPPORTED */
|
||||||
|
|
||||||
|
#ifdef INLINE_ASM_SUPPORTED
|
||||||
|
void cpu_rdtsc(uint64_t* result)
|
||||||
|
{
|
||||||
|
uint32_t low_part, hi_part;
|
||||||
|
#ifdef COMPILER_GCC
|
||||||
|
__asm __volatile (
|
||||||
|
" rdtsc\n"
|
||||||
|
" mov %%eax, %0\n"
|
||||||
|
" mov %%edx, %1\n"
|
||||||
|
:"=m"(low_part), "=m"(hi_part)::"memory", "eax", "edx"
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
# ifdef COMPILER_MICROSOFT
|
||||||
|
__asm {
|
||||||
|
rdtsc
|
||||||
|
mov low_part, eax
|
||||||
|
mov hi_part, edx
|
||||||
|
};
|
||||||
|
# else
|
||||||
|
# error "Unsupported compiler"
|
||||||
|
# endif /* COMPILER_MICROSOFT */
|
||||||
|
#endif /* COMPILER_GCC */
|
||||||
|
*result = (uint64_t)low_part + (((uint64_t) hi_part) << 32);
|
||||||
|
}
|
||||||
|
#endif /* INLINE_ASM_SUPPORTED */
|
||||||
|
|
||||||
|
#ifdef INLINE_ASM_SUPPORTED
|
||||||
|
void busy_sse_loop(int cycles)
|
||||||
|
{
|
||||||
|
#ifdef COMPILER_GCC
|
||||||
|
#ifndef __APPLE__
|
||||||
|
# define XALIGN ".balign 16\n"
|
||||||
|
#else
|
||||||
|
# define XALIGN ".align 4\n"
|
||||||
|
#endif
|
||||||
|
__asm __volatile (
|
||||||
|
" xorps %%xmm0, %%xmm0\n"
|
||||||
|
" xorps %%xmm1, %%xmm1\n"
|
||||||
|
" xorps %%xmm2, %%xmm2\n"
|
||||||
|
" xorps %%xmm3, %%xmm3\n"
|
||||||
|
" xorps %%xmm4, %%xmm4\n"
|
||||||
|
" xorps %%xmm5, %%xmm5\n"
|
||||||
|
" xorps %%xmm6, %%xmm6\n"
|
||||||
|
" xorps %%xmm7, %%xmm7\n"
|
||||||
|
XALIGN
|
||||||
|
/* ".bsLoop:\n" */
|
||||||
|
"1:\n"
|
||||||
|
// 0:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
// 1:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
// 2:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
// 3:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
// 4:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
// 5:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
// 6:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
// 7:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
// 8:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
// 9:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//10:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//11:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//12:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//13:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//14:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//15:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//16:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//17:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//18:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//19:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//20:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//21:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//22:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//23:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//24:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//25:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//26:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//27:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//28:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//29:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//30:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
//31:
|
||||||
|
" addps %%xmm1, %%xmm0\n"
|
||||||
|
" addps %%xmm2, %%xmm1\n"
|
||||||
|
" addps %%xmm3, %%xmm2\n"
|
||||||
|
" addps %%xmm4, %%xmm3\n"
|
||||||
|
" addps %%xmm5, %%xmm4\n"
|
||||||
|
" addps %%xmm6, %%xmm5\n"
|
||||||
|
" addps %%xmm7, %%xmm6\n"
|
||||||
|
" addps %%xmm0, %%xmm7\n"
|
||||||
|
|
||||||
|
" dec %%eax\n"
|
||||||
|
/* "jnz .bsLoop\n" */
|
||||||
|
" jnz 1b\n"
|
||||||
|
::"a"(cycles)
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
# ifdef COMPILER_MICROSOFT
|
||||||
|
__asm {
|
||||||
|
mov eax, cycles
|
||||||
|
xorps xmm0, xmm0
|
||||||
|
xorps xmm1, xmm1
|
||||||
|
xorps xmm2, xmm2
|
||||||
|
xorps xmm3, xmm3
|
||||||
|
xorps xmm4, xmm4
|
||||||
|
xorps xmm5, xmm5
|
||||||
|
xorps xmm6, xmm6
|
||||||
|
xorps xmm7, xmm7
|
||||||
|
//--
|
||||||
|
align 16
|
||||||
|
bsLoop:
|
||||||
|
// 0:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 1:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 2:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 3:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 4:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 5:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 6:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 7:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 8:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 9:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 10:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 11:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 12:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 13:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 14:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 15:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 16:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 17:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 18:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 19:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 20:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 21:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 22:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 23:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 24:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 25:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 26:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 27:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 28:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 29:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 30:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
// 31:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
//----------------------
|
||||||
|
dec eax
|
||||||
|
jnz bsLoop
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
# error "Unsupported compiler"
|
||||||
|
# endif /* COMPILER_MICROSOFT */
|
||||||
|
#endif /* COMPILER_GCC */
|
||||||
|
}
|
||||||
|
#endif /* INLINE_ASSEMBLY_SUPPORTED */
|
||||||
53
src/3rdparty/libcpuid/asm-bits.h
vendored
Normal file
53
src/3rdparty/libcpuid/asm-bits.h
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
#ifndef __ASM_BITS_H__
|
||||||
|
#define __ASM_BITS_H__
|
||||||
|
#include "libcpuid.h"
|
||||||
|
|
||||||
|
/* Determine Compiler: */
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# define COMPILER_MICROSOFT
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
# define COMPILER_GCC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Determine Platform */
|
||||||
|
#if defined(__x86_64__) || defined(_M_AMD64)
|
||||||
|
# define PLATFORM_X64
|
||||||
|
#elif defined(__i386__) || defined(_M_IX86)
|
||||||
|
# define PLATFORM_X86
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Under Windows/AMD64 with MSVC, inline assembly isn't supported */
|
||||||
|
#if (defined(COMPILER_GCC) && defined(PLATFORM_X64)) || defined(PLATFORM_X86)
|
||||||
|
# define INLINE_ASM_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int cpuid_exists_by_eflags(void);
|
||||||
|
void exec_cpuid(uint32_t *regs);
|
||||||
|
void busy_sse_loop(int cycles);
|
||||||
|
|
||||||
|
#endif /* __ASM_BITS_H__ */
|
||||||
389
src/3rdparty/libcpuid/cpuid_main.c
vendored
Normal file
389
src/3rdparty/libcpuid/cpuid_main.c
vendored
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "libcpuid.h"
|
||||||
|
#include "libcpuid_internal.h"
|
||||||
|
#include "recog_intel.h"
|
||||||
|
#include "recog_amd.h"
|
||||||
|
#include "asm-bits.h"
|
||||||
|
#include "libcpuid_util.h"
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Implementation: */
|
||||||
|
|
||||||
|
static int _libcpiud_errno = ERR_OK;
|
||||||
|
|
||||||
|
int set_error(cpu_error_t err)
|
||||||
|
{
|
||||||
|
_libcpiud_errno = (int) err;
|
||||||
|
return (int) err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpu_id_t_constructor(struct cpu_id_t* id)
|
||||||
|
{
|
||||||
|
memset(id, 0, sizeof(struct cpu_id_t));
|
||||||
|
id->l1_data_cache = id->l1_instruction_cache = id->l2_cache = id->l3_cache = id->l4_cache = -1;
|
||||||
|
id->l1_assoc = id->l2_assoc = id->l3_assoc = id->l4_assoc = -1;
|
||||||
|
id->l1_cacheline = id->l2_cacheline = id->l3_cacheline = id->l4_cacheline = -1;
|
||||||
|
id->sse_size = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get_total_cpus() system specific code: uses OS routines to determine total number of CPUs */
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <mach/clock_types.h>
|
||||||
|
#include <mach/clock.h>
|
||||||
|
#include <mach/mach.h>
|
||||||
|
static int get_total_cpus(void)
|
||||||
|
{
|
||||||
|
kern_return_t kr;
|
||||||
|
host_basic_info_data_t basic_info;
|
||||||
|
host_info_t info = (host_info_t)&basic_info;
|
||||||
|
host_flavor_t flavor = HOST_BASIC_INFO;
|
||||||
|
mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
|
||||||
|
kr = host_info(mach_host_self(), flavor, info, &count);
|
||||||
|
if (kr != KERN_SUCCESS) return 1;
|
||||||
|
return basic_info.avail_cpus;
|
||||||
|
}
|
||||||
|
#define GET_TOTAL_CPUS_DEFINED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
static int get_total_cpus(void)
|
||||||
|
{
|
||||||
|
SYSTEM_INFO system_info;
|
||||||
|
GetSystemInfo(&system_info);
|
||||||
|
return system_info.dwNumberOfProcessors;
|
||||||
|
}
|
||||||
|
#define GET_TOTAL_CPUS_DEFINED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined linux || defined __linux__ || defined __sun
|
||||||
|
#include <sys/sysinfo.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static int get_total_cpus(void)
|
||||||
|
{
|
||||||
|
return sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
}
|
||||||
|
#define GET_TOTAL_CPUS_DEFINED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __bsdi__ || defined __QNX__
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
|
||||||
|
static int get_total_cpus(void)
|
||||||
|
{
|
||||||
|
int mib[2] = { CTL_HW, HW_NCPU };
|
||||||
|
int ncpus;
|
||||||
|
size_t len = sizeof(ncpus);
|
||||||
|
if (sysctl(mib, 2, &ncpus, &len, (void *) 0, 0) != 0) return 1;
|
||||||
|
return ncpus;
|
||||||
|
}
|
||||||
|
#define GET_TOTAL_CPUS_DEFINED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GET_TOTAL_CPUS_DEFINED
|
||||||
|
static int get_total_cpus(void)
|
||||||
|
{
|
||||||
|
static int warning_printed = 0;
|
||||||
|
if (!warning_printed) {
|
||||||
|
warning_printed = 1;
|
||||||
|
warnf("Your system is not supported by libcpuid -- don't know how to detect the\n");
|
||||||
|
warnf("total number of CPUs on your system. It will be reported as 1.\n");
|
||||||
|
printf("Please use cpu_id_t.logical_cpus field instead.\n");
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif /* GET_TOTAL_CPUS_DEFINED */
|
||||||
|
|
||||||
|
|
||||||
|
static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
const struct feature_map_t matchtable_edx1[] = {
|
||||||
|
{ 0, CPU_FEATURE_FPU },
|
||||||
|
{ 1, CPU_FEATURE_VME },
|
||||||
|
{ 2, CPU_FEATURE_DE },
|
||||||
|
{ 3, CPU_FEATURE_PSE },
|
||||||
|
{ 4, CPU_FEATURE_TSC },
|
||||||
|
{ 5, CPU_FEATURE_MSR },
|
||||||
|
{ 6, CPU_FEATURE_PAE },
|
||||||
|
{ 7, CPU_FEATURE_MCE },
|
||||||
|
{ 8, CPU_FEATURE_CX8 },
|
||||||
|
{ 9, CPU_FEATURE_APIC },
|
||||||
|
{ 11, CPU_FEATURE_SEP },
|
||||||
|
{ 12, CPU_FEATURE_MTRR },
|
||||||
|
{ 13, CPU_FEATURE_PGE },
|
||||||
|
{ 14, CPU_FEATURE_MCA },
|
||||||
|
{ 15, CPU_FEATURE_CMOV },
|
||||||
|
{ 16, CPU_FEATURE_PAT },
|
||||||
|
{ 17, CPU_FEATURE_PSE36 },
|
||||||
|
{ 19, CPU_FEATURE_CLFLUSH },
|
||||||
|
{ 23, CPU_FEATURE_MMX },
|
||||||
|
{ 24, CPU_FEATURE_FXSR },
|
||||||
|
{ 25, CPU_FEATURE_SSE },
|
||||||
|
{ 26, CPU_FEATURE_SSE2 },
|
||||||
|
{ 28, CPU_FEATURE_HT },
|
||||||
|
};
|
||||||
|
const struct feature_map_t matchtable_ecx1[] = {
|
||||||
|
{ 0, CPU_FEATURE_PNI },
|
||||||
|
{ 1, CPU_FEATURE_PCLMUL },
|
||||||
|
{ 3, CPU_FEATURE_MONITOR },
|
||||||
|
{ 9, CPU_FEATURE_SSSE3 },
|
||||||
|
{ 12, CPU_FEATURE_FMA3 },
|
||||||
|
{ 13, CPU_FEATURE_CX16 },
|
||||||
|
{ 19, CPU_FEATURE_SSE4_1 },
|
||||||
|
{ 20, CPU_FEATURE_SSE4_2 },
|
||||||
|
{ 22, CPU_FEATURE_MOVBE },
|
||||||
|
{ 23, CPU_FEATURE_POPCNT },
|
||||||
|
{ 25, CPU_FEATURE_AES },
|
||||||
|
{ 26, CPU_FEATURE_XSAVE },
|
||||||
|
{ 27, CPU_FEATURE_OSXSAVE },
|
||||||
|
{ 28, CPU_FEATURE_AVX },
|
||||||
|
{ 29, CPU_FEATURE_F16C },
|
||||||
|
{ 30, CPU_FEATURE_RDRAND },
|
||||||
|
};
|
||||||
|
const struct feature_map_t matchtable_ebx7[] = {
|
||||||
|
{ 3, CPU_FEATURE_BMI1 },
|
||||||
|
{ 5, CPU_FEATURE_AVX2 },
|
||||||
|
{ 8, CPU_FEATURE_BMI2 },
|
||||||
|
};
|
||||||
|
const struct feature_map_t matchtable_edx81[] = {
|
||||||
|
{ 11, CPU_FEATURE_SYSCALL },
|
||||||
|
{ 27, CPU_FEATURE_RDTSCP },
|
||||||
|
{ 29, CPU_FEATURE_LM },
|
||||||
|
};
|
||||||
|
const struct feature_map_t matchtable_ecx81[] = {
|
||||||
|
{ 0, CPU_FEATURE_LAHF_LM },
|
||||||
|
};
|
||||||
|
const struct feature_map_t matchtable_edx87[] = {
|
||||||
|
{ 8, CPU_FEATURE_CONSTANT_TSC },
|
||||||
|
};
|
||||||
|
if (raw->basic_cpuid[0][0] >= 1) {
|
||||||
|
match_features(matchtable_edx1, COUNT_OF(matchtable_edx1), raw->basic_cpuid[1][3], data);
|
||||||
|
match_features(matchtable_ecx1, COUNT_OF(matchtable_ecx1), raw->basic_cpuid[1][2], data);
|
||||||
|
}
|
||||||
|
if (raw->basic_cpuid[0][0] >= 7) {
|
||||||
|
match_features(matchtable_ebx7, COUNT_OF(matchtable_ebx7), raw->basic_cpuid[7][1], data);
|
||||||
|
}
|
||||||
|
if (raw->ext_cpuid[0][0] >= 0x80000001) {
|
||||||
|
match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
|
||||||
|
match_features(matchtable_ecx81, COUNT_OF(matchtable_ecx81), raw->ext_cpuid[1][2], data);
|
||||||
|
}
|
||||||
|
if (raw->ext_cpuid[0][0] >= 0x80000007) {
|
||||||
|
match_features(matchtable_edx87, COUNT_OF(matchtable_edx87), raw->ext_cpuid[7][3], data);
|
||||||
|
}
|
||||||
|
if (data->flags[CPU_FEATURE_SSE]) {
|
||||||
|
/* apply guesswork to check if the SSE unit width is 128 bit */
|
||||||
|
switch (data->vendor) {
|
||||||
|
case VENDOR_AMD:
|
||||||
|
data->sse_size = (data->ext_family >= 16 && data->ext_family != 17) ? 128 : 64;
|
||||||
|
break;
|
||||||
|
case VENDOR_INTEL:
|
||||||
|
data->sse_size = (data->family == 6 && data->ext_model >= 15) ? 128 : 64;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* leave the CPU_FEATURE_128BIT_SSE_AUTH 0; the advanced per-vendor detection routines
|
||||||
|
* will set it accordingly if they detect the needed bit */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static cpu_vendor_t cpuid_vendor_identify(const uint32_t *raw_vendor, char *vendor_str)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
cpu_vendor_t vendor = VENDOR_UNKNOWN;
|
||||||
|
const struct { cpu_vendor_t vendor; char match[16]; }
|
||||||
|
matchtable[NUM_CPU_VENDORS] = {
|
||||||
|
/* source: http://www.sandpile.org/ia32/cpuid.htm */
|
||||||
|
{ VENDOR_INTEL , "GenuineIntel" },
|
||||||
|
{ VENDOR_AMD , "AuthenticAMD" },
|
||||||
|
{ VENDOR_CYRIX , "CyrixInstead" },
|
||||||
|
{ VENDOR_NEXGEN , "NexGenDriven" },
|
||||||
|
{ VENDOR_TRANSMETA , "GenuineTMx86" },
|
||||||
|
{ VENDOR_UMC , "UMC UMC UMC " },
|
||||||
|
{ VENDOR_CENTAUR , "CentaurHauls" },
|
||||||
|
{ VENDOR_RISE , "RiseRiseRise" },
|
||||||
|
{ VENDOR_SIS , "SiS SiS SiS " },
|
||||||
|
{ VENDOR_NSC , "Geode by NSC" },
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(vendor_str + 0, &raw_vendor[1], 4);
|
||||||
|
memcpy(vendor_str + 4, &raw_vendor[3], 4);
|
||||||
|
memcpy(vendor_str + 8, &raw_vendor[2], 4);
|
||||||
|
vendor_str[12] = 0;
|
||||||
|
|
||||||
|
/* Determine vendor: */
|
||||||
|
for (i = 0; i < NUM_CPU_VENDORS; i++)
|
||||||
|
if (!strcmp(vendor_str, matchtable[i].match)) {
|
||||||
|
vendor = matchtable[i].vendor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return vendor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
int i, j, basic, xmodel, xfamily, ext;
|
||||||
|
char brandstr[64] = {0};
|
||||||
|
data->vendor = cpuid_vendor_identify(raw->basic_cpuid[0], data->vendor_str);
|
||||||
|
|
||||||
|
if (data->vendor == VENDOR_UNKNOWN)
|
||||||
|
return set_error(ERR_CPU_UNKN);
|
||||||
|
basic = raw->basic_cpuid[0][0];
|
||||||
|
if (basic >= 1) {
|
||||||
|
data->family = (raw->basic_cpuid[1][0] >> 8) & 0xf;
|
||||||
|
data->model = (raw->basic_cpuid[1][0] >> 4) & 0xf;
|
||||||
|
data->stepping = raw->basic_cpuid[1][0] & 0xf;
|
||||||
|
xmodel = (raw->basic_cpuid[1][0] >> 16) & 0xf;
|
||||||
|
xfamily = (raw->basic_cpuid[1][0] >> 20) & 0xff;
|
||||||
|
if (data->vendor == VENDOR_AMD && data->family < 0xf)
|
||||||
|
data->ext_family = data->family;
|
||||||
|
else
|
||||||
|
data->ext_family = data->family + xfamily;
|
||||||
|
data->ext_model = data->model + (xmodel << 4);
|
||||||
|
}
|
||||||
|
ext = raw->ext_cpuid[0][0] - 0x8000000;
|
||||||
|
|
||||||
|
/* obtain the brand string, if present: */
|
||||||
|
if (ext >= 4) {
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
memcpy(brandstr + i * 16 + j * 4,
|
||||||
|
&raw->ext_cpuid[2 + i][j], 4);
|
||||||
|
brandstr[48] = 0;
|
||||||
|
i = 0;
|
||||||
|
while (brandstr[i] == ' ') i++;
|
||||||
|
strncpy(data->brand_str, brandstr + i, sizeof(data->brand_str));
|
||||||
|
data->brand_str[48] = 0;
|
||||||
|
}
|
||||||
|
load_features_common(raw, data);
|
||||||
|
data->total_logical_cpus = get_total_cpus();
|
||||||
|
return set_error(ERR_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interface: */
|
||||||
|
|
||||||
|
int cpuid_get_total_cpus(void)
|
||||||
|
{
|
||||||
|
return get_total_cpus();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpuid_present(void)
|
||||||
|
{
|
||||||
|
return cpuid_exists_by_eflags();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_exec_cpuid(uint32_t eax, uint32_t* regs)
|
||||||
|
{
|
||||||
|
regs[0] = eax;
|
||||||
|
regs[1] = regs[2] = regs[3] = 0;
|
||||||
|
exec_cpuid(regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_exec_cpuid_ext(uint32_t* regs)
|
||||||
|
{
|
||||||
|
exec_cpuid(regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpuid_get_raw_data(struct cpu_raw_data_t* data)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
if (!cpuid_present())
|
||||||
|
return set_error(ERR_NO_CPUID);
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
cpu_exec_cpuid(i, data->basic_cpuid[i]);
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
cpu_exec_cpuid(0x80000000 + i, data->ext_cpuid[i]);
|
||||||
|
for (i = 0; i < MAX_INTELFN4_LEVEL; i++) {
|
||||||
|
memset(data->intel_fn4[i], 0, sizeof(data->intel_fn4[i]));
|
||||||
|
data->intel_fn4[i][0] = 4;
|
||||||
|
data->intel_fn4[i][2] = i;
|
||||||
|
cpu_exec_cpuid_ext(data->intel_fn4[i]);
|
||||||
|
}
|
||||||
|
for (i = 0; i < MAX_INTELFN11_LEVEL; i++) {
|
||||||
|
memset(data->intel_fn11[i], 0, sizeof(data->intel_fn11[i]));
|
||||||
|
data->intel_fn11[i][0] = 11;
|
||||||
|
data->intel_fn11[i][2] = i;
|
||||||
|
cpu_exec_cpuid_ext(data->intel_fn11[i]);
|
||||||
|
}
|
||||||
|
for (i = 0; i < MAX_INTELFN12H_LEVEL; i++) {
|
||||||
|
memset(data->intel_fn12h[i], 0, sizeof(data->intel_fn12h[i]));
|
||||||
|
data->intel_fn12h[i][0] = 0x12;
|
||||||
|
data->intel_fn12h[i][2] = i;
|
||||||
|
cpu_exec_cpuid_ext(data->intel_fn12h[i]);
|
||||||
|
}
|
||||||
|
for (i = 0; i < MAX_INTELFN14H_LEVEL; i++) {
|
||||||
|
memset(data->intel_fn14h[i], 0, sizeof(data->intel_fn14h[i]));
|
||||||
|
data->intel_fn14h[i][0] = 0x14;
|
||||||
|
data->intel_fn14h[i][2] = i;
|
||||||
|
cpu_exec_cpuid_ext(data->intel_fn14h[i]);
|
||||||
|
}
|
||||||
|
return set_error(ERR_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpu_ident_internal(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
struct cpu_raw_data_t myraw;
|
||||||
|
if (!raw) {
|
||||||
|
if ((r = cpuid_get_raw_data(&myraw)) < 0)
|
||||||
|
return set_error(r);
|
||||||
|
raw = &myraw;
|
||||||
|
}
|
||||||
|
cpu_id_t_constructor(data);
|
||||||
|
if ((r = cpuid_basic_identify(raw, data)) < 0)
|
||||||
|
return set_error(r);
|
||||||
|
switch (data->vendor) {
|
||||||
|
case VENDOR_INTEL:
|
||||||
|
r = cpuid_identify_intel(raw, data, internal);
|
||||||
|
break;
|
||||||
|
case VENDOR_AMD:
|
||||||
|
r = cpuid_identify_amd(raw, data, internal);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return set_error(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
struct internal_id_info_t throwaway;
|
||||||
|
return cpu_ident_internal(raw, data, &throwaway);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* cpuid_lib_version(void)
|
||||||
|
{
|
||||||
|
return VERSION;
|
||||||
|
}
|
||||||
58
src/3rdparty/libcpuid/intel_code_t.h
vendored
Normal file
58
src/3rdparty/libcpuid/intel_code_t.h
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file contains a list of internal codes we use in detection. It is
|
||||||
|
* of no external use and isn't a complete list of intel products.
|
||||||
|
*/
|
||||||
|
CODE2(PENTIUM, 2000),
|
||||||
|
|
||||||
|
CODE(IRWIN),
|
||||||
|
CODE(POTOMAC),
|
||||||
|
CODE(GAINESTOWN),
|
||||||
|
CODE(WESTMERE),
|
||||||
|
|
||||||
|
CODE(PENTIUM_M),
|
||||||
|
CODE(NOT_CELERON),
|
||||||
|
|
||||||
|
CODE(CORE_SOLO),
|
||||||
|
CODE(MOBILE_CORE_SOLO),
|
||||||
|
CODE(CORE_DUO),
|
||||||
|
CODE(MOBILE_CORE_DUO),
|
||||||
|
|
||||||
|
CODE(WOLFDALE),
|
||||||
|
CODE(MEROM),
|
||||||
|
CODE(PENRYN),
|
||||||
|
CODE(QUAD_CORE),
|
||||||
|
CODE(DUAL_CORE_HT),
|
||||||
|
CODE(QUAD_CORE_HT),
|
||||||
|
CODE(MORE_THAN_QUADCORE),
|
||||||
|
CODE(PENTIUM_D),
|
||||||
|
|
||||||
|
CODE(SILVERTHORNE),
|
||||||
|
CODE(DIAMONDVILLE),
|
||||||
|
CODE(PINEVIEW),
|
||||||
|
CODE(CEDARVIEW),
|
||||||
677
src/3rdparty/libcpuid/libcpuid.h
vendored
Normal file
677
src/3rdparty/libcpuid/libcpuid.h
vendored
Normal file
@@ -0,0 +1,677 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
#ifndef __LIBCPUID_H__
|
||||||
|
#define __LIBCPUID_H__
|
||||||
|
/**
|
||||||
|
* \file libcpuid.h
|
||||||
|
* \author Veselin Georgiev
|
||||||
|
* \date Oct 2008
|
||||||
|
* \version 0.4.0
|
||||||
|
*
|
||||||
|
* Version history:
|
||||||
|
*
|
||||||
|
* * 0.1.0 (2008-10-15): initial adaptation from wxfractgui sources
|
||||||
|
* * 0.1.1 (2009-07-06): Added intel_fn11 fields to cpu_raw_data_t to handle
|
||||||
|
* new processor topology enumeration required on Core i7
|
||||||
|
* * 0.1.2 (2009-09-26): Added support for MSR reading through self-extracting
|
||||||
|
* kernel driver on Win32.
|
||||||
|
* * 0.1.3 (2010-04-20): Added support for greater more accurate CPU clock
|
||||||
|
* measurements with cpu_clock_by_ic()
|
||||||
|
* * 0.2.0 (2011-10-11): Support for AMD Bulldozer CPUs, 128-bit SSE unit size
|
||||||
|
* checking. A backwards-incompatible change, since the
|
||||||
|
* sizeof cpu_id_t is now different.
|
||||||
|
* * 0.2.1 (2012-05-26): Support for Ivy Bridge, and detecting the presence of
|
||||||
|
* the RdRand instruction.
|
||||||
|
* * 0.2.2 (2015-11-04): Support for newer processors up to Haswell and Vishera.
|
||||||
|
* Fix clock detection in cpu_clock_by_ic() for Bulldozer.
|
||||||
|
* More entries supported in cpu_msrinfo().
|
||||||
|
* *BSD and Solaris support (unofficial).
|
||||||
|
* * 0.3.0 (2016-07-09): Support for Skylake; MSR ops in FreeBSD; INFO_VOLTAGE
|
||||||
|
* for AMD CPUs. Level 4 cache support for Crystalwell
|
||||||
|
* (a backwards-incompatible change since the sizeof
|
||||||
|
* cpu_raw_data_t is now different).
|
||||||
|
* * 0.4.0 (2016-09-30): Better detection of AMD clock multiplier with msrinfo.
|
||||||
|
* Support for Intel SGX detection
|
||||||
|
* (a backwards-incompatible change since the sizeof
|
||||||
|
* cpu_raw_data_t and cpu_id_t is now different).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @mainpage A simple libcpuid introduction
|
||||||
|
*
|
||||||
|
* LibCPUID provides CPU identification and access to the CPUID and RDTSC
|
||||||
|
* instructions on the x86.
|
||||||
|
* <p>
|
||||||
|
* To execute CPUID, use \ref cpu_exec_cpuid <br>
|
||||||
|
* To execute RDTSC, use \ref cpu_rdtsc <br>
|
||||||
|
* To fetch the CPUID info needed for CPU identification, use
|
||||||
|
* \ref cpuid_get_raw_data <br>
|
||||||
|
* To make sense of that data (decode, extract features), use \ref cpu_identify <br>
|
||||||
|
* To detect the CPU speed, use either \ref cpu_clock, \ref cpu_clock_by_os,
|
||||||
|
* \ref cpu_tsc_mark + \ref cpu_tsc_unmark + \ref cpu_clock_by_mark,
|
||||||
|
* \ref cpu_clock_measure or \ref cpu_clock_by_ic.
|
||||||
|
* Read carefully for pros/cons of each method. <br>
|
||||||
|
*
|
||||||
|
* To read MSRs, use \ref cpu_msr_driver_open to get a handle, and then
|
||||||
|
* \ref cpu_rdmsr for querying abilities. Some MSR decoding is available on recent
|
||||||
|
* CPUs, and can be queried through \ref cpu_msrinfo; the various types of queries
|
||||||
|
* are described in \ref cpu_msrinfo_request_t.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup libcpuid LibCPUID
|
||||||
|
@{ */
|
||||||
|
|
||||||
|
/* Include some integer type specifications: */
|
||||||
|
#include "libcpuid_types.h"
|
||||||
|
|
||||||
|
/* Some limits and other constants */
|
||||||
|
#include "libcpuid_constants.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CPU vendor, as guessed from the Vendor String.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
VENDOR_INTEL = 0, /*!< Intel CPU */
|
||||||
|
VENDOR_AMD, /*!< AMD CPU */
|
||||||
|
VENDOR_CYRIX, /*!< Cyrix CPU */
|
||||||
|
VENDOR_NEXGEN, /*!< NexGen CPU */
|
||||||
|
VENDOR_TRANSMETA, /*!< Transmeta CPU */
|
||||||
|
VENDOR_UMC, /*!< x86 CPU by UMC */
|
||||||
|
VENDOR_CENTAUR, /*!< x86 CPU by IDT */
|
||||||
|
VENDOR_RISE, /*!< x86 CPU by Rise Technology */
|
||||||
|
VENDOR_SIS, /*!< x86 CPU by SiS */
|
||||||
|
VENDOR_NSC, /*!< x86 CPU by National Semiconductor */
|
||||||
|
|
||||||
|
NUM_CPU_VENDORS, /*!< Valid CPU vendor ids: 0..NUM_CPU_VENDORS - 1 */
|
||||||
|
VENDOR_UNKNOWN = -1,
|
||||||
|
} cpu_vendor_t;
|
||||||
|
#define NUM_CPU_VENDORS NUM_CPU_VENDORS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Contains just the raw CPUID data.
|
||||||
|
*
|
||||||
|
* This contains only the most basic CPU data, required to do identification
|
||||||
|
* and feature recognition. Every processor should be identifiable using this
|
||||||
|
* data only.
|
||||||
|
*/
|
||||||
|
struct cpu_raw_data_t {
|
||||||
|
/** contains results of CPUID for eax = 0, 1, ...*/
|
||||||
|
uint32_t basic_cpuid[MAX_CPUID_LEVEL][4];
|
||||||
|
|
||||||
|
/** contains results of CPUID for eax = 0x80000000, 0x80000001, ...*/
|
||||||
|
uint32_t ext_cpuid[MAX_EXT_CPUID_LEVEL][4];
|
||||||
|
|
||||||
|
/** when the CPU is intel and it supports deterministic cache
|
||||||
|
information: this contains the results of CPUID for eax = 4
|
||||||
|
and ecx = 0, 1, ... */
|
||||||
|
uint32_t intel_fn4[MAX_INTELFN4_LEVEL][4];
|
||||||
|
|
||||||
|
/** when the CPU is intel and it supports leaf 0Bh (Extended Topology
|
||||||
|
enumeration leaf), this stores the result of CPUID with
|
||||||
|
eax = 11 and ecx = 0, 1, 2... */
|
||||||
|
uint32_t intel_fn11[MAX_INTELFN11_LEVEL][4];
|
||||||
|
|
||||||
|
/** when the CPU is intel and supports leaf 12h (SGX enumeration leaf),
|
||||||
|
* this stores the result of CPUID with eax = 0x12 and
|
||||||
|
* ecx = 0, 1, 2... */
|
||||||
|
uint32_t intel_fn12h[MAX_INTELFN12H_LEVEL][4];
|
||||||
|
|
||||||
|
/** when the CPU is intel and supports leaf 14h (Intel Processor Trace
|
||||||
|
* capabilities leaf).
|
||||||
|
* this stores the result of CPUID with eax = 0x12 and
|
||||||
|
* ecx = 0, 1, 2... */
|
||||||
|
uint32_t intel_fn14h[MAX_INTELFN14H_LEVEL][4];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This contains information about SGX features of the processor
|
||||||
|
* Example usage:
|
||||||
|
* @code
|
||||||
|
* ...
|
||||||
|
* struct cpu_raw_data_t raw;
|
||||||
|
* struct cpu_id_t id;
|
||||||
|
*
|
||||||
|
* if (cpuid_get_raw_data(&raw) == 0 && cpu_identify(&raw, &id) == 0 && id.sgx.present) {
|
||||||
|
* printf("SGX is present.\n");
|
||||||
|
* printf("SGX1 instructions: %s.\n", id.sgx.flags[INTEL_SGX1] ? "present" : "absent");
|
||||||
|
* printf("SGX2 instructions: %s.\n", id.sgx.flags[INTEL_SGX2] ? "present" : "absent");
|
||||||
|
* printf("Max 32-bit enclave size: 2^%d bytes.\n", id.sgx.max_enclave_32bit);
|
||||||
|
* printf("Max 64-bit enclave size: 2^%d bytes.\n", id.sgx.max_enclave_64bit);
|
||||||
|
* for (int i = 0; i < id.sgx.num_epc_sections; i++) {
|
||||||
|
* struct cpu_epc_t epc = cpuid_get_epc(i, NULL);
|
||||||
|
* printf("EPC section #%d: address = %x, size = %d bytes.\n", epc.address, epc.size);
|
||||||
|
* }
|
||||||
|
* } else {
|
||||||
|
* printf("SGX is not present.\n");
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
struct cpu_sgx_t {
|
||||||
|
/** Whether SGX is present (boolean) */
|
||||||
|
uint32_t present;
|
||||||
|
|
||||||
|
/** Max enclave size in 32-bit mode. This is a power-of-two value:
|
||||||
|
* if it is "31", then the max enclave size is 2^31 bytes (2 GiB).
|
||||||
|
*/
|
||||||
|
uint8_t max_enclave_32bit;
|
||||||
|
|
||||||
|
/** Max enclave size in 64-bit mode. This is a power-of-two value:
|
||||||
|
* if it is "36", then the max enclave size is 2^36 bytes (64 GiB).
|
||||||
|
*/
|
||||||
|
uint8_t max_enclave_64bit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* contains SGX feature flags. See the \ref cpu_sgx_feature_t
|
||||||
|
* "INTEL_SGX*" macros below.
|
||||||
|
*/
|
||||||
|
uint8_t flags[SGX_FLAGS_MAX];
|
||||||
|
|
||||||
|
/** number of Enclave Page Cache (EPC) sections. Info for each
|
||||||
|
* section is available through the \ref cpuid_get_epc() function
|
||||||
|
*/
|
||||||
|
int num_epc_sections;
|
||||||
|
|
||||||
|
/** bit vector of the supported extended features that can be written
|
||||||
|
* to the MISC region of the SSA (Save State Area)
|
||||||
|
*/
|
||||||
|
uint32_t misc_select;
|
||||||
|
|
||||||
|
/** a bit vector of the attributes that can be set to SECS.ATTRIBUTES
|
||||||
|
* via ECREATE. Corresponds to bits 0-63 (incl.) of SECS.ATTRIBUTES.
|
||||||
|
*/
|
||||||
|
uint64_t secs_attributes;
|
||||||
|
|
||||||
|
/** a bit vector of the bits that can be set in the XSAVE feature
|
||||||
|
* request mask; Corresponds to bits 64-127 of SECS.ATTRIBUTES.
|
||||||
|
*/
|
||||||
|
uint64_t secs_xfrm;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This contains the recognized CPU features/info
|
||||||
|
*/
|
||||||
|
struct cpu_id_t {
|
||||||
|
/** contains the CPU vendor string, e.g. "GenuineIntel" */
|
||||||
|
char vendor_str[VENDOR_STR_MAX];
|
||||||
|
|
||||||
|
/** contains the brand string, e.g. "Intel(R) Xeon(TM) CPU 2.40GHz" */
|
||||||
|
char brand_str[BRAND_STR_MAX];
|
||||||
|
|
||||||
|
/** contains the recognized CPU vendor */
|
||||||
|
cpu_vendor_t vendor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* contain CPU flags. Used to test for features. See
|
||||||
|
* the \ref cpu_feature_t "CPU_FEATURE_*" macros below.
|
||||||
|
* @see Features
|
||||||
|
*/
|
||||||
|
uint8_t flags[CPU_FLAGS_MAX];
|
||||||
|
|
||||||
|
/** CPU family */
|
||||||
|
int32_t family;
|
||||||
|
|
||||||
|
/** CPU model */
|
||||||
|
int32_t model;
|
||||||
|
|
||||||
|
/** CPU stepping */
|
||||||
|
int32_t stepping;
|
||||||
|
|
||||||
|
/** CPU extended family */
|
||||||
|
int32_t ext_family;
|
||||||
|
|
||||||
|
/** CPU extended model */
|
||||||
|
int32_t ext_model;
|
||||||
|
|
||||||
|
/** Number of CPU cores on the current processor */
|
||||||
|
int32_t num_cores;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of logical processors on the current processor.
|
||||||
|
* Could be more than the number of physical cores,
|
||||||
|
* e.g. when the processor has HyperThreading.
|
||||||
|
*/
|
||||||
|
int32_t num_logical_cpus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total number of logical processors.
|
||||||
|
* The same value is availabe through \ref cpuid_get_total_cpus.
|
||||||
|
*
|
||||||
|
* This is num_logical_cpus * {total physical processors in the system}
|
||||||
|
* (but only on a real system, under a VM this number may be lower).
|
||||||
|
*
|
||||||
|
* If you're writing a multithreaded program and you want to run it on
|
||||||
|
* all CPUs, this is the number of threads you need.
|
||||||
|
*
|
||||||
|
* @note in a VM, this will exactly match the number of CPUs set in
|
||||||
|
* the VM's configuration.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int32_t total_logical_cpus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* L1 data cache size in KB. Could be zero, if the CPU lacks cache.
|
||||||
|
* If the size cannot be determined, it will be -1.
|
||||||
|
*/
|
||||||
|
int32_t l1_data_cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* L1 instruction cache size in KB. Could be zero, if the CPU lacks
|
||||||
|
* cache. If the size cannot be determined, it will be -1.
|
||||||
|
* @note On some Intel CPUs, whose instruction cache is in fact
|
||||||
|
* a trace cache, the size will be expressed in K uOps.
|
||||||
|
*/
|
||||||
|
int32_t l1_instruction_cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* L2 cache size in KB. Could be zero, if the CPU lacks L2 cache.
|
||||||
|
* If the size of the cache could not be determined, it will be -1
|
||||||
|
*/
|
||||||
|
int32_t l2_cache;
|
||||||
|
|
||||||
|
/** L3 cache size in KB. Zero on most systems */
|
||||||
|
int32_t l3_cache;
|
||||||
|
|
||||||
|
/** L4 cache size in KB. Zero on most systems */
|
||||||
|
int32_t l4_cache;
|
||||||
|
|
||||||
|
/** Cache associativity for the L1 data cache. -1 if undetermined */
|
||||||
|
int32_t l1_assoc;
|
||||||
|
|
||||||
|
/** Cache associativity for the L2 cache. -1 if undetermined */
|
||||||
|
int32_t l2_assoc;
|
||||||
|
|
||||||
|
/** Cache associativity for the L3 cache. -1 if undetermined */
|
||||||
|
int32_t l3_assoc;
|
||||||
|
|
||||||
|
/** Cache associativity for the L4 cache. -1 if undetermined */
|
||||||
|
int32_t l4_assoc;
|
||||||
|
|
||||||
|
/** Cache-line size for L1 data cache. -1 if undetermined */
|
||||||
|
int32_t l1_cacheline;
|
||||||
|
|
||||||
|
/** Cache-line size for L2 cache. -1 if undetermined */
|
||||||
|
int32_t l2_cacheline;
|
||||||
|
|
||||||
|
/** Cache-line size for L3 cache. -1 if undetermined */
|
||||||
|
int32_t l3_cacheline;
|
||||||
|
|
||||||
|
/** Cache-line size for L4 cache. -1 if undetermined */
|
||||||
|
int32_t l4_cacheline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The brief and human-friendly CPU codename, which was recognized.<br>
|
||||||
|
* Examples:
|
||||||
|
* @code
|
||||||
|
* +--------+--------+-------+-------+-------+---------------------------------------+-----------------------+
|
||||||
|
* | Vendor | Family | Model | Step. | Cache | Brand String | cpu_id_t.cpu_codename |
|
||||||
|
* +--------+--------+-------+-------+-------+---------------------------------------+-----------------------+
|
||||||
|
* | AMD | 6 | 8 | 0 | 256 | (not available - will be ignored) | "K6-2" |
|
||||||
|
* | Intel | 15 | 2 | 5 | 512 | "Intel(R) Xeon(TM) CPU 2.40GHz" | "Xeon (Prestonia)" |
|
||||||
|
* | Intel | 6 | 15 | 11 | 4096 | "Intel(R) Core(TM)2 Duo CPU E6550..." | "Conroe (Core 2 Duo)" |
|
||||||
|
* | AMD | 15 | 35 | 2 | 1024 | "Dual Core AMD Opteron(tm) Proces..." | "Opteron (Dual Core)" |
|
||||||
|
* +--------+--------+-------+-------+-------+---------------------------------------+-----------------------+
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
char cpu_codename[64];
|
||||||
|
|
||||||
|
/** SSE execution unit size (64 or 128; -1 if N/A) */
|
||||||
|
int32_t sse_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* contain miscellaneous detection information. Used to test about specifics of
|
||||||
|
* certain detected features. See \ref cpu_hint_t "CPU_HINT_*" macros below.
|
||||||
|
* @see Hints
|
||||||
|
*/
|
||||||
|
uint8_t detection_hints[CPU_HINTS_MAX];
|
||||||
|
|
||||||
|
/** contains information about SGX features if the processor, if present */
|
||||||
|
struct cpu_sgx_t sgx;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CPU feature identifiers
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* @code
|
||||||
|
* ...
|
||||||
|
* struct cpu_raw_data_t raw;
|
||||||
|
* struct cpu_id_t id;
|
||||||
|
* if (cpuid_get_raw_data(&raw) == 0 && cpu_identify(&raw, &id) == 0) {
|
||||||
|
* if (id.flags[CPU_FEATURE_SSE2]) {
|
||||||
|
* // The CPU has SSE2...
|
||||||
|
* ...
|
||||||
|
* } else {
|
||||||
|
* // no SSE2
|
||||||
|
* }
|
||||||
|
* } else {
|
||||||
|
* // processor cannot be determined.
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
CPU_FEATURE_FPU = 0, /*!< Floating point unit */
|
||||||
|
CPU_FEATURE_VME, /*!< Virtual mode extension */
|
||||||
|
CPU_FEATURE_DE, /*!< Debugging extension */
|
||||||
|
CPU_FEATURE_PSE, /*!< Page size extension */
|
||||||
|
CPU_FEATURE_TSC, /*!< Time-stamp counter */
|
||||||
|
CPU_FEATURE_MSR, /*!< Model-specific regsisters, RDMSR/WRMSR supported */
|
||||||
|
CPU_FEATURE_PAE, /*!< Physical address extension */
|
||||||
|
CPU_FEATURE_MCE, /*!< Machine check exception */
|
||||||
|
CPU_FEATURE_CX8, /*!< CMPXCHG8B instruction supported */
|
||||||
|
CPU_FEATURE_APIC, /*!< APIC support */
|
||||||
|
CPU_FEATURE_MTRR, /*!< Memory type range registers */
|
||||||
|
CPU_FEATURE_SEP, /*!< SYSENTER / SYSEXIT instructions supported */
|
||||||
|
CPU_FEATURE_PGE, /*!< Page global enable */
|
||||||
|
CPU_FEATURE_MCA, /*!< Machine check architecture */
|
||||||
|
CPU_FEATURE_CMOV, /*!< CMOVxx instructions supported */
|
||||||
|
CPU_FEATURE_PAT, /*!< Page attribute table */
|
||||||
|
CPU_FEATURE_PSE36, /*!< 36-bit page address extension */
|
||||||
|
CPU_FEATURE_PN, /*!< Processor serial # implemented (Intel P3 only) */
|
||||||
|
CPU_FEATURE_CLFLUSH, /*!< CLFLUSH instruction supported */
|
||||||
|
CPU_FEATURE_DTS, /*!< Debug store supported */
|
||||||
|
CPU_FEATURE_ACPI, /*!< ACPI support (power states) */
|
||||||
|
CPU_FEATURE_MMX, /*!< MMX instruction set supported */
|
||||||
|
CPU_FEATURE_FXSR, /*!< FXSAVE / FXRSTOR supported */
|
||||||
|
CPU_FEATURE_SSE, /*!< Streaming-SIMD Extensions (SSE) supported */
|
||||||
|
CPU_FEATURE_SSE2, /*!< SSE2 instructions supported */
|
||||||
|
CPU_FEATURE_SS, /*!< Self-snoop */
|
||||||
|
CPU_FEATURE_HT, /*!< Hyper-threading supported (but might be disabled) */
|
||||||
|
CPU_FEATURE_TM, /*!< Thermal monitor */
|
||||||
|
CPU_FEATURE_IA64, /*!< IA64 supported (Itanium only) */
|
||||||
|
CPU_FEATURE_PBE, /*!< Pending-break enable */
|
||||||
|
CPU_FEATURE_PNI, /*!< PNI (SSE3) instructions supported */
|
||||||
|
CPU_FEATURE_PCLMUL, /*!< PCLMULQDQ instruction supported */
|
||||||
|
CPU_FEATURE_DTS64, /*!< 64-bit Debug store supported */
|
||||||
|
CPU_FEATURE_MONITOR, /*!< MONITOR / MWAIT supported */
|
||||||
|
CPU_FEATURE_DS_CPL, /*!< CPL Qualified Debug Store */
|
||||||
|
CPU_FEATURE_VMX, /*!< Virtualization technology supported */
|
||||||
|
CPU_FEATURE_SMX, /*!< Safer mode exceptions */
|
||||||
|
CPU_FEATURE_EST, /*!< Enhanced SpeedStep */
|
||||||
|
CPU_FEATURE_TM2, /*!< Thermal monitor 2 */
|
||||||
|
CPU_FEATURE_SSSE3, /*!< SSSE3 instructionss supported (this is different from SSE3!) */
|
||||||
|
CPU_FEATURE_CID, /*!< Context ID supported */
|
||||||
|
CPU_FEATURE_CX16, /*!< CMPXCHG16B instruction supported */
|
||||||
|
CPU_FEATURE_XTPR, /*!< Send Task Priority Messages disable */
|
||||||
|
CPU_FEATURE_PDCM, /*!< Performance capabilities MSR supported */
|
||||||
|
CPU_FEATURE_DCA, /*!< Direct cache access supported */
|
||||||
|
CPU_FEATURE_SSE4_1, /*!< SSE 4.1 instructions supported */
|
||||||
|
CPU_FEATURE_SSE4_2, /*!< SSE 4.2 instructions supported */
|
||||||
|
CPU_FEATURE_SYSCALL, /*!< SYSCALL / SYSRET instructions supported */
|
||||||
|
CPU_FEATURE_XD, /*!< Execute disable bit supported */
|
||||||
|
CPU_FEATURE_MOVBE, /*!< MOVBE instruction supported */
|
||||||
|
CPU_FEATURE_POPCNT, /*!< POPCNT instruction supported */
|
||||||
|
CPU_FEATURE_AES, /*!< AES* instructions supported */
|
||||||
|
CPU_FEATURE_XSAVE, /*!< XSAVE/XRSTOR/etc instructions supported */
|
||||||
|
CPU_FEATURE_OSXSAVE, /*!< non-privileged copy of OSXSAVE supported */
|
||||||
|
CPU_FEATURE_AVX, /*!< Advanced vector extensions supported */
|
||||||
|
CPU_FEATURE_MMXEXT, /*!< AMD MMX-extended instructions supported */
|
||||||
|
CPU_FEATURE_3DNOW, /*!< AMD 3DNow! instructions supported */
|
||||||
|
CPU_FEATURE_3DNOWEXT, /*!< AMD 3DNow! extended instructions supported */
|
||||||
|
CPU_FEATURE_NX, /*!< No-execute bit supported */
|
||||||
|
CPU_FEATURE_FXSR_OPT, /*!< FFXSR: FXSAVE and FXRSTOR optimizations */
|
||||||
|
CPU_FEATURE_RDTSCP, /*!< RDTSCP instruction supported (AMD-only) */
|
||||||
|
CPU_FEATURE_LM, /*!< Long mode (x86_64/EM64T) supported */
|
||||||
|
CPU_FEATURE_LAHF_LM, /*!< LAHF/SAHF supported in 64-bit mode */
|
||||||
|
CPU_FEATURE_CMP_LEGACY, /*!< core multi-processing legacy mode */
|
||||||
|
CPU_FEATURE_SVM, /*!< AMD Secure virtual machine */
|
||||||
|
CPU_FEATURE_ABM, /*!< LZCNT instruction support */
|
||||||
|
CPU_FEATURE_MISALIGNSSE,/*!< Misaligned SSE supported */
|
||||||
|
CPU_FEATURE_SSE4A, /*!< SSE 4a from AMD */
|
||||||
|
CPU_FEATURE_3DNOWPREFETCH, /*!< PREFETCH/PREFETCHW support */
|
||||||
|
CPU_FEATURE_OSVW, /*!< OS Visible Workaround (AMD) */
|
||||||
|
CPU_FEATURE_IBS, /*!< Instruction-based sampling */
|
||||||
|
CPU_FEATURE_SSE5, /*!< SSE 5 instructions supported (deprecated, will never be 1) */
|
||||||
|
CPU_FEATURE_SKINIT, /*!< SKINIT / STGI supported */
|
||||||
|
CPU_FEATURE_WDT, /*!< Watchdog timer support */
|
||||||
|
CPU_FEATURE_TS, /*!< Temperature sensor */
|
||||||
|
CPU_FEATURE_FID, /*!< Frequency ID control */
|
||||||
|
CPU_FEATURE_VID, /*!< Voltage ID control */
|
||||||
|
CPU_FEATURE_TTP, /*!< THERMTRIP */
|
||||||
|
CPU_FEATURE_TM_AMD, /*!< AMD-specified hardware thermal control */
|
||||||
|
CPU_FEATURE_STC, /*!< Software thermal control */
|
||||||
|
CPU_FEATURE_100MHZSTEPS,/*!< 100 MHz multiplier control */
|
||||||
|
CPU_FEATURE_HWPSTATE, /*!< Hardware P-state control */
|
||||||
|
CPU_FEATURE_CONSTANT_TSC, /*!< TSC ticks at constant rate */
|
||||||
|
CPU_FEATURE_XOP, /*!< The XOP instruction set (same as the old CPU_FEATURE_SSE5) */
|
||||||
|
CPU_FEATURE_FMA3, /*!< The FMA3 instruction set */
|
||||||
|
CPU_FEATURE_FMA4, /*!< The FMA4 instruction set */
|
||||||
|
CPU_FEATURE_TBM, /*!< Trailing bit manipulation instruction support */
|
||||||
|
CPU_FEATURE_F16C, /*!< 16-bit FP convert instruction support */
|
||||||
|
CPU_FEATURE_RDRAND, /*!< RdRand instruction */
|
||||||
|
CPU_FEATURE_X2APIC, /*!< x2APIC, APIC_BASE.EXTD, MSRs 0000_0800h...0000_0BFFh 64-bit ICR (+030h but not +031h), no DFR (+00Eh), SELF_IPI (+040h) also see standard level 0000_000Bh */
|
||||||
|
CPU_FEATURE_CPB, /*!< Core performance boost */
|
||||||
|
CPU_FEATURE_APERFMPERF, /*!< MPERF/APERF MSRs support */
|
||||||
|
CPU_FEATURE_PFI, /*!< Processor Feedback Interface support */
|
||||||
|
CPU_FEATURE_PA, /*!< Processor accumulator */
|
||||||
|
CPU_FEATURE_AVX2, /*!< AVX2 instructions */
|
||||||
|
CPU_FEATURE_BMI1, /*!< BMI1 instructions */
|
||||||
|
CPU_FEATURE_BMI2, /*!< BMI2 instructions */
|
||||||
|
CPU_FEATURE_HLE, /*!< Hardware Lock Elision prefixes */
|
||||||
|
CPU_FEATURE_RTM, /*!< Restricted Transactional Memory instructions */
|
||||||
|
CPU_FEATURE_AVX512F, /*!< AVX-512 Foundation */
|
||||||
|
CPU_FEATURE_AVX512DQ, /*!< AVX-512 Double/Quad granular insns */
|
||||||
|
CPU_FEATURE_AVX512PF, /*!< AVX-512 Prefetch */
|
||||||
|
CPU_FEATURE_AVX512ER, /*!< AVX-512 Exponential/Reciprocal */
|
||||||
|
CPU_FEATURE_AVX512CD, /*!< AVX-512 Conflict detection */
|
||||||
|
CPU_FEATURE_SHA_NI, /*!< SHA-1/SHA-256 instructions */
|
||||||
|
CPU_FEATURE_AVX512BW, /*!< AVX-512 Byte/Word granular insns */
|
||||||
|
CPU_FEATURE_AVX512VL, /*!< AVX-512 128/256 vector length extensions */
|
||||||
|
CPU_FEATURE_SGX, /*!< SGX extensions. Non-autoritative, check cpu_id_t::sgx::present to verify presence */
|
||||||
|
CPU_FEATURE_RDSEED, /*!< RDSEED instruction */
|
||||||
|
CPU_FEATURE_ADX, /*!< ADX extensions (arbitrary precision) */
|
||||||
|
/* termination: */
|
||||||
|
NUM_CPU_FEATURES,
|
||||||
|
} cpu_feature_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CPU detection hints identifiers
|
||||||
|
*
|
||||||
|
* Usage: similar to the flags usage
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
CPU_HINT_SSE_SIZE_AUTH = 0, /*!< SSE unit size is authoritative (not only a Family/Model guesswork, but based on an actual CPUID bit) */
|
||||||
|
/* termination */
|
||||||
|
NUM_CPU_HINTS,
|
||||||
|
} cpu_hint_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SGX features flags
|
||||||
|
* \see cpu_sgx_t
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* @code
|
||||||
|
* ...
|
||||||
|
* struct cpu_raw_data_t raw;
|
||||||
|
* struct cpu_id_t id;
|
||||||
|
* if (cpuid_get_raw_data(&raw) == 0 && cpu_identify(&raw, &id) == 0 && id.sgx.present) {
|
||||||
|
* if (id.sgx.flags[INTEL_SGX1])
|
||||||
|
* // The CPU has SGX1 instructions support...
|
||||||
|
* ...
|
||||||
|
* } else {
|
||||||
|
* // no SGX
|
||||||
|
* }
|
||||||
|
* } else {
|
||||||
|
* // processor cannot be determined.
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
INTEL_SGX1, /*!< SGX1 instructions support */
|
||||||
|
INTEL_SGX2, /*!< SGX2 instructions support */
|
||||||
|
|
||||||
|
/* termination: */
|
||||||
|
NUM_SGX_FEATURES,
|
||||||
|
} cpu_sgx_feature_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Describes common library error codes
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
ERR_OK = 0, /*!< "No error" */
|
||||||
|
ERR_NO_CPUID = -1, /*!< "CPUID instruction is not supported" */
|
||||||
|
ERR_NO_RDTSC = -2, /*!< "RDTSC instruction is not supported" */
|
||||||
|
ERR_NO_MEM = -3, /*!< "Memory allocation failed" */
|
||||||
|
ERR_OPEN = -4, /*!< "File open operation failed" */
|
||||||
|
ERR_BADFMT = -5, /*!< "Bad file format" */
|
||||||
|
ERR_NOT_IMP = -6, /*!< "Not implemented" */
|
||||||
|
ERR_CPU_UNKN = -7, /*!< "Unsupported processor" */
|
||||||
|
ERR_NO_RDMSR = -8, /*!< "RDMSR instruction is not supported" */
|
||||||
|
ERR_NO_DRIVER= -9, /*!< "RDMSR driver error (generic)" */
|
||||||
|
ERR_NO_PERMS = -10, /*!< "No permissions to install RDMSR driver" */
|
||||||
|
ERR_EXTRACT = -11, /*!< "Cannot extract RDMSR driver (read only media?)" */
|
||||||
|
ERR_HANDLE = -12, /*!< "Bad handle" */
|
||||||
|
ERR_INVMSR = -13, /*!< "Invalid MSR" */
|
||||||
|
ERR_INVCNB = -14, /*!< "Invalid core number" */
|
||||||
|
ERR_HANDLE_R = -15, /*!< "Error on handle read" */
|
||||||
|
ERR_INVRANGE = -16, /*!< "Invalid given range" */
|
||||||
|
} cpu_error_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Internal structure, used in cpu_tsc_mark, cpu_tsc_unmark and
|
||||||
|
* cpu_clock_by_mark
|
||||||
|
*/
|
||||||
|
struct cpu_mark_t {
|
||||||
|
uint64_t tsc; /*!< Time-stamp from RDTSC */
|
||||||
|
uint64_t sys_clock; /*!< In microsecond resolution */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the total number of logical CPU threads (even if CPUID is not present).
|
||||||
|
*
|
||||||
|
* Under VM, this number (and total_logical_cpus, since they are fetched with the same code)
|
||||||
|
* may be nonsensical, i.e. might not equal NumPhysicalCPUs*NumCoresPerCPU*HyperThreading.
|
||||||
|
* This is because no matter how many logical threads the host machine has, you may limit them
|
||||||
|
* in the VM to any number you like. **This** is the number returned by cpuid_get_total_cpus().
|
||||||
|
*
|
||||||
|
* @returns Number of logical CPU threads available. Equals the \ref cpu_id_t::total_logical_cpus.
|
||||||
|
*/
|
||||||
|
int cpuid_get_total_cpus(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if the CPUID instruction is supported
|
||||||
|
* @retval 1 if CPUID is present
|
||||||
|
* @retval 0 the CPU doesn't have CPUID.
|
||||||
|
*/
|
||||||
|
int cpuid_present(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Executes the CPUID instruction
|
||||||
|
* @param eax - the value of the EAX register when executing CPUID
|
||||||
|
* @param regs - the results will be stored here. regs[0] = EAX, regs[1] = EBX, ...
|
||||||
|
* @note CPUID will be executed with EAX set to the given value and EBX, ECX,
|
||||||
|
* EDX set to zero.
|
||||||
|
*/
|
||||||
|
void cpu_exec_cpuid(uint32_t eax, uint32_t* regs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Executes the CPUID instruction with the given input registers
|
||||||
|
* @note This is just a bit more generic version of cpu_exec_cpuid - it allows
|
||||||
|
* you to control all the registers.
|
||||||
|
* @param regs - Input/output. Prior to executing CPUID, EAX, EBX, ECX and
|
||||||
|
* EDX will be set to regs[0], regs[1], regs[2] and regs[3].
|
||||||
|
* After CPUID, this array will contain the results.
|
||||||
|
*/
|
||||||
|
void cpu_exec_cpuid_ext(uint32_t* regs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Obtains the raw CPUID data from the current CPU
|
||||||
|
* @param data - a pointer to cpu_raw_data_t structure
|
||||||
|
* @returns zero if successful, and some negative number on error.
|
||||||
|
* The error message can be obtained by calling \ref cpuid_error.
|
||||||
|
* @see cpu_error_t
|
||||||
|
*/
|
||||||
|
int cpuid_get_raw_data(struct cpu_raw_data_t* data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Identifies the CPU
|
||||||
|
* @param raw - Input - a pointer to the raw CPUID data, which is obtained
|
||||||
|
* either by cpuid_get_raw_data or cpuid_deserialize_raw_data.
|
||||||
|
* Can also be NULL, in which case the functions calls
|
||||||
|
* cpuid_get_raw_data itself.
|
||||||
|
* @param data - Output - the decoded CPU features/info is written here.
|
||||||
|
* @note The function will not fail, even if some of the information
|
||||||
|
* cannot be obtained. Even when the CPU is new and thus unknown to
|
||||||
|
* libcpuid, some generic info, such as "AMD K9 family CPU" will be
|
||||||
|
* written to data.cpu_codename, and most other things, such as the
|
||||||
|
* CPU flags, cache sizes, etc. should be detected correctly anyway.
|
||||||
|
* However, the function CAN fail, if the CPU is completely alien to
|
||||||
|
* libcpuid.
|
||||||
|
* @note While cpu_identify() and cpuid_get_raw_data() are fast for most
|
||||||
|
* purposes, running them several thousand times per second can hamper
|
||||||
|
* performance significantly. Specifically, avoid writing "cpu feature
|
||||||
|
* checker" wrapping function, which calls cpu_identify and returns the
|
||||||
|
* value of some flag, if that function is going to be called frequently.
|
||||||
|
* @returns zero if successful, and some negative number on error.
|
||||||
|
* The error message can be obtained by calling \ref cpuid_error.
|
||||||
|
* @see cpu_error_t
|
||||||
|
*/
|
||||||
|
int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The return value of cpuid_get_epc().
|
||||||
|
* @details
|
||||||
|
* Describes an EPC (Enclave Page Cache) layout (physical address and size).
|
||||||
|
* A CPU may have one or more EPC areas, and information about each is
|
||||||
|
* fetched via \ref cpuid_get_epc.
|
||||||
|
*/
|
||||||
|
struct cpu_epc_t {
|
||||||
|
uint64_t start_addr;
|
||||||
|
uint64_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Fetches information about an EPC (Enclave Page Cache) area.
|
||||||
|
* @param index - zero-based index, valid range [0..cpu_id_t.egx.num_epc_sections)
|
||||||
|
* @param raw - a pointer to fetched raw CPUID data. Needed only for testing,
|
||||||
|
* you can safely pass NULL here (if you pass a real structure,
|
||||||
|
* it will be used for fetching the leaf 12h data if index < 2;
|
||||||
|
* otherwise the real CPUID instruction will be used).
|
||||||
|
* @returns the requested data. If the CPU doesn't support SGX, or if
|
||||||
|
* index >= cpu_id_t.egx.num_epc_sections, both fields of the returned
|
||||||
|
* structure will be zeros.
|
||||||
|
*/
|
||||||
|
struct cpu_epc_t cpuid_get_epc(int index, const struct cpu_raw_data_t* raw);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the libcpuid version
|
||||||
|
*
|
||||||
|
* @returns the string representation of the libcpuid version, like "0.1.1"
|
||||||
|
*/
|
||||||
|
const char* cpuid_lib_version(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}; /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#endif /* __LIBCPUID_H__ */
|
||||||
47
src/3rdparty/libcpuid/libcpuid_constants.h
vendored
Normal file
47
src/3rdparty/libcpuid/libcpuid_constants.h
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @File libcpuid_constants.h
|
||||||
|
* @Author Veselin Georgiev
|
||||||
|
* @Brief Some limits and constants for libcpuid
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBCPUID_CONSTANTS_H__
|
||||||
|
#define __LIBCPUID_CONSTANTS_H__
|
||||||
|
|
||||||
|
#define VENDOR_STR_MAX 16
|
||||||
|
#define BRAND_STR_MAX 64
|
||||||
|
#define CPU_FLAGS_MAX 128
|
||||||
|
#define MAX_CPUID_LEVEL 32
|
||||||
|
#define MAX_EXT_CPUID_LEVEL 32
|
||||||
|
#define MAX_INTELFN4_LEVEL 8
|
||||||
|
#define MAX_INTELFN11_LEVEL 4
|
||||||
|
#define MAX_INTELFN12H_LEVEL 4
|
||||||
|
#define MAX_INTELFN14H_LEVEL 4
|
||||||
|
#define CPU_HINTS_MAX 16
|
||||||
|
#define SGX_FLAGS_MAX 14
|
||||||
|
|
||||||
|
#endif /* __LIBCPUID_CONSTANTS_H__ */
|
||||||
106
src/3rdparty/libcpuid/libcpuid_internal.h
vendored
Normal file
106
src/3rdparty/libcpuid/libcpuid_internal.h
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
#ifndef __LIBCPUID_INTERNAL_H__
|
||||||
|
#define __LIBCPUID_INTERNAL_H__
|
||||||
|
/*
|
||||||
|
* This file contains internal undocumented declarations and function prototypes
|
||||||
|
* for the workings of the internal library infrastructure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum _common_codes_t {
|
||||||
|
NA = 0,
|
||||||
|
NC, /* No code */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CODE(x) x
|
||||||
|
#define CODE2(x, y) x = y
|
||||||
|
enum _amd_code_t {
|
||||||
|
#include "amd_code_t.h"
|
||||||
|
};
|
||||||
|
typedef enum _amd_code_t amd_code_t;
|
||||||
|
|
||||||
|
enum _intel_code_t {
|
||||||
|
#include "intel_code_t.h"
|
||||||
|
};
|
||||||
|
typedef enum _intel_code_t intel_code_t;
|
||||||
|
#undef CODE
|
||||||
|
#undef CODE2
|
||||||
|
|
||||||
|
struct internal_id_info_t {
|
||||||
|
union {
|
||||||
|
amd_code_t amd;
|
||||||
|
intel_code_t intel;
|
||||||
|
} code;
|
||||||
|
uint64_t bits;
|
||||||
|
int score; // detection (matchtable) score
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LBIT(x) (((long long) 1) << x)
|
||||||
|
|
||||||
|
enum _common_bits_t {
|
||||||
|
_M_ = LBIT( 0 ),
|
||||||
|
MOBILE_ = LBIT( 1 ),
|
||||||
|
_MP_ = LBIT( 2 ),
|
||||||
|
};
|
||||||
|
|
||||||
|
// additional detection bits for Intel CPUs:
|
||||||
|
enum _intel_bits_t {
|
||||||
|
PENTIUM_ = LBIT( 10 ),
|
||||||
|
CELERON_ = LBIT( 11 ),
|
||||||
|
CORE_ = LBIT( 12 ),
|
||||||
|
_I_ = LBIT( 13 ),
|
||||||
|
_3 = LBIT( 14 ),
|
||||||
|
_5 = LBIT( 15 ),
|
||||||
|
_7 = LBIT( 16 ),
|
||||||
|
XEON_ = LBIT( 17 ),
|
||||||
|
ATOM_ = LBIT( 18 ),
|
||||||
|
};
|
||||||
|
typedef enum _intel_bits_t intel_bits_t;
|
||||||
|
|
||||||
|
enum _amd_bits_t {
|
||||||
|
ATHLON_ = LBIT( 10 ),
|
||||||
|
_XP_ = LBIT( 11 ),
|
||||||
|
DURON_ = LBIT( 12 ),
|
||||||
|
SEMPRON_ = LBIT( 13 ),
|
||||||
|
OPTERON_ = LBIT( 14 ),
|
||||||
|
TURION_ = LBIT( 15 ),
|
||||||
|
_LV_ = LBIT( 16 ),
|
||||||
|
_64_ = LBIT( 17 ),
|
||||||
|
_X2 = LBIT( 18 ),
|
||||||
|
_X3 = LBIT( 19 ),
|
||||||
|
_X4 = LBIT( 20 ),
|
||||||
|
_X6 = LBIT( 21 ),
|
||||||
|
_FX = LBIT( 22 ),
|
||||||
|
_APU_ = LBIT( 23 ),
|
||||||
|
};
|
||||||
|
typedef enum _amd_bits_t amd_bits_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cpu_ident_internal(struct cpu_raw_data_t* raw, struct cpu_id_t* data,
|
||||||
|
struct internal_id_info_t* internal);
|
||||||
|
|
||||||
|
#endif /* __LIBCPUID_INTERNAL_H__ */
|
||||||
37
src/3rdparty/libcpuid/libcpuid_types.h
vendored
Normal file
37
src/3rdparty/libcpuid/libcpuid_types.h
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @File libcpuid_types.h
|
||||||
|
* @Author Veselin Georgiev
|
||||||
|
* @Brief Type specifications for libcpuid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBCPUID_TYPES_H__
|
||||||
|
#define __LIBCPUID_TYPES_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#endif /* __LIBCPUID_TYPES_H__ */
|
||||||
93
src/3rdparty/libcpuid/libcpuid_util.c
vendored
Normal file
93
src/3rdparty/libcpuid/libcpuid_util.c
vendored
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "libcpuid.h"
|
||||||
|
#include "libcpuid_util.h"
|
||||||
|
|
||||||
|
void match_features(const struct feature_map_t* matchtable, int count, uint32_t reg, struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
if (reg & (1u << matchtable[i].bit))
|
||||||
|
data->flags[matchtable[i].feature] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xmatch_entry(char c, const char* p)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
if (c == 0) return -1;
|
||||||
|
if (c == p[0]) return 1;
|
||||||
|
if (p[0] == '.') return 1;
|
||||||
|
if (p[0] == '#' && isdigit(c)) return 1;
|
||||||
|
if (p[0] == '[') {
|
||||||
|
j = 1;
|
||||||
|
while (p[j] && p[j] != ']') j++;
|
||||||
|
if (!p[j]) return -1;
|
||||||
|
for (i = 1; i < j; i++)
|
||||||
|
if (p[i] == c) return j + 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int match_pattern(const char* s, const char* p)
|
||||||
|
{
|
||||||
|
int i, j, dj, k, n, m;
|
||||||
|
n = (int) strlen(s);
|
||||||
|
m = (int) strlen(p);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (xmatch_entry(s[i], p) != -1) {
|
||||||
|
j = 0;
|
||||||
|
k = 0;
|
||||||
|
while (j < m && ((dj = xmatch_entry(s[i + k], p + j)) != -1)) {
|
||||||
|
k++;
|
||||||
|
j += dj;
|
||||||
|
}
|
||||||
|
if (j == m) return i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cpu_id_t* get_cached_cpuid(void)
|
||||||
|
{
|
||||||
|
static int initialized = 0;
|
||||||
|
static struct cpu_id_t id;
|
||||||
|
if (initialized) return &id;
|
||||||
|
if (cpu_identify(NULL, &id))
|
||||||
|
memset(&id, 0, sizeof(id));
|
||||||
|
initialized = 1;
|
||||||
|
return &id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int match_all(uint64_t bits, uint64_t mask)
|
||||||
|
{
|
||||||
|
return (bits & mask) == mask;
|
||||||
|
}
|
||||||
78
src/3rdparty/libcpuid/libcpuid_util.h
vendored
Normal file
78
src/3rdparty/libcpuid/libcpuid_util.h
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
#ifndef __LIBCPUID_UTIL_H__
|
||||||
|
#define __LIBCPUID_UTIL_H__
|
||||||
|
|
||||||
|
#define COUNT_OF(array) (sizeof(array) / sizeof(array[0]))
|
||||||
|
|
||||||
|
struct feature_map_t {
|
||||||
|
unsigned bit;
|
||||||
|
cpu_feature_t feature;
|
||||||
|
};
|
||||||
|
|
||||||
|
void match_features(const struct feature_map_t* matchtable, int count,
|
||||||
|
uint32_t reg, struct cpu_id_t* data);
|
||||||
|
|
||||||
|
struct match_entry_t {
|
||||||
|
int family, model, stepping, ext_family, ext_model;
|
||||||
|
int ncores, l2cache, l3cache, brand_code;
|
||||||
|
uint64_t model_bits;
|
||||||
|
int model_code;
|
||||||
|
char name[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
// returns the match score:
|
||||||
|
int match_cpu_codename(const struct match_entry_t* matchtable, int count,
|
||||||
|
struct cpu_id_t* data, int brand_code, uint64_t bits,
|
||||||
|
int model_code);
|
||||||
|
/*
|
||||||
|
* Seek for a pattern in `haystack'.
|
||||||
|
* Pattern may be an fixed string, or contain the special metacharacters
|
||||||
|
* '.' - match any single character
|
||||||
|
* '#' - match any digit
|
||||||
|
* '[<chars>] - match any of the given chars (regex-like ranges are not
|
||||||
|
* supported)
|
||||||
|
* Return val: 0 if the pattern is not found. Nonzero if it is found (actually,
|
||||||
|
* x + 1 where x is the index where the match is found).
|
||||||
|
*/
|
||||||
|
int match_pattern(const char* haystack, const char* pattern);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets an initialized cpu_id_t. It is cached, so that internal libcpuid
|
||||||
|
* machinery doesn't need to issue cpu_identify more than once.
|
||||||
|
*/
|
||||||
|
struct cpu_id_t* get_cached_cpuid(void);
|
||||||
|
|
||||||
|
|
||||||
|
/* returns true if all bits of mask are present in `bits'. */
|
||||||
|
int match_all(uint64_t bits, uint64_t mask);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets the current errno
|
||||||
|
*/
|
||||||
|
int set_error(cpu_error_t err);
|
||||||
|
|
||||||
|
#endif /* __LIBCPUID_UTIL_H__ */
|
||||||
359
src/3rdparty/libcpuid/masm-x64.asm
vendored
Normal file
359
src/3rdparty/libcpuid/masm-x64.asm
vendored
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
|
||||||
|
.code
|
||||||
|
; procedure exec_cpuid
|
||||||
|
; Signature: void exec_cpiud(uint32_t *regs)
|
||||||
|
exec_cpuid Proc
|
||||||
|
push rbx
|
||||||
|
push rcx
|
||||||
|
push rdx
|
||||||
|
push rdi
|
||||||
|
|
||||||
|
mov rdi, rcx
|
||||||
|
|
||||||
|
mov eax, [rdi]
|
||||||
|
mov ebx, [rdi+4]
|
||||||
|
mov ecx, [rdi+8]
|
||||||
|
mov edx, [rdi+12]
|
||||||
|
|
||||||
|
cpuid
|
||||||
|
|
||||||
|
mov [rdi], eax
|
||||||
|
mov [rdi+4], ebx
|
||||||
|
mov [rdi+8], ecx
|
||||||
|
mov [rdi+12], edx
|
||||||
|
pop rdi
|
||||||
|
pop rdx
|
||||||
|
pop rcx
|
||||||
|
pop rbx
|
||||||
|
ret
|
||||||
|
exec_cpuid endp
|
||||||
|
|
||||||
|
; procedure cpu_rdtsc
|
||||||
|
; Signature: void cpu_rdtsc(uint64_t *result)
|
||||||
|
cpu_rdtsc Proc
|
||||||
|
push rdx
|
||||||
|
rdtsc
|
||||||
|
mov [rcx], eax
|
||||||
|
mov [rcx+4], edx
|
||||||
|
pop rdx
|
||||||
|
ret
|
||||||
|
cpu_rdtsc endp
|
||||||
|
|
||||||
|
; procedure busy_sse_loop
|
||||||
|
; Signature: void busy_sse_loop(int cycles)
|
||||||
|
busy_sse_loop Proc
|
||||||
|
; save xmm6 & xmm7 into the shadow area, as Visual C++ 2008
|
||||||
|
; expects that we don't touch them:
|
||||||
|
movups [rsp + 8], xmm6
|
||||||
|
movups [rsp + 24], xmm7
|
||||||
|
|
||||||
|
xorps xmm0, xmm0
|
||||||
|
xorps xmm1, xmm1
|
||||||
|
xorps xmm2, xmm2
|
||||||
|
xorps xmm3, xmm3
|
||||||
|
xorps xmm4, xmm4
|
||||||
|
xorps xmm5, xmm5
|
||||||
|
xorps xmm6, xmm6
|
||||||
|
xorps xmm7, xmm7
|
||||||
|
; --
|
||||||
|
align 16
|
||||||
|
bsLoop:
|
||||||
|
; 0:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 1:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 2:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 3:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 4:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 5:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 6:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 7:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 8:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 9:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 10:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 11:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 12:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 13:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 14:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 15:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 16:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 17:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 18:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 19:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 20:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 21:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 22:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 23:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 24:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 25:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 26:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 27:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 28:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 29:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 30:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; 31:
|
||||||
|
addps xmm0, xmm1
|
||||||
|
addps xmm1, xmm2
|
||||||
|
addps xmm2, xmm3
|
||||||
|
addps xmm3, xmm4
|
||||||
|
addps xmm4, xmm5
|
||||||
|
addps xmm5, xmm6
|
||||||
|
addps xmm6, xmm7
|
||||||
|
addps xmm7, xmm0
|
||||||
|
; ----------------------
|
||||||
|
dec ecx
|
||||||
|
jnz bsLoop
|
||||||
|
|
||||||
|
; restore xmm6 & xmm7:
|
||||||
|
movups xmm6, [rsp + 8]
|
||||||
|
movups xmm7, [rsp + 24]
|
||||||
|
ret
|
||||||
|
busy_sse_loop endp
|
||||||
|
|
||||||
|
END
|
||||||
169
src/3rdparty/libcpuid/recog_amd.c
vendored
Normal file
169
src/3rdparty/libcpuid/recog_amd.c
vendored
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "libcpuid.h"
|
||||||
|
#include "libcpuid_util.h"
|
||||||
|
#include "libcpuid_internal.h"
|
||||||
|
#include "recog_amd.h"
|
||||||
|
|
||||||
|
const struct amd_code_str { amd_code_t code; char *str; } amd_code_str[] = {
|
||||||
|
#define CODE(x) { x, #x }
|
||||||
|
#define CODE2(x, y) CODE(x)
|
||||||
|
#include "amd_code_t.h"
|
||||||
|
#undef CODE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct amd_code_and_bits_t {
|
||||||
|
int code;
|
||||||
|
uint64_t bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum _amd_model_codes_t {
|
||||||
|
// Only for Ryzen CPUs:
|
||||||
|
_1400,
|
||||||
|
_1500,
|
||||||
|
_1600,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
const struct feature_map_t matchtable_edx81[] = {
|
||||||
|
{ 20, CPU_FEATURE_NX },
|
||||||
|
{ 22, CPU_FEATURE_MMXEXT },
|
||||||
|
{ 25, CPU_FEATURE_FXSR_OPT },
|
||||||
|
{ 30, CPU_FEATURE_3DNOWEXT },
|
||||||
|
{ 31, CPU_FEATURE_3DNOW },
|
||||||
|
};
|
||||||
|
const struct feature_map_t matchtable_ecx81[] = {
|
||||||
|
{ 1, CPU_FEATURE_CMP_LEGACY },
|
||||||
|
{ 2, CPU_FEATURE_SVM },
|
||||||
|
{ 5, CPU_FEATURE_ABM },
|
||||||
|
{ 6, CPU_FEATURE_SSE4A },
|
||||||
|
{ 7, CPU_FEATURE_MISALIGNSSE },
|
||||||
|
{ 8, CPU_FEATURE_3DNOWPREFETCH },
|
||||||
|
{ 9, CPU_FEATURE_OSVW },
|
||||||
|
{ 10, CPU_FEATURE_IBS },
|
||||||
|
{ 11, CPU_FEATURE_XOP },
|
||||||
|
{ 12, CPU_FEATURE_SKINIT },
|
||||||
|
{ 13, CPU_FEATURE_WDT },
|
||||||
|
{ 16, CPU_FEATURE_FMA4 },
|
||||||
|
{ 21, CPU_FEATURE_TBM },
|
||||||
|
};
|
||||||
|
const struct feature_map_t matchtable_edx87[] = {
|
||||||
|
{ 0, CPU_FEATURE_TS },
|
||||||
|
{ 1, CPU_FEATURE_FID },
|
||||||
|
{ 2, CPU_FEATURE_VID },
|
||||||
|
{ 3, CPU_FEATURE_TTP },
|
||||||
|
{ 4, CPU_FEATURE_TM_AMD },
|
||||||
|
{ 5, CPU_FEATURE_STC },
|
||||||
|
{ 6, CPU_FEATURE_100MHZSTEPS },
|
||||||
|
{ 7, CPU_FEATURE_HWPSTATE },
|
||||||
|
/* id 8 is handled in common */
|
||||||
|
{ 9, CPU_FEATURE_CPB },
|
||||||
|
{ 10, CPU_FEATURE_APERFMPERF },
|
||||||
|
{ 11, CPU_FEATURE_PFI },
|
||||||
|
{ 12, CPU_FEATURE_PA },
|
||||||
|
};
|
||||||
|
if (raw->ext_cpuid[0][0] >= 0x80000001) {
|
||||||
|
match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
|
||||||
|
match_features(matchtable_ecx81, COUNT_OF(matchtable_ecx81), raw->ext_cpuid[1][2], data);
|
||||||
|
}
|
||||||
|
if (raw->ext_cpuid[0][0] >= 0x80000007)
|
||||||
|
match_features(matchtable_edx87, COUNT_OF(matchtable_edx87), raw->ext_cpuid[7][3], data);
|
||||||
|
if (raw->ext_cpuid[0][0] >= 0x8000001a) {
|
||||||
|
/* We have the extended info about SSE unit size */
|
||||||
|
data->detection_hints[CPU_HINT_SSE_SIZE_AUTH] = 1;
|
||||||
|
data->sse_size = (raw->ext_cpuid[0x1a][0] & 1) ? 128 : 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decode_amd_cache_info(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
int l3_result;
|
||||||
|
const int assoc_table[16] = {
|
||||||
|
0, 1, 2, 0, 4, 0, 8, 0, 16, 0, 32, 48, 64, 96, 128, 255
|
||||||
|
};
|
||||||
|
unsigned n = raw->ext_cpuid[0][0];
|
||||||
|
|
||||||
|
if (n >= 0x80000005) {
|
||||||
|
data->l1_data_cache = (raw->ext_cpuid[5][2] >> 24) & 0xff;
|
||||||
|
data->l1_assoc = (raw->ext_cpuid[5][2] >> 16) & 0xff;
|
||||||
|
data->l1_cacheline = (raw->ext_cpuid[5][2]) & 0xff;
|
||||||
|
data->l1_instruction_cache = (raw->ext_cpuid[5][3] >> 24) & 0xff;
|
||||||
|
}
|
||||||
|
if (n >= 0x80000006) {
|
||||||
|
data->l2_cache = (raw->ext_cpuid[6][2] >> 16) & 0xffff;
|
||||||
|
data->l2_assoc = assoc_table[(raw->ext_cpuid[6][2] >> 12) & 0xf];
|
||||||
|
data->l2_cacheline = (raw->ext_cpuid[6][2]) & 0xff;
|
||||||
|
|
||||||
|
l3_result = (raw->ext_cpuid[6][3] >> 18);
|
||||||
|
if (l3_result > 0) {
|
||||||
|
l3_result = 512 * l3_result; /* AMD spec says it's a range,
|
||||||
|
but we take the lower bound */
|
||||||
|
data->l3_cache = l3_result;
|
||||||
|
data->l3_assoc = assoc_table[(raw->ext_cpuid[6][3] >> 12) & 0xf];
|
||||||
|
data->l3_cacheline = (raw->ext_cpuid[6][3]) & 0xff;
|
||||||
|
} else {
|
||||||
|
data->l3_cache = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decode_amd_number_of_cores(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
int logical_cpus = -1, num_cores = -1;
|
||||||
|
|
||||||
|
if (raw->basic_cpuid[0][0] >= 1) {
|
||||||
|
logical_cpus = (raw->basic_cpuid[1][1] >> 16) & 0xff;
|
||||||
|
if (raw->ext_cpuid[0][0] >= 8) {
|
||||||
|
num_cores = 1 + (raw->ext_cpuid[8][2] & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data->flags[CPU_FEATURE_HT]) {
|
||||||
|
if (num_cores > 1) {
|
||||||
|
if (data->ext_family >= 23)
|
||||||
|
num_cores /= 2; // e.g., Ryzen 7 reports 16 "real" cores, but they are really just 8.
|
||||||
|
data->num_cores = num_cores;
|
||||||
|
data->num_logical_cpus = logical_cpus;
|
||||||
|
} else {
|
||||||
|
data->num_cores = 1;
|
||||||
|
data->num_logical_cpus = (logical_cpus >= 2 ? logical_cpus : 2);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data->num_cores = data->num_logical_cpus = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
|
||||||
|
{
|
||||||
|
load_amd_features(raw, data);
|
||||||
|
decode_amd_cache_info(raw, data);
|
||||||
|
decode_amd_number_of_cores(raw, data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
31
src/3rdparty/libcpuid/recog_amd.h
vendored
Normal file
31
src/3rdparty/libcpuid/recog_amd.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
#ifndef __RECOG_AMD_H__
|
||||||
|
#define __RECOG_AMD_H__
|
||||||
|
|
||||||
|
int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal);
|
||||||
|
|
||||||
|
#endif /* __RECOG_AMD_H__ */
|
||||||
542
src/3rdparty/libcpuid/recog_intel.c
vendored
Normal file
542
src/3rdparty/libcpuid/recog_intel.c
vendored
Normal file
@@ -0,0 +1,542 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "libcpuid.h"
|
||||||
|
#include "libcpuid_util.h"
|
||||||
|
#include "libcpuid_internal.h"
|
||||||
|
#include "recog_intel.h"
|
||||||
|
|
||||||
|
const struct intel_bcode_str { intel_code_t code; char *str; } intel_bcode_str[] = {
|
||||||
|
#define CODE(x) { x, #x }
|
||||||
|
#define CODE2(x, y) CODE(x)
|
||||||
|
#include "intel_code_t.h"
|
||||||
|
#undef CODE
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int code;
|
||||||
|
uint64_t bits;
|
||||||
|
} intel_code_and_bits_t;
|
||||||
|
|
||||||
|
enum _intel_model_t {
|
||||||
|
UNKNOWN = -1,
|
||||||
|
_3000 = 100,
|
||||||
|
_3100,
|
||||||
|
_3200,
|
||||||
|
X3200,
|
||||||
|
_3300,
|
||||||
|
X3300,
|
||||||
|
_5100,
|
||||||
|
_5200,
|
||||||
|
_5300,
|
||||||
|
_5400,
|
||||||
|
_2xxx, /* Core i[357] 2xxx */
|
||||||
|
_3xxx, /* Core i[357] 3xxx */
|
||||||
|
};
|
||||||
|
typedef enum _intel_model_t intel_model_t;
|
||||||
|
|
||||||
|
static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
const struct feature_map_t matchtable_edx1[] = {
|
||||||
|
{ 18, CPU_FEATURE_PN },
|
||||||
|
{ 21, CPU_FEATURE_DTS },
|
||||||
|
{ 22, CPU_FEATURE_ACPI },
|
||||||
|
{ 27, CPU_FEATURE_SS },
|
||||||
|
{ 29, CPU_FEATURE_TM },
|
||||||
|
{ 30, CPU_FEATURE_IA64 },
|
||||||
|
{ 31, CPU_FEATURE_PBE },
|
||||||
|
};
|
||||||
|
const struct feature_map_t matchtable_ecx1[] = {
|
||||||
|
{ 2, CPU_FEATURE_DTS64 },
|
||||||
|
{ 4, CPU_FEATURE_DS_CPL },
|
||||||
|
{ 5, CPU_FEATURE_VMX },
|
||||||
|
{ 6, CPU_FEATURE_SMX },
|
||||||
|
{ 7, CPU_FEATURE_EST },
|
||||||
|
{ 8, CPU_FEATURE_TM2 },
|
||||||
|
{ 10, CPU_FEATURE_CID },
|
||||||
|
{ 14, CPU_FEATURE_XTPR },
|
||||||
|
{ 15, CPU_FEATURE_PDCM },
|
||||||
|
{ 18, CPU_FEATURE_DCA },
|
||||||
|
{ 21, CPU_FEATURE_X2APIC },
|
||||||
|
};
|
||||||
|
const struct feature_map_t matchtable_edx81[] = {
|
||||||
|
{ 20, CPU_FEATURE_XD },
|
||||||
|
};
|
||||||
|
const struct feature_map_t matchtable_ebx7[] = {
|
||||||
|
{ 2, CPU_FEATURE_SGX },
|
||||||
|
{ 4, CPU_FEATURE_HLE },
|
||||||
|
{ 11, CPU_FEATURE_RTM },
|
||||||
|
{ 16, CPU_FEATURE_AVX512F },
|
||||||
|
{ 17, CPU_FEATURE_AVX512DQ },
|
||||||
|
{ 18, CPU_FEATURE_RDSEED },
|
||||||
|
{ 19, CPU_FEATURE_ADX },
|
||||||
|
{ 26, CPU_FEATURE_AVX512PF },
|
||||||
|
{ 27, CPU_FEATURE_AVX512ER },
|
||||||
|
{ 28, CPU_FEATURE_AVX512CD },
|
||||||
|
{ 29, CPU_FEATURE_SHA_NI },
|
||||||
|
{ 30, CPU_FEATURE_AVX512BW },
|
||||||
|
{ 31, CPU_FEATURE_AVX512VL },
|
||||||
|
};
|
||||||
|
if (raw->basic_cpuid[0][0] >= 1) {
|
||||||
|
match_features(matchtable_edx1, COUNT_OF(matchtable_edx1), raw->basic_cpuid[1][3], data);
|
||||||
|
match_features(matchtable_ecx1, COUNT_OF(matchtable_ecx1), raw->basic_cpuid[1][2], data);
|
||||||
|
}
|
||||||
|
if (raw->ext_cpuid[0][0] >= 1) {
|
||||||
|
match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
|
||||||
|
}
|
||||||
|
// detect TSX/AVX512:
|
||||||
|
if (raw->basic_cpuid[0][0] >= 7) {
|
||||||
|
match_features(matchtable_ebx7, COUNT_OF(matchtable_ebx7), raw->basic_cpuid[7][1], data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum _cache_type_t {
|
||||||
|
L1I,
|
||||||
|
L1D,
|
||||||
|
L2,
|
||||||
|
L3,
|
||||||
|
L4
|
||||||
|
};
|
||||||
|
typedef enum _cache_type_t cache_type_t;
|
||||||
|
|
||||||
|
static void check_case(uint8_t on, cache_type_t cache, int size, int assoc, int linesize, struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
if (!on) return;
|
||||||
|
switch (cache) {
|
||||||
|
case L1I:
|
||||||
|
data->l1_instruction_cache = size;
|
||||||
|
break;
|
||||||
|
case L1D:
|
||||||
|
data->l1_data_cache = size;
|
||||||
|
data->l1_assoc = assoc;
|
||||||
|
data->l1_cacheline = linesize;
|
||||||
|
break;
|
||||||
|
case L2:
|
||||||
|
data->l2_cache = size;
|
||||||
|
data->l2_assoc = assoc;
|
||||||
|
data->l2_cacheline = linesize;
|
||||||
|
break;
|
||||||
|
case L3:
|
||||||
|
data->l3_cache = size;
|
||||||
|
data->l3_assoc = assoc;
|
||||||
|
data->l3_cacheline = linesize;
|
||||||
|
break;
|
||||||
|
case L4:
|
||||||
|
data->l4_cache = size;
|
||||||
|
data->l4_assoc = assoc;
|
||||||
|
data->l4_cacheline = linesize;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decode_intel_oldstyle_cache_info(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
uint8_t f[256] = {0};
|
||||||
|
int reg, off;
|
||||||
|
uint32_t x;
|
||||||
|
for (reg = 0; reg < 4; reg++) {
|
||||||
|
x = raw->basic_cpuid[2][reg];
|
||||||
|
if (x & 0x80000000) continue;
|
||||||
|
for (off = 0; off < 4; off++) {
|
||||||
|
f[x & 0xff] = 1;
|
||||||
|
x >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check_case(f[0x06], L1I, 8, 4, 32, data);
|
||||||
|
check_case(f[0x08], L1I, 16, 4, 32, data);
|
||||||
|
check_case(f[0x0A], L1D, 8, 2, 32, data);
|
||||||
|
check_case(f[0x0C], L1D, 16, 4, 32, data);
|
||||||
|
check_case(f[0x22], L3, 512, 4, 64, data);
|
||||||
|
check_case(f[0x23], L3, 1024, 8, 64, data);
|
||||||
|
check_case(f[0x25], L3, 2048, 8, 64, data);
|
||||||
|
check_case(f[0x29], L3, 4096, 8, 64, data);
|
||||||
|
check_case(f[0x2C], L1D, 32, 8, 64, data);
|
||||||
|
check_case(f[0x30], L1I, 32, 8, 64, data);
|
||||||
|
check_case(f[0x39], L2, 128, 4, 64, data);
|
||||||
|
check_case(f[0x3A], L2, 192, 6, 64, data);
|
||||||
|
check_case(f[0x3B], L2, 128, 2, 64, data);
|
||||||
|
check_case(f[0x3C], L2, 256, 4, 64, data);
|
||||||
|
check_case(f[0x3D], L2, 384, 6, 64, data);
|
||||||
|
check_case(f[0x3E], L2, 512, 4, 64, data);
|
||||||
|
check_case(f[0x41], L2, 128, 4, 32, data);
|
||||||
|
check_case(f[0x42], L2, 256, 4, 32, data);
|
||||||
|
check_case(f[0x43], L2, 512, 4, 32, data);
|
||||||
|
check_case(f[0x44], L2, 1024, 4, 32, data);
|
||||||
|
check_case(f[0x45], L2, 2048, 4, 32, data);
|
||||||
|
check_case(f[0x46], L3, 4096, 4, 64, data);
|
||||||
|
check_case(f[0x47], L3, 8192, 8, 64, data);
|
||||||
|
check_case(f[0x4A], L3, 6144, 12, 64, data);
|
||||||
|
check_case(f[0x4B], L3, 8192, 16, 64, data);
|
||||||
|
check_case(f[0x4C], L3, 12288, 12, 64, data);
|
||||||
|
check_case(f[0x4D], L3, 16384, 16, 64, data);
|
||||||
|
check_case(f[0x4E], L2, 6144, 24, 64, data);
|
||||||
|
check_case(f[0x60], L1D, 16, 8, 64, data);
|
||||||
|
check_case(f[0x66], L1D, 8, 4, 64, data);
|
||||||
|
check_case(f[0x67], L1D, 16, 4, 64, data);
|
||||||
|
check_case(f[0x68], L1D, 32, 4, 64, data);
|
||||||
|
/* The following four entries are trace cache. Intel does not
|
||||||
|
* specify a cache-line size, so we use -1 instead
|
||||||
|
*/
|
||||||
|
check_case(f[0x70], L1I, 12, 8, -1, data);
|
||||||
|
check_case(f[0x71], L1I, 16, 8, -1, data);
|
||||||
|
check_case(f[0x72], L1I, 32, 8, -1, data);
|
||||||
|
check_case(f[0x73], L1I, 64, 8, -1, data);
|
||||||
|
|
||||||
|
check_case(f[0x78], L2, 1024, 4, 64, data);
|
||||||
|
check_case(f[0x79], L2, 128, 8, 64, data);
|
||||||
|
check_case(f[0x7A], L2, 256, 8, 64, data);
|
||||||
|
check_case(f[0x7B], L2, 512, 8, 64, data);
|
||||||
|
check_case(f[0x7C], L2, 1024, 8, 64, data);
|
||||||
|
check_case(f[0x7D], L2, 2048, 8, 64, data);
|
||||||
|
check_case(f[0x7F], L2, 512, 2, 64, data);
|
||||||
|
check_case(f[0x82], L2, 256, 8, 32, data);
|
||||||
|
check_case(f[0x83], L2, 512, 8, 32, data);
|
||||||
|
check_case(f[0x84], L2, 1024, 8, 32, data);
|
||||||
|
check_case(f[0x85], L2, 2048, 8, 32, data);
|
||||||
|
check_case(f[0x86], L2, 512, 4, 64, data);
|
||||||
|
check_case(f[0x87], L2, 1024, 8, 64, data);
|
||||||
|
|
||||||
|
if (f[0x49]) {
|
||||||
|
/* This flag is overloaded with two meanings. On Xeon MP
|
||||||
|
* (family 0xf, model 0x6) this means L3 cache. On all other
|
||||||
|
* CPUs (notably Conroe et al), this is L2 cache. In both cases
|
||||||
|
* it means 4MB, 16-way associative, 64-byte line size.
|
||||||
|
*/
|
||||||
|
if (data->family == 0xf && data->model == 0x6) {
|
||||||
|
data->l3_cache = 4096;
|
||||||
|
data->l3_assoc = 16;
|
||||||
|
data->l3_cacheline = 64;
|
||||||
|
} else {
|
||||||
|
data->l2_cache = 4096;
|
||||||
|
data->l2_assoc = 16;
|
||||||
|
data->l2_cacheline = 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (f[0x40]) {
|
||||||
|
/* Again, a special flag. It means:
|
||||||
|
* 1) If no L2 is specified, then CPU is w/o L2 (0 KB)
|
||||||
|
* 2) If L2 is specified by other flags, then, CPU is w/o L3.
|
||||||
|
*/
|
||||||
|
if (data->l2_cache == -1) {
|
||||||
|
data->l2_cache = 0;
|
||||||
|
} else {
|
||||||
|
data->l3_cache = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decode_intel_deterministic_cache_info(struct cpu_raw_data_t* raw,
|
||||||
|
struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
int ecx;
|
||||||
|
int ways, partitions, linesize, sets, size, level, typenumber;
|
||||||
|
cache_type_t type;
|
||||||
|
for (ecx = 0; ecx < MAX_INTELFN4_LEVEL; ecx++) {
|
||||||
|
typenumber = raw->intel_fn4[ecx][0] & 0x1f;
|
||||||
|
if (typenumber == 0) break;
|
||||||
|
level = (raw->intel_fn4[ecx][0] >> 5) & 0x7;
|
||||||
|
if (level == 1 && typenumber == 1)
|
||||||
|
type = L1D;
|
||||||
|
else if (level == 1 && typenumber == 2)
|
||||||
|
type = L1I;
|
||||||
|
else if (level == 2 && typenumber == 3)
|
||||||
|
type = L2;
|
||||||
|
else if (level == 3 && typenumber == 3)
|
||||||
|
type = L3;
|
||||||
|
else if (level == 4 && typenumber == 3)
|
||||||
|
type = L4;
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ways = ((raw->intel_fn4[ecx][1] >> 22) & 0x3ff) + 1;
|
||||||
|
partitions = ((raw->intel_fn4[ecx][1] >> 12) & 0x3ff) + 1;
|
||||||
|
linesize = (raw->intel_fn4[ecx][1] & 0xfff) + 1;
|
||||||
|
sets = raw->intel_fn4[ecx][2] + 1;
|
||||||
|
size = ways * partitions * linesize * sets / 1024;
|
||||||
|
check_case(1, type, size, ways, linesize, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int decode_intel_extended_topology(struct cpu_raw_data_t* raw,
|
||||||
|
struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
int i, level_type, num_smt = -1, num_core = -1;
|
||||||
|
for (i = 0; i < MAX_INTELFN11_LEVEL; i++) {
|
||||||
|
level_type = (raw->intel_fn11[i][2] & 0xff00) >> 8;
|
||||||
|
switch (level_type) {
|
||||||
|
case 0x01:
|
||||||
|
num_smt = raw->intel_fn11[i][1] & 0xffff;
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
num_core = raw->intel_fn11[i][1] & 0xffff;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (num_smt == -1 || num_core == -1) return 0;
|
||||||
|
data->num_logical_cpus = num_core;
|
||||||
|
data->num_cores = num_core / num_smt;
|
||||||
|
// make sure num_cores is at least 1. In VMs, the CPUID instruction
|
||||||
|
// is rigged and may give nonsensical results, but we should at least
|
||||||
|
// avoid outputs like data->num_cores == 0.
|
||||||
|
if (data->num_cores <= 0) data->num_cores = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decode_intel_number_of_cores(struct cpu_raw_data_t* raw,
|
||||||
|
struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
int logical_cpus = -1, num_cores = -1;
|
||||||
|
|
||||||
|
if (raw->basic_cpuid[0][0] >= 11) {
|
||||||
|
if (decode_intel_extended_topology(raw, data)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raw->basic_cpuid[0][0] >= 1) {
|
||||||
|
logical_cpus = (raw->basic_cpuid[1][1] >> 16) & 0xff;
|
||||||
|
if (raw->basic_cpuid[0][0] >= 4) {
|
||||||
|
num_cores = 1 + ((raw->basic_cpuid[4][0] >> 26) & 0x3f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data->flags[CPU_FEATURE_HT]) {
|
||||||
|
if (num_cores > 1) {
|
||||||
|
data->num_cores = num_cores;
|
||||||
|
data->num_logical_cpus = logical_cpus;
|
||||||
|
} else {
|
||||||
|
data->num_cores = 1;
|
||||||
|
data->num_logical_cpus = (logical_cpus >= 1 ? logical_cpus : 1);
|
||||||
|
if (data->num_logical_cpus == 1)
|
||||||
|
data->flags[CPU_FEATURE_HT] = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data->num_cores = data->num_logical_cpus = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static intel_code_and_bits_t get_brand_code_and_bits(struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
intel_code_t code = (intel_code_t) NC;
|
||||||
|
intel_code_and_bits_t result;
|
||||||
|
uint64_t bits = 0;
|
||||||
|
int i = 0;
|
||||||
|
const char* bs = data->brand_str;
|
||||||
|
const char* s;
|
||||||
|
const struct { intel_code_t c; const char *search; } matchtable[] = {
|
||||||
|
{ PENTIUM_M, "Pentium(R) M" },
|
||||||
|
{ CORE_SOLO, "Pentium(R) Dual CPU" },
|
||||||
|
{ CORE_SOLO, "Pentium(R) Dual-Core" },
|
||||||
|
{ PENTIUM_D, "Pentium(R) D" },
|
||||||
|
{ CORE_SOLO, "Genuine Intel(R) CPU" },
|
||||||
|
{ CORE_SOLO, "Intel(R) Core(TM)" },
|
||||||
|
{ DIAMONDVILLE, "CPU [N ][23]## " },
|
||||||
|
{ SILVERTHORNE, "CPU Z" },
|
||||||
|
{ PINEVIEW, "CPU [ND][45]## " },
|
||||||
|
{ CEDARVIEW, "CPU [ND]#### " },
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct { uint64_t bit; const char* search; } bit_matchtable[] = {
|
||||||
|
{ XEON_, "Xeon" },
|
||||||
|
{ _MP_, " MP" },
|
||||||
|
{ ATOM_, "Atom(TM) CPU" },
|
||||||
|
{ MOBILE_, "Mobile" },
|
||||||
|
{ CELERON_, "Celeron" },
|
||||||
|
{ PENTIUM_, "Pentium" },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i = 0; i < COUNT_OF(bit_matchtable); i++) {
|
||||||
|
if (match_pattern(bs, bit_matchtable[i].search))
|
||||||
|
bits |= bit_matchtable[i].bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i = match_pattern(bs, "Core(TM) [im][357]")) != 0) {
|
||||||
|
bits |= CORE_;
|
||||||
|
i--;
|
||||||
|
switch (bs[i + 9]) {
|
||||||
|
case 'i': bits |= _I_; break;
|
||||||
|
case 'm': bits |= _M_; break;
|
||||||
|
}
|
||||||
|
switch (bs[i + 10]) {
|
||||||
|
case '3': bits |= _3; break;
|
||||||
|
case '5': bits |= _5; break;
|
||||||
|
case '7': bits |= _7; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < COUNT_OF(matchtable); i++)
|
||||||
|
if (match_pattern(bs, matchtable[i].search)) {
|
||||||
|
code = matchtable[i].c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (bits & XEON_) {
|
||||||
|
if (match_pattern(bs, "W35##") || match_pattern(bs, "[ELXW]75##"))
|
||||||
|
bits |= _7;
|
||||||
|
else if (match_pattern(bs, "[ELXW]55##"))
|
||||||
|
code = GAINESTOWN;
|
||||||
|
else if (match_pattern(bs, "[ELXW]56##"))
|
||||||
|
code = WESTMERE;
|
||||||
|
else if (data->l3_cache > 0 && data->family == 16)
|
||||||
|
/* restrict by family, since later Xeons also have L3 ... */
|
||||||
|
code = IRWIN;
|
||||||
|
}
|
||||||
|
if (match_all(bits, XEON_ + _MP_) && data->l3_cache > 0)
|
||||||
|
code = POTOMAC;
|
||||||
|
if (code == CORE_SOLO) {
|
||||||
|
s = strstr(bs, "CPU");
|
||||||
|
if (s) {
|
||||||
|
s += 3;
|
||||||
|
while (*s == ' ') s++;
|
||||||
|
if (*s == 'T')
|
||||||
|
bits |= MOBILE_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (code == CORE_SOLO) {
|
||||||
|
switch (data->num_cores) {
|
||||||
|
case 1: break;
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
code = CORE_DUO;
|
||||||
|
if (data->num_logical_cpus > 2)
|
||||||
|
code = DUAL_CORE_HT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
code = QUAD_CORE;
|
||||||
|
if (data->num_logical_cpus > 4)
|
||||||
|
code = QUAD_CORE_HT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
code = MORE_THAN_QUADCORE; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code == CORE_DUO && (bits & MOBILE_) && data->model != 14) {
|
||||||
|
if (data->ext_model < 23) {
|
||||||
|
code = MEROM;
|
||||||
|
} else {
|
||||||
|
code = PENRYN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data->ext_model == 23 &&
|
||||||
|
(code == CORE_DUO || code == PENTIUM_D || (bits & CELERON_))) {
|
||||||
|
code = WOLFDALE;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.code = code;
|
||||||
|
result.bits = bits;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decode_intel_sgx_features(const struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||||
|
{
|
||||||
|
struct cpu_epc_t epc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (raw->basic_cpuid[0][0] < 0x12) return; // no 12h leaf
|
||||||
|
if (raw->basic_cpuid[0x12][0] == 0) return; // no sub-leafs available, probably it's disabled by BIOS
|
||||||
|
|
||||||
|
// decode sub-leaf 0:
|
||||||
|
if (raw->basic_cpuid[0x12][0] & 1) data->sgx.flags[INTEL_SGX1] = 1;
|
||||||
|
if (raw->basic_cpuid[0x12][0] & 2) data->sgx.flags[INTEL_SGX2] = 1;
|
||||||
|
if (data->sgx.flags[INTEL_SGX1] || data->sgx.flags[INTEL_SGX2])
|
||||||
|
data->sgx.present = 1;
|
||||||
|
data->sgx.misc_select = raw->basic_cpuid[0x12][1];
|
||||||
|
data->sgx.max_enclave_32bit = (raw->basic_cpuid[0x12][3] ) & 0xff;
|
||||||
|
data->sgx.max_enclave_64bit = (raw->basic_cpuid[0x12][3] >> 8) & 0xff;
|
||||||
|
|
||||||
|
// decode sub-leaf 1:
|
||||||
|
data->sgx.secs_attributes = raw->intel_fn12h[1][0] | (((uint64_t) raw->intel_fn12h[1][1]) << 32);
|
||||||
|
data->sgx.secs_xfrm = raw->intel_fn12h[1][2] | (((uint64_t) raw->intel_fn12h[1][3]) << 32);
|
||||||
|
|
||||||
|
// decode higher-order subleafs, whenever present:
|
||||||
|
data->sgx.num_epc_sections = -1;
|
||||||
|
for (i = 0; i < 1000000; i++) {
|
||||||
|
epc = cpuid_get_epc(i, raw);
|
||||||
|
if (epc.length == 0) {
|
||||||
|
data->sgx.num_epc_sections = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data->sgx.num_epc_sections == -1) {
|
||||||
|
data->sgx.num_epc_sections = 1000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cpu_epc_t cpuid_get_epc(int index, const struct cpu_raw_data_t* raw)
|
||||||
|
{
|
||||||
|
uint32_t regs[4];
|
||||||
|
struct cpu_epc_t retval = {0, 0};
|
||||||
|
if (raw && index < MAX_INTELFN12H_LEVEL - 2) {
|
||||||
|
// this was queried already, use the data:
|
||||||
|
memcpy(regs, raw->intel_fn12h[2 + index], sizeof(regs));
|
||||||
|
} else {
|
||||||
|
// query this ourselves:
|
||||||
|
regs[0] = 0x12;
|
||||||
|
regs[2] = 2 + index;
|
||||||
|
regs[1] = regs[3] = 0;
|
||||||
|
cpu_exec_cpuid_ext(regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode values:
|
||||||
|
if ((regs[0] & 0xf) == 0x1) {
|
||||||
|
retval.start_addr |= (regs[0] & 0xfffff000); // bits [12, 32) -> bits [12, 32)
|
||||||
|
retval.start_addr |= ((uint64_t) (regs[1] & 0x000fffff)) << 32; // bits [0, 20) -> bits [32, 52)
|
||||||
|
retval.length |= (regs[2] & 0xfffff000); // bits [12, 32) -> bits [12, 32)
|
||||||
|
retval.length |= ((uint64_t) (regs[3] & 0x000fffff)) << 32; // bits [0, 20) -> bits [32, 52)
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
|
||||||
|
{
|
||||||
|
intel_code_and_bits_t brand;
|
||||||
|
|
||||||
|
load_intel_features(raw, data);
|
||||||
|
if (raw->basic_cpuid[0][0] >= 4) {
|
||||||
|
/* Deterministic way is preferred, being more generic */
|
||||||
|
decode_intel_deterministic_cache_info(raw, data);
|
||||||
|
} else if (raw->basic_cpuid[0][0] >= 2) {
|
||||||
|
decode_intel_oldstyle_cache_info(raw, data);
|
||||||
|
}
|
||||||
|
decode_intel_number_of_cores(raw, data);
|
||||||
|
|
||||||
|
brand = get_brand_code_and_bits(data);
|
||||||
|
|
||||||
|
internal->code.intel = brand.code;
|
||||||
|
internal->bits = brand.bits;
|
||||||
|
|
||||||
|
if (data->flags[CPU_FEATURE_SGX]) {
|
||||||
|
// if SGX is indicated by the CPU, verify its presence:
|
||||||
|
decode_intel_sgx_features(raw, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
31
src/3rdparty/libcpuid/recog_intel.h
vendored
Normal file
31
src/3rdparty/libcpuid/recog_intel.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Veselin Georgiev,
|
||||||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
#ifndef __RECOG_INTEL_H__
|
||||||
|
#define __RECOG_INTEL_H__
|
||||||
|
|
||||||
|
int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal);
|
||||||
|
|
||||||
|
#endif /*__RECOG_INTEL_H__*/
|
||||||
6
compat/winansi.c → src/3rdparty/winansi.cpp
vendored
6
compat/winansi.c → src/3rdparty/winansi.cpp
vendored
@@ -11,7 +11,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
#include "compat/winansi.h"
|
#include "winansi.h"
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 Peter Harris <git@peter.is-a-geek.org>
|
* Copyright 2008 Peter Harris <git@peter.is-a-geek.org>
|
||||||
*/
|
*/
|
||||||
@@ -344,8 +344,8 @@ int winansi_vfprintf(FILE *stream, const char *format, va_list list)
|
|||||||
#endif
|
#endif
|
||||||
va_end(cp);
|
va_end(cp);
|
||||||
|
|
||||||
if (len > sizeof(small_buf) - 1) {
|
if ((unsigned) len > sizeof(small_buf) - 1) {
|
||||||
buf = malloc(len + 1);
|
buf = (char*)malloc(len + 1);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
goto abort;
|
goto abort;
|
||||||
|
|
||||||
5
compat/winansi.h → src/3rdparty/winansi.h
vendored
5
compat/winansi.h → src/3rdparty/winansi.h
vendored
@@ -1,12 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* ANSI emulation wrappers
|
* ANSI emulation wrappers
|
||||||
*/
|
*/
|
||||||
#ifdef WIN32
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define isatty(fd) _isatty(fd)
|
|
||||||
#define fileno(fd) _fileno(fd)
|
#define fileno(fd) _fileno(fd)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -28,5 +27,3 @@ extern "C" {
|
|||||||
#define printf winansi_printf
|
#define printf winansi_printf
|
||||||
#define fprintf winansi_fprintf
|
#define fprintf winansi_fprintf
|
||||||
#define vfprintf winansi_vfprintf
|
#define vfprintf winansi_vfprintf
|
||||||
|
|
||||||
#endif
|
|
||||||
129
src/App.cpp
Normal file
129
src/App.cpp
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "App.h"
|
||||||
|
#include "Console.h"
|
||||||
|
#include "Cpu.h"
|
||||||
|
#include "crypto/CryptoNight.h"
|
||||||
|
#include "Mem.h"
|
||||||
|
#include "net/Network.h"
|
||||||
|
#include "Options.h"
|
||||||
|
#include "Summary.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "workers/Workers.h"
|
||||||
|
|
||||||
|
|
||||||
|
App *App::m_self = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
App::App(int argc, char **argv) :
|
||||||
|
m_network(nullptr),
|
||||||
|
m_options(nullptr)
|
||||||
|
{
|
||||||
|
m_self = this;
|
||||||
|
|
||||||
|
Console::init();
|
||||||
|
Cpu::init();
|
||||||
|
|
||||||
|
m_options = Options::parse(argc, argv);
|
||||||
|
m_network = new Network(m_options);
|
||||||
|
|
||||||
|
uv_signal_init(uv_default_loop(), &m_signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
App::~App()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int App::exec()
|
||||||
|
{
|
||||||
|
if (!m_options->isReady()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CryptoNight::init(m_options->algo(), m_options->algoVariant())) {
|
||||||
|
LOG_ERR("\"%s\" hash self-test failed.", m_options->algoName());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_signal_start(&m_signal, App::onSignal, SIGHUP);
|
||||||
|
uv_signal_start(&m_signal, App::onSignal, SIGTERM);
|
||||||
|
uv_signal_start(&m_signal, App::onSignal, SIGINT);
|
||||||
|
|
||||||
|
background();
|
||||||
|
|
||||||
|
Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash());
|
||||||
|
Summary::print();
|
||||||
|
|
||||||
|
Workers::start(m_options->affinity(), m_options->nicehash());
|
||||||
|
|
||||||
|
m_network->connect();
|
||||||
|
|
||||||
|
const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||||
|
uv_loop_close(uv_default_loop());
|
||||||
|
|
||||||
|
free(m_network);
|
||||||
|
free(m_options);
|
||||||
|
|
||||||
|
Mem::release();
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void App::close()
|
||||||
|
{
|
||||||
|
uv_stop(uv_default_loop());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void App::onSignal(uv_signal_t *handle, int signum)
|
||||||
|
{
|
||||||
|
switch (signum)
|
||||||
|
{
|
||||||
|
case SIGHUP:
|
||||||
|
LOG_WARN("SIGHUP received, exiting");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIGTERM:
|
||||||
|
LOG_WARN("SIGTERM received, exiting");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIGINT:
|
||||||
|
LOG_WARN("SIGINT received, exiting");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_self->close();
|
||||||
|
}
|
||||||
57
src/App.h
Normal file
57
src/App.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __APP_H__
|
||||||
|
#define __APP_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
|
class Network;
|
||||||
|
class Options;
|
||||||
|
|
||||||
|
|
||||||
|
class App
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
App(int argc, char **argv);
|
||||||
|
~App();
|
||||||
|
|
||||||
|
int exec();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void background();
|
||||||
|
void close();
|
||||||
|
|
||||||
|
static void onSignal(uv_signal_t *handle, int signum);
|
||||||
|
|
||||||
|
static App *m_self;
|
||||||
|
|
||||||
|
Network *m_network;
|
||||||
|
Options *m_options;
|
||||||
|
uv_signal_t m_signal;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __APP_H__ */
|
||||||
@@ -21,37 +21,46 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __XMRIG_H__
|
|
||||||
#define __XMRIG_H__
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdlib.h>
|
||||||
#include <inttypes.h>
|
#include <signal.h>
|
||||||
#include <jansson.h>
|
#include <errno.h>
|
||||||
#include <curl/curl.h>
|
#include <unistd.h>
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#define unlikely(expr) (__builtin_expect(!!(expr), 0))
|
|
||||||
#define likely(expr) (__builtin_expect(!!(expr), 1))
|
|
||||||
|
|
||||||
|
|
||||||
struct thr_info {
|
#include "App.h"
|
||||||
int id;
|
#include "Console.h"
|
||||||
pthread_t pth;
|
#include "Cpu.h"
|
||||||
struct thread_q *q;
|
#include "Options.h"
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct work_restart {
|
void App::background()
|
||||||
volatile unsigned long restart;
|
{
|
||||||
char padding[128 - sizeof(unsigned long)];
|
if (m_options->affinity() != -1L) {
|
||||||
};
|
Cpu::setAffinity(-1, m_options->affinity());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_options->background()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
struct work;
|
int i = fork();
|
||||||
|
if (i < 0) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 0) {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
extern struct thr_info *thr_info;
|
i = setsid();
|
||||||
extern struct work_restart *work_restart;
|
|
||||||
extern void os_specific_init();
|
|
||||||
|
|
||||||
#endif /* __XMRIG_H__ */
|
if (i < 0) {
|
||||||
|
LOG_ERR("setsid() failed (errno = %d)", errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = chdir("/");
|
||||||
|
if (i < 0) {
|
||||||
|
LOG_ERR("chdir() failed (errno = %d)", errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,29 +21,32 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __PERSISTENT_MEMORY_H__
|
|
||||||
#define __PERSISTENT_MEMORY_H__
|
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <winsock2.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
|
||||||
enum memory_flags {
|
#include "App.h"
|
||||||
MEMORY_HUGEPAGES_AVAILABLE = 1,
|
#include "Options.h"
|
||||||
MEMORY_HUGEPAGES_ENABLED = 2,
|
#include "Cpu.h"
|
||||||
MEMORY_LOCK = 4
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define TWO_MB_PAGE 2097152
|
void App::background()
|
||||||
|
{
|
||||||
|
if (m_options->affinity() != -1L) {
|
||||||
|
Cpu::setAffinity(-1, m_options->affinity());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_options->background()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
extern char *persistent_memory;
|
HWND hcon = GetConsoleWindow();
|
||||||
extern int persistent_memory_flags;
|
if (hcon) {
|
||||||
|
ShowWindow(hcon, SW_HIDE);
|
||||||
|
} else {
|
||||||
const char * persistent_memory_allocate();
|
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
void persistent_memory_free();
|
CloseHandle(h);
|
||||||
void * persistent_calloc(size_t num, size_t size);
|
FreeConsole();
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif /* __PERSISTENT_MEMORY_H__ */
|
|
||||||
144
src/Console.cpp
Normal file
144
src/Console.cpp
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
# include <winsock2.h>
|
||||||
|
# include <malloc.h>
|
||||||
|
# include "3rdparty/winansi.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "Console.h"
|
||||||
|
|
||||||
|
|
||||||
|
Console *Console::m_self = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
void Console::init()
|
||||||
|
{
|
||||||
|
if (!m_self) {
|
||||||
|
m_self = new Console();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Console::message(Console::Level level, const char* fmt, ...)
|
||||||
|
{
|
||||||
|
time_t now = time(nullptr);
|
||||||
|
tm stime;
|
||||||
|
|
||||||
|
# ifdef _WIN32
|
||||||
|
localtime_s(&stime, &now);
|
||||||
|
# else
|
||||||
|
localtime_r(&now, &stime);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
|
||||||
|
const char* color = nullptr;
|
||||||
|
if (m_colors) {
|
||||||
|
switch (level) {
|
||||||
|
case ERR:
|
||||||
|
color = kCL_RED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WARNING:
|
||||||
|
color = kCL_YELLOW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NOTICE:
|
||||||
|
color = kCL_WHITE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEBUG:
|
||||||
|
color = kCL_GRAY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
color = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t len = 64 + strlen(fmt) + 2;
|
||||||
|
char *buf = static_cast<char *>(alloca(len));
|
||||||
|
|
||||||
|
sprintf(buf, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n",
|
||||||
|
stime.tm_year + 1900,
|
||||||
|
stime.tm_mon + 1,
|
||||||
|
stime.tm_mday,
|
||||||
|
stime.tm_hour,
|
||||||
|
stime.tm_min,
|
||||||
|
stime.tm_sec,
|
||||||
|
color,
|
||||||
|
fmt,
|
||||||
|
m_colors ? kCL_N : ""
|
||||||
|
);
|
||||||
|
|
||||||
|
uv_mutex_lock(&m_mutex);
|
||||||
|
|
||||||
|
vfprintf(stdout, buf, ap);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
uv_mutex_unlock(&m_mutex);
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Console::text(const char* fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
|
||||||
|
const int len = 64 + strlen(fmt) + 2;
|
||||||
|
char *buf = static_cast<char *>(alloca(len));
|
||||||
|
|
||||||
|
sprintf(buf, "%s%s\n",
|
||||||
|
fmt,
|
||||||
|
m_colors ? kCL_N : ""
|
||||||
|
);
|
||||||
|
|
||||||
|
uv_mutex_lock(&m_mutex);
|
||||||
|
|
||||||
|
vfprintf(stdout, buf, ap);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
uv_mutex_unlock(&m_mutex);
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Console::Console() :
|
||||||
|
m_colors(true)
|
||||||
|
{
|
||||||
|
uv_mutex_init(&m_mutex);
|
||||||
|
}
|
||||||
83
src/Console.h
Normal file
83
src/Console.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CONSOLE_H__
|
||||||
|
#define __CONSOLE_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
|
class Console
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Level {
|
||||||
|
ERR,
|
||||||
|
WARNING,
|
||||||
|
NOTICE,
|
||||||
|
INFO,
|
||||||
|
DEBUG
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr static const char* kCL_N = "\x1B[0m";
|
||||||
|
constexpr static const char* kCL_RED = "\x1B[31m";
|
||||||
|
constexpr static const char* kCL_YELLOW = "\x1B[33m";
|
||||||
|
constexpr static const char* kCL_WHITE = "\x1B[01;37m";
|
||||||
|
|
||||||
|
# ifdef WIN32
|
||||||
|
constexpr static const char* kCL_GRAY = "\x1B[01;30m";
|
||||||
|
# else
|
||||||
|
constexpr static const char* kCL_GRAY = "\x1B[90m";
|
||||||
|
# endif
|
||||||
|
|
||||||
|
static inline Console* i() { return m_self; }
|
||||||
|
static void init();
|
||||||
|
|
||||||
|
void message(Level level, const char* fmt, ...);
|
||||||
|
void text(const char* fmt, ...);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Console();
|
||||||
|
|
||||||
|
static Console *m_self;
|
||||||
|
bool m_colors;
|
||||||
|
uv_mutex_t m_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define LOG_ERR(x, ...) Console::i()->message(Console::ERR, x, ##__VA_ARGS__)
|
||||||
|
#define LOG_WARN(x, ...) Console::i()->message(Console::WARNING, x, ##__VA_ARGS__)
|
||||||
|
#define LOG_NOTICE(x, ...) Console::i()->message(Console::NOTICE, x, ##__VA_ARGS__)
|
||||||
|
#define LOG_INFO(x, ...) Console::i()->message(Console::INFO, x, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#ifdef APP_DEBUG
|
||||||
|
# define LOG_DEBUG(x, ...) Console::i()->message(Console::DEBUG, x, ##__VA_ARGS__)
|
||||||
|
# define LOG_DEBUG_ERR(x, ...) Console::i()->message(Console::ERR, x, ##__VA_ARGS__)
|
||||||
|
# define LOG_DEBUG_WARN(x, ...) Console::i()->message(Console::WARNING, x, ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
# define LOG_DEBUG(x, ...)
|
||||||
|
# define LOG_DEBUG_ERR(x, ...)
|
||||||
|
# define LOG_DEBUG_WARN(x, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __CONSOLE_H__ */
|
||||||
105
src/Cpu.cpp
Normal file
105
src/Cpu.cpp
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <libcpuid.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "Cpu.h"
|
||||||
|
|
||||||
|
|
||||||
|
char Cpu::m_brand[64] = { 0 };
|
||||||
|
int Cpu::m_flags = 0;
|
||||||
|
int Cpu::m_l2_cache = 0;
|
||||||
|
int Cpu::m_l3_cache = 0;
|
||||||
|
int Cpu::m_sockets = 1;
|
||||||
|
int Cpu::m_totalCores = 0;
|
||||||
|
int Cpu::m_totalThreads = 0;
|
||||||
|
|
||||||
|
|
||||||
|
int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage)
|
||||||
|
{
|
||||||
|
if (m_totalThreads == 1) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cache = m_l3_cache ? m_l3_cache : m_l2_cache;
|
||||||
|
int count = 0;
|
||||||
|
const int size = (algo ? 1024 : 2048) * (doubleHash ? 2 : 1);
|
||||||
|
|
||||||
|
if (cache) {
|
||||||
|
count = cache / size;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
count = m_totalThreads / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > m_totalThreads) {
|
||||||
|
count = m_totalThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((float) count / m_totalThreads * 100) > maxCpuUsage) {
|
||||||
|
count = ceil((float) m_totalThreads * (maxCpuUsage / 100.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return count < 1 ? 1 : count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Cpu::initCommon()
|
||||||
|
{
|
||||||
|
struct cpu_raw_data_t raw = { 0 };
|
||||||
|
struct cpu_id_t data = { 0 };
|
||||||
|
|
||||||
|
cpuid_get_raw_data(&raw);
|
||||||
|
cpu_identify(&raw, &data);
|
||||||
|
|
||||||
|
strncpy(m_brand, data.brand_str, sizeof(m_brand) - 1);
|
||||||
|
|
||||||
|
m_totalThreads = data.total_logical_cpus;
|
||||||
|
m_sockets = m_totalThreads / data.num_logical_cpus;
|
||||||
|
m_totalCores = data.num_cores *m_sockets;
|
||||||
|
|
||||||
|
m_l3_cache = data.l3_cache > 0 ? data.l3_cache * m_sockets : 0;
|
||||||
|
|
||||||
|
// Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97
|
||||||
|
if (data.vendor == VENDOR_AMD && data.l3_cache <= 0 && data.l2_assoc == 16 && data.ext_family >= 21) {
|
||||||
|
m_l2_cache = data.l2_cache * (m_totalCores / 2) * m_sockets;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_l2_cache = data.l2_cache > 0 ? data.l2_cache * m_totalCores * m_sockets : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# if defined(__x86_64__) || defined(_M_AMD64)
|
||||||
|
m_flags |= X86_64;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
if (data.flags[CPU_FEATURE_AES]) {
|
||||||
|
m_flags |= AES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.flags[CPU_FEATURE_BMI2]) {
|
||||||
|
m_flags |= BMI2;
|
||||||
|
}
|
||||||
|
}
|
||||||
63
src/Cpu.h
Normal file
63
src/Cpu.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CPU_H__
|
||||||
|
#define __CPU_H__
|
||||||
|
|
||||||
|
|
||||||
|
class Cpu
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Flags {
|
||||||
|
X86_64 = 1,
|
||||||
|
AES = 2,
|
||||||
|
BMI2 = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
static int optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage);
|
||||||
|
static void init();
|
||||||
|
static void setAffinity(int id, unsigned long mask);
|
||||||
|
|
||||||
|
static inline bool hasAES() { return m_flags & AES; }
|
||||||
|
static inline bool isX64() { return m_flags & X86_64; }
|
||||||
|
static inline const char *brand() { return m_brand; }
|
||||||
|
static inline int cores() { return m_totalCores; }
|
||||||
|
static inline int l2() { return m_l2_cache; }
|
||||||
|
static inline int l3() { return m_l3_cache; }
|
||||||
|
static inline int sockets() { return m_sockets; }
|
||||||
|
static inline int threads() { return m_totalThreads; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void initCommon();
|
||||||
|
|
||||||
|
static char m_brand[64];
|
||||||
|
static int m_flags;
|
||||||
|
static int m_l2_cache;
|
||||||
|
static int m_l3_cache;
|
||||||
|
static int m_sockets;
|
||||||
|
static int m_totalCores;
|
||||||
|
static int m_totalThreads;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __CPU_H__ */
|
||||||
@@ -21,17 +21,25 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __STATS_H__
|
|
||||||
#define __STATS_H__
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <pthread.h>
|
||||||
#include <inttypes.h>
|
#include <sched.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
void stats_init();
|
#include "Cpu.h"
|
||||||
void stats_set_target(uint32_t new_target);
|
|
||||||
void stats_share_result(bool success);
|
|
||||||
void stats_add_hashes(int thr_id, struct timeval *tv_start, unsigned long hashes_done);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __STATS_H__ */
|
void Cpu::init()
|
||||||
|
{
|
||||||
|
# ifdef XMRIG_NO_LIBCPUID
|
||||||
|
m_totalThreads = sysconf(_SC_NPROCESSORS_CONF);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
initCommon();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Cpu::setAffinity(int id, unsigned long mask)
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -21,10 +21,20 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cpuid.h>
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# include <intrin.h>
|
||||||
|
|
||||||
|
# define bit_AES (1 << 25)
|
||||||
|
# define bit_BMI2 (1 << 8)
|
||||||
|
#else
|
||||||
|
# include <cpuid.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include "cpu.h"
|
|
||||||
|
#include "Cpu.h"
|
||||||
|
|
||||||
|
|
||||||
#define VENDOR_ID (0)
|
#define VENDOR_ID (0)
|
||||||
@@ -41,6 +51,11 @@
|
|||||||
#define EDX_Reg (3)
|
#define EDX_Reg (3)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
static inline void cpuid(int level, int output[4]) {
|
||||||
|
__cpuid(output, level);
|
||||||
|
}
|
||||||
|
#else
|
||||||
static inline void cpuid(int level, int output[4]) {
|
static inline void cpuid(int level, int output[4]) {
|
||||||
int a, b, c, d;
|
int a, b, c, d;
|
||||||
__cpuid_count(level, 0, a, b, c, d);
|
__cpuid_count(level, 0, a, b, c, d);
|
||||||
@@ -50,9 +65,10 @@ static inline void cpuid(int level, int output[4]) {
|
|||||||
output[2] = c;
|
output[2] = c;
|
||||||
output[3] = d;
|
output[3] = d;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void cpu_brand_string(char* s) {
|
static inline void cpu_brand_string(char* s) {
|
||||||
int cpu_info[4] = { 0 };
|
int cpu_info[4] = { 0 };
|
||||||
cpuid(VENDOR_ID, cpu_info);
|
cpuid(VENDOR_ID, cpu_info);
|
||||||
|
|
||||||
@@ -66,7 +82,7 @@ static void cpu_brand_string(char* s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool has_aes_ni()
|
static inline bool has_aes_ni()
|
||||||
{
|
{
|
||||||
int cpu_info[4] = { 0 };
|
int cpu_info[4] = { 0 };
|
||||||
cpuid(PROCESSOR_INFO, cpu_info);
|
cpuid(PROCESSOR_INFO, cpu_info);
|
||||||
@@ -75,7 +91,7 @@ static bool has_aes_ni()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool has_bmi2() {
|
static inline bool has_bmi2() {
|
||||||
int cpu_info[4] = { 0 };
|
int cpu_info[4] = { 0 };
|
||||||
cpuid(EXTENDED_FEATURES, cpu_info);
|
cpuid(EXTENDED_FEATURES, cpu_info);
|
||||||
|
|
||||||
@@ -83,18 +99,35 @@ static bool has_bmi2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void cpu_init_common() {
|
char Cpu::m_brand[64] = { 0 };
|
||||||
cpu_brand_string(cpu_info.brand);
|
int Cpu::m_flags = 0;
|
||||||
|
int Cpu::m_l2_cache = 0;
|
||||||
|
int Cpu::m_l3_cache = 0;
|
||||||
|
int Cpu::m_sockets = 1;
|
||||||
|
int Cpu::m_totalCores = 0;
|
||||||
|
int Cpu::m_totalThreads = 0;
|
||||||
|
|
||||||
# ifdef __x86_64__
|
|
||||||
cpu_info.flags |= CPU_FLAG_X86_64;
|
int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage)
|
||||||
|
{
|
||||||
|
int count = m_totalThreads / 2;
|
||||||
|
return count < 1 ? 1 : count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Cpu::initCommon()
|
||||||
|
{
|
||||||
|
cpu_brand_string(m_brand);
|
||||||
|
|
||||||
|
# if defined(__x86_64__) || defined(_M_AMD64)
|
||||||
|
m_flags |= X86_64;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
if (has_aes_ni()) {
|
if (has_aes_ni()) {
|
||||||
cpu_info.flags |= CPU_FLAG_AES;
|
m_flags |= AES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_bmi2()) {
|
if (has_bmi2()) {
|
||||||
cpu_info.flags |= CPU_FLAG_BMI2;
|
m_flags |= BMI2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -21,36 +21,31 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sched.h>
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <sched.h>
|
||||||
#include "cpu.h"
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
struct cpu_info cpu_info = { 0 };
|
#include "Cpu.h"
|
||||||
void cpu_init_common();
|
|
||||||
|
|
||||||
|
|
||||||
void cpu_init() {
|
void Cpu::init()
|
||||||
cpu_info.count = sysconf(_SC_NPROCESSORS_CONF);
|
{
|
||||||
|
# ifdef XMRIG_NO_LIBCPUID
|
||||||
|
m_totalThreads = sysconf(_SC_NPROCESSORS_CONF);
|
||||||
|
# endif
|
||||||
|
|
||||||
cpu_init_common();
|
initCommon();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int get_optimal_threads_count() {
|
void Cpu::setAffinity(int id, unsigned long mask)
|
||||||
int count = cpu_info.count / 2;
|
|
||||||
return count < 1 ? 1 : count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int affine_to_cpu_mask(int id, unsigned long mask)
|
|
||||||
{
|
{
|
||||||
cpu_set_t set;
|
cpu_set_t set;
|
||||||
CPU_ZERO(&set);
|
CPU_ZERO(&set);
|
||||||
|
|
||||||
for (unsigned i = 0; i < cpu_info.count; i++) {
|
for (int i = 0; i < m_totalThreads; i++) {
|
||||||
if (mask & (1UL << i)) {
|
if (mask & (1UL << i)) {
|
||||||
CPU_SET(i, &set);
|
CPU_SET(i, &set);
|
||||||
}
|
}
|
||||||
@@ -21,33 +21,27 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "cpu.h"
|
|
||||||
|
|
||||||
|
|
||||||
struct cpu_info cpu_info = { 0 };
|
#include "Cpu.h"
|
||||||
void cpu_init_common();
|
|
||||||
|
|
||||||
|
|
||||||
void cpu_init() {
|
void Cpu::init()
|
||||||
|
{
|
||||||
|
# ifdef XMRIG_NO_LIBCPUID
|
||||||
SYSTEM_INFO sysinfo;
|
SYSTEM_INFO sysinfo;
|
||||||
GetSystemInfo(&sysinfo);
|
GetSystemInfo(&sysinfo);
|
||||||
|
|
||||||
cpu_info.count = sysinfo.dwNumberOfProcessors;
|
m_totalThreads = sysinfo.dwNumberOfProcessors;
|
||||||
|
# endif
|
||||||
|
|
||||||
cpu_init_common();
|
initCommon();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int get_optimal_threads_count(int mining_algo) {
|
void Cpu::setAffinity(int id, unsigned long mask)
|
||||||
int count = cpu_info.count / 2;
|
|
||||||
return count < 1 ? 1 : count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int affine_to_cpu_mask(int id, unsigned long mask)
|
|
||||||
{
|
{
|
||||||
if (id == -1) {
|
if (id == -1) {
|
||||||
SetProcessAffinityMask(GetCurrentProcess(), mask);
|
SetProcessAffinityMask(GetCurrentProcess(), mask);
|
||||||
87
src/Mem.cpp
Normal file
87
src/Mem.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <memory.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "crypto/CryptoNight.h"
|
||||||
|
#include "Mem.h"
|
||||||
|
#include "Options.h"
|
||||||
|
|
||||||
|
|
||||||
|
bool Mem::m_doubleHash = false;
|
||||||
|
int Mem::m_algo = 0;
|
||||||
|
int Mem::m_flags = 0;
|
||||||
|
int Mem::m_threads = 0;
|
||||||
|
size_t Mem::m_offset = 0;
|
||||||
|
uint8_t *Mem::m_memory = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
cryptonight_ctx *Mem::create(int threadId)
|
||||||
|
{
|
||||||
|
# ifndef XMRIG_NO_AEON
|
||||||
|
if (m_algo == Options::ALGO_CRYPTONIGHT_LITE) {
|
||||||
|
return createLite(threadId);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
cryptonight_ctx *ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[MEMORY - sizeof(cryptonight_ctx) * (threadId + 1)]);
|
||||||
|
|
||||||
|
const int ratio = m_doubleHash ? 2 : 1;
|
||||||
|
ctx->memory = &m_memory[MEMORY * (threadId * ratio + 1)];
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void *Mem::calloc(size_t num, size_t size)
|
||||||
|
{
|
||||||
|
void *mem = &m_memory[m_offset];
|
||||||
|
m_offset += (num * size);
|
||||||
|
|
||||||
|
memset(mem, 0, num * size);
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef XMRIG_NO_AEON
|
||||||
|
cryptonight_ctx *Mem::createLite(int threadId) {
|
||||||
|
cryptonight_ctx *ctx;
|
||||||
|
|
||||||
|
if (!m_doubleHash) {
|
||||||
|
const size_t offset = MEMORY * (threadId + 1);
|
||||||
|
|
||||||
|
ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[offset + MEMORY_LITE]);
|
||||||
|
ctx->memory = &m_memory[offset];
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[MEMORY - sizeof(cryptonight_ctx) * (threadId + 1)]);
|
||||||
|
ctx->memory = &m_memory[MEMORY * (threadId + 1)];
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
71
src/Mem.h
Normal file
71
src/Mem.h
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MEM_H__
|
||||||
|
#define __MEM_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "align.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct cryptonight_ctx;
|
||||||
|
|
||||||
|
|
||||||
|
class Mem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Flags {
|
||||||
|
HugepagesAvailable = 1,
|
||||||
|
HugepagesEnabled = 2,
|
||||||
|
Lock = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool allocate(int algo, int threads, bool doubleHash);
|
||||||
|
static cryptonight_ctx *create(int threadId);
|
||||||
|
static void *calloc(size_t num, size_t size);
|
||||||
|
static void release();
|
||||||
|
|
||||||
|
static inline bool isDoubleHash() { return m_doubleHash; }
|
||||||
|
static inline bool isHugepagesAvailable() { return m_flags & HugepagesAvailable; }
|
||||||
|
static inline bool isHugepagesEnabled() { return m_flags & HugepagesEnabled; }
|
||||||
|
static inline int flags() { return m_flags; }
|
||||||
|
static inline int threads() { return m_threads; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool m_doubleHash;
|
||||||
|
static int m_algo;
|
||||||
|
static int m_flags;
|
||||||
|
static int m_threads;
|
||||||
|
static size_t m_offset;
|
||||||
|
VAR_ALIGN(16, static uint8_t *m_memory);
|
||||||
|
|
||||||
|
# ifndef XMRIG_NO_AEON
|
||||||
|
static cryptonight_ctx *createLite(int threadId);
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __MEM_H__ */
|
||||||
86
src/Mem_unix.cpp
Normal file
86
src/Mem_unix.cpp
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <mm_malloc.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "crypto/CryptoNight.h"
|
||||||
|
#include "Mem.h"
|
||||||
|
#include "Options.h"
|
||||||
|
#include "Console.h"
|
||||||
|
|
||||||
|
|
||||||
|
bool Mem::allocate(int algo, int threads, bool doubleHash)
|
||||||
|
{
|
||||||
|
m_algo = algo;
|
||||||
|
m_threads = threads;
|
||||||
|
m_doubleHash = doubleHash;
|
||||||
|
|
||||||
|
const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
|
||||||
|
const size_t size = MEMORY * (threads * ratio + 1);
|
||||||
|
|
||||||
|
m_flags |= HugepagesAvailable;
|
||||||
|
|
||||||
|
# if defined(__APPLE__)
|
||||||
|
m_memory = static_cast<uint8_t*>(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0));
|
||||||
|
# else
|
||||||
|
m_memory = static_cast<uint8_t*>(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0));
|
||||||
|
# endif
|
||||||
|
|
||||||
|
if (m_memory == MAP_FAILED) {
|
||||||
|
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_flags |= HugepagesEnabled;
|
||||||
|
|
||||||
|
if (madvise(m_memory, size, MADV_RANDOM | MADV_WILLNEED) != 0) {
|
||||||
|
LOG_ERR("madvise failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mlock(m_memory, size) == 0) {
|
||||||
|
m_flags |= Lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Mem::release()
|
||||||
|
{
|
||||||
|
const int size = MEMORY * (m_threads + 1);
|
||||||
|
|
||||||
|
if (m_flags & HugepagesEnabled) {
|
||||||
|
if (m_flags & Lock) {
|
||||||
|
munlock(m_memory, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
munmap(m_memory, size);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_mm_free(m_memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
181
src/Mem_win.cpp
Normal file
181
src/Mem_win.cpp
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <ntsecapi.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
# include <mm_malloc.h>
|
||||||
|
#else
|
||||||
|
# include <malloc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "Console.h"
|
||||||
|
#include "crypto/CryptoNight.h"
|
||||||
|
#include "Mem.h"
|
||||||
|
#include "Options.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************
|
||||||
|
SetLockPagesPrivilege: a function to obtain or
|
||||||
|
release the privilege of locking physical pages.
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
|
||||||
|
HANDLE hProcess: Handle for the process for which the
|
||||||
|
privilege is needed
|
||||||
|
|
||||||
|
BOOL bEnable: Enable (TRUE) or disable?
|
||||||
|
|
||||||
|
Return value: TRUE indicates success, FALSE failure.
|
||||||
|
|
||||||
|
*****************************************************************/
|
||||||
|
/**
|
||||||
|
* AWE Example: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366531(v=vs.85).aspx
|
||||||
|
* Creating a File Mapping Using Large Pages: https://msdn.microsoft.com/en-us/library/aa366543(VS.85).aspx
|
||||||
|
*/
|
||||||
|
static BOOL SetLockPagesPrivilege() {
|
||||||
|
HANDLE token;
|
||||||
|
|
||||||
|
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) != TRUE) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOKEN_PRIVILEGES tp;
|
||||||
|
tp.PrivilegeCount = 1;
|
||||||
|
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
|
||||||
|
if (LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)) != TRUE) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL rc = AdjustTokenPrivileges(token, FALSE, (PTOKEN_PRIVILEGES) &tp, 0, NULL, NULL);
|
||||||
|
if (rc != TRUE || GetLastError() != ERROR_SUCCESS) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(token);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string) {
|
||||||
|
LSA_UNICODE_STRING lsaString;
|
||||||
|
DWORD dwLen = 0;
|
||||||
|
|
||||||
|
dwLen = wcslen(string);
|
||||||
|
lsaString.Buffer = (LPWSTR) string;
|
||||||
|
lsaString.Length = (USHORT)((dwLen) * sizeof(WCHAR));
|
||||||
|
lsaString.MaximumLength = (USHORT)((dwLen + 1) * sizeof(WCHAR));
|
||||||
|
return lsaString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static BOOL ObtainLockPagesPrivilege() {
|
||||||
|
HANDLE token;
|
||||||
|
PTOKEN_USER user = NULL;
|
||||||
|
|
||||||
|
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == TRUE) {
|
||||||
|
DWORD size = 0;
|
||||||
|
|
||||||
|
GetTokenInformation(token, TokenUser, NULL, 0, &size);
|
||||||
|
if (size) {
|
||||||
|
user = (PTOKEN_USER) LocalAlloc(LPTR, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
GetTokenInformation(token, TokenUser, user, size, &size);
|
||||||
|
CloseHandle(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LSA_HANDLE handle;
|
||||||
|
LSA_OBJECT_ATTRIBUTES attributes;
|
||||||
|
ZeroMemory(&attributes, sizeof(attributes));
|
||||||
|
|
||||||
|
BOOL result = FALSE;
|
||||||
|
if (LsaOpenPolicy(NULL, &attributes, POLICY_ALL_ACCESS, &handle) == 0) {
|
||||||
|
LSA_UNICODE_STRING str = StringToLsaUnicodeString(_T(SE_LOCK_MEMORY_NAME));
|
||||||
|
|
||||||
|
if (LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0) {
|
||||||
|
LOG_DEBUG("Huge pages support was successfully enabled, but reboot required to use it");
|
||||||
|
result = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LsaClose(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalFree(user);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static BOOL TrySetLockPagesPrivilege() {
|
||||||
|
if (SetLockPagesPrivilege()) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ObtainLockPagesPrivilege() && SetLockPagesPrivilege();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Mem::allocate(int algo, int threads, bool doubleHash)
|
||||||
|
{
|
||||||
|
m_algo = algo;
|
||||||
|
m_threads = threads;
|
||||||
|
m_doubleHash = doubleHash;
|
||||||
|
|
||||||
|
const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
|
||||||
|
const size_t size = MEMORY * (threads * ratio + 1);
|
||||||
|
|
||||||
|
if (TrySetLockPagesPrivilege()) {
|
||||||
|
m_flags |= HugepagesAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_memory = static_cast<uint8_t*>(VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE));
|
||||||
|
if (!m_memory) {
|
||||||
|
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_flags |= HugepagesEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Mem::release()
|
||||||
|
{
|
||||||
|
if (m_flags & HugepagesEnabled) {
|
||||||
|
VirtualFree(m_memory, 0, MEM_RELEASE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_mm_free(m_memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
518
src/Options.cpp
Normal file
518
src/Options.cpp
Normal file
@@ -0,0 +1,518 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <jansson.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# include "getopt/getopt.h"
|
||||||
|
#else
|
||||||
|
# include <getopt.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include "Console.h"
|
||||||
|
#include "Cpu.h"
|
||||||
|
#include "donate.h"
|
||||||
|
#include "net/Url.h"
|
||||||
|
#include "Options.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ARRAY_SIZE
|
||||||
|
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
Options *Options::m_self = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
static char const usage[] = "\
|
||||||
|
Usage: " APP_ID " [OPTIONS]\n\
|
||||||
|
Options:\n\
|
||||||
|
-a, --algo=ALGO cryptonight (default) or cryptonight-lite\n\
|
||||||
|
-o, --url=URL URL of mining server\n\
|
||||||
|
-b, --backup-url=URL URL of backup mining server\n\
|
||||||
|
-O, --userpass=U:P username:password pair for mining server\n\
|
||||||
|
-u, --user=USERNAME username for mining server\n\
|
||||||
|
-p, --pass=PASSWORD password for mining server\n\
|
||||||
|
-t, --threads=N number of miner threads\n\
|
||||||
|
-v, --av=N algorithm variation, 0 auto select\n\
|
||||||
|
-k, --keepalive send keepalived for prevent timeout (need pool support)\n\
|
||||||
|
-r, --retries=N number of times to retry before switch to backup server (default: 5)\n\
|
||||||
|
-R, --retry-pause=N time to pause between retries (default: 5)\n\
|
||||||
|
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\
|
||||||
|
--no-color disable colored output\n\
|
||||||
|
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\
|
||||||
|
-B, --background run the miner in the background\n\
|
||||||
|
-c, --config=FILE load a JSON-format configuration file\n\
|
||||||
|
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\
|
||||||
|
--safe safe adjust threads and av settings for current CPU\n\
|
||||||
|
--nicehash enable nicehash support\n\
|
||||||
|
--print-time=N print hashrate report every N seconds\n\
|
||||||
|
-h, --help display this help and exit\n\
|
||||||
|
-V, --version output version information and exit\n\
|
||||||
|
";
|
||||||
|
|
||||||
|
|
||||||
|
static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vb:";
|
||||||
|
|
||||||
|
|
||||||
|
static struct option const options[] = {
|
||||||
|
{ "algo", 1, nullptr, 'a' },
|
||||||
|
{ "av", 1, nullptr, 'v' },
|
||||||
|
{ "background", 0, nullptr, 'B' },
|
||||||
|
{ "backup-url", 1, nullptr, 'b' },
|
||||||
|
{ "config", 1, nullptr, 'c' },
|
||||||
|
{ "cpu-affinity", 1, nullptr, 1020 },
|
||||||
|
{ "donate-level", 1, nullptr, 1003 },
|
||||||
|
{ "help", 0, nullptr, 'h' },
|
||||||
|
{ "keepalive", 0, nullptr ,'k' },
|
||||||
|
{ "max-cpu-usage", 1, nullptr, 1004 },
|
||||||
|
{ "nicehash", 0, nullptr, 1006 },
|
||||||
|
{ "no-color", 0, nullptr, 1002 },
|
||||||
|
{ "pass", 1, nullptr, 'p' },
|
||||||
|
{ "print-time", 1, nullptr, 1007 },
|
||||||
|
{ "retries", 1, nullptr, 'r' },
|
||||||
|
{ "retry-pause", 1, nullptr, 'R' },
|
||||||
|
{ "safe", 0, nullptr, 1005 },
|
||||||
|
{ "threads", 1, nullptr, 't' },
|
||||||
|
{ "url", 1, nullptr, 'o' },
|
||||||
|
{ "user", 1, nullptr, 'u' },
|
||||||
|
{ "userpass", 1, nullptr, 'O' },
|
||||||
|
{ "version", 0, nullptr, 'V' },
|
||||||
|
{ 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const char *algo_names[] = {
|
||||||
|
"cryptonight",
|
||||||
|
# ifndef XMRIG_NO_AEON
|
||||||
|
"cryptonight-lite"
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Options *Options::parse(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (!m_self) {
|
||||||
|
m_self = new Options(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *Options::algoName() const
|
||||||
|
{
|
||||||
|
return algo_names[m_algo];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Options::Options(int argc, char **argv) :
|
||||||
|
m_background(false),
|
||||||
|
m_colors(true),
|
||||||
|
m_doubleHash(false),
|
||||||
|
m_keepAlive(false),
|
||||||
|
m_nicehash(false),
|
||||||
|
m_ready(false),
|
||||||
|
m_safe(false),
|
||||||
|
m_pass(nullptr),
|
||||||
|
m_user(nullptr),
|
||||||
|
m_algo(0),
|
||||||
|
m_algoVariant(0),
|
||||||
|
m_donateLevel(kDonateLevel),
|
||||||
|
m_maxCpuUsage(75),
|
||||||
|
m_printTime(60),
|
||||||
|
m_retries(5),
|
||||||
|
m_retryPause(5),
|
||||||
|
m_threads(0),
|
||||||
|
m_affinity(-1L),
|
||||||
|
m_backupUrl(nullptr),
|
||||||
|
m_url(nullptr)
|
||||||
|
{
|
||||||
|
int key;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
key = getopt_long(argc, argv, short_options, options, NULL);
|
||||||
|
if (key < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parseArg(key, optarg)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind < argc) {
|
||||||
|
fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_url) {
|
||||||
|
LOG_ERR("No pool URL supplied. Exiting.", argv[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_nicehash && m_url->isNicehash()) {
|
||||||
|
m_nicehash = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_user) {
|
||||||
|
m_user = strdup("x");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_pass) {
|
||||||
|
m_pass = strdup("x");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_algoVariant = getAlgoVariant();
|
||||||
|
if (m_algoVariant == AV2_AESNI_DOUBLE || m_algoVariant == AV4_SOFT_AES_DOUBLE) {
|
||||||
|
m_doubleHash = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_threads) {
|
||||||
|
m_threads = Cpu::optimalThreadsCount(m_algo, m_doubleHash, m_maxCpuUsage);
|
||||||
|
}
|
||||||
|
else if (m_safe) {
|
||||||
|
const int count = Cpu::optimalThreadsCount(m_algo, m_doubleHash, m_maxCpuUsage);
|
||||||
|
if (m_threads > count) {
|
||||||
|
m_threads = count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Options::~Options()
|
||||||
|
{
|
||||||
|
delete m_url;
|
||||||
|
delete m_backupUrl;
|
||||||
|
|
||||||
|
free(m_user);
|
||||||
|
free(m_pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Options::parseArg(int key, char *arg)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
int v;
|
||||||
|
uint64_t ul;
|
||||||
|
Url *url;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case 'a': /* --algo */
|
||||||
|
if (!setAlgo(arg)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'O': /* --userpass */
|
||||||
|
if (!setUserpass(arg)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'o': /* --url */
|
||||||
|
url = parseUrl(arg);
|
||||||
|
if (url) {
|
||||||
|
free(m_url);
|
||||||
|
m_url = url;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'b': /* --backup-url */
|
||||||
|
url = parseUrl(arg);
|
||||||
|
if (url) {
|
||||||
|
free(m_backupUrl);
|
||||||
|
m_backupUrl = url;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'u': /* --user */
|
||||||
|
free(m_user);
|
||||||
|
m_user = strdup(arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p': /* --pass */
|
||||||
|
free(m_pass);
|
||||||
|
m_pass = strdup(arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r': /* --retries */
|
||||||
|
v = strtol(arg, nullptr, 10);
|
||||||
|
if (v < 1 || v > 1000) {
|
||||||
|
showUsage(1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_retries = v;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'R': /* --retry-pause */
|
||||||
|
v = strtol(arg, nullptr, 10);
|
||||||
|
if (v < 1 || v > 3600) {
|
||||||
|
showUsage(1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_retryPause = v;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 't': /* --threads */
|
||||||
|
v = strtol(arg, nullptr, 10);
|
||||||
|
if (v < 1 || v > 1024) {
|
||||||
|
showUsage(1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_threads = v;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1004: /* --max-cpu-usage */
|
||||||
|
v = strtol(arg, nullptr, 10);
|
||||||
|
if (v < 1 || v > 100) {
|
||||||
|
showUsage(1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_maxCpuUsage = v;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1005: /* --safe */
|
||||||
|
m_safe = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'k': /* --keepalive */
|
||||||
|
m_keepAlive = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'V': /* --version */
|
||||||
|
showVersion();
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case 'h': /* --help */
|
||||||
|
showUsage(0);
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case 'B': /* --background */
|
||||||
|
m_background = true;
|
||||||
|
m_colors = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'v': /* --av */
|
||||||
|
v = strtol(arg, nullptr, 10);
|
||||||
|
if (v < 0 || v > 1000) {
|
||||||
|
showUsage(1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_algoVariant = v;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1020: /* --cpu-affinity */
|
||||||
|
p = strstr(arg, "0x");
|
||||||
|
ul = p ? strtoul(p, NULL, 16) : atol(arg);
|
||||||
|
if (ul > (1UL << Cpu::threads()) -1) {
|
||||||
|
ul = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_affinity = ul;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1002: /* --no-color */
|
||||||
|
m_colors = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1003: /* --donate-level */
|
||||||
|
v = strtol(arg, nullptr, 10);
|
||||||
|
if (v < 1 || v > 99) {
|
||||||
|
showUsage(1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_donateLevel = v;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1006: /* --nicehash */
|
||||||
|
m_nicehash = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1007: /* --print-time */
|
||||||
|
v = strtol(arg, nullptr, 10);
|
||||||
|
if (v < 0 || v > 1000) {
|
||||||
|
showUsage(1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_printTime = v;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
showUsage(1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Url *Options::parseUrl(const char *arg) const
|
||||||
|
{
|
||||||
|
auto url = new Url(arg);
|
||||||
|
if (!url->isValid()) {
|
||||||
|
delete url;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Options::showUsage(int status) const
|
||||||
|
{
|
||||||
|
if (status) {
|
||||||
|
fprintf(stderr, "Try \"" APP_ID "\" --help' for more information.\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf(usage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Options::showVersion()
|
||||||
|
{
|
||||||
|
printf(APP_NAME " " APP_VERSION "\n built on " __DATE__
|
||||||
|
|
||||||
|
# if defined(__clang__)
|
||||||
|
" with clang " __clang_version__);
|
||||||
|
# elif defined(__GNUC__)
|
||||||
|
" with GCC");
|
||||||
|
printf(" %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
|
||||||
|
# elif defined(_MSC_VER)
|
||||||
|
" with MSVC");
|
||||||
|
printf(" %d", MSVC_VERSION);
|
||||||
|
# else
|
||||||
|
);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
printf("\n features:"
|
||||||
|
# if defined(__i386__) || defined(_M_IX86)
|
||||||
|
" i386"
|
||||||
|
# elif defined(__x86_64__) || defined(_M_AMD64)
|
||||||
|
" x86_64"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if defined(__AES__) || defined(_MSC_VER)
|
||||||
|
" AES-NI"
|
||||||
|
# endif
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
printf("\nlibuv/%s\n", uv_version_string());
|
||||||
|
printf("libjansson/%s\n", JANSSON_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Options::setAlgo(const char *algo)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < ARRAY_SIZE(algo_names); i++) {
|
||||||
|
if (algo_names[i] && !strcmp(algo, algo_names[i])) {
|
||||||
|
m_algo = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifndef XMRIG_NO_AEON
|
||||||
|
if (i == ARRAY_SIZE(algo_names) - 1 && !strcmp(algo, "cryptonight-light")) {
|
||||||
|
m_algo = ALGO_CRYPTONIGHT_LITE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
if (i == ARRAY_SIZE(algo_names) - 1) {
|
||||||
|
showUsage(1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Options::setUserpass(const char *userpass)
|
||||||
|
{
|
||||||
|
const char *p = strchr(userpass, ':');
|
||||||
|
if (!p) {
|
||||||
|
showUsage(1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(m_user);
|
||||||
|
free(m_pass);
|
||||||
|
|
||||||
|
m_user = static_cast<char*>(calloc(p - userpass + 1, 1));
|
||||||
|
strncpy(m_user, userpass, p - userpass);
|
||||||
|
m_pass = strdup(p + 1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Options::getAlgoVariant() const
|
||||||
|
{
|
||||||
|
# ifndef XMRIG_NO_AEON
|
||||||
|
if (m_algo == ALGO_CRYPTONIGHT_LITE) {
|
||||||
|
return getAlgoVariantLite();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) {
|
||||||
|
return Cpu::hasAES() ? AV1_AESNI : AV3_SOFT_AES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) {
|
||||||
|
return m_algoVariant + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_algoVariant;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef XMRIG_NO_AEON
|
||||||
|
int Options::getAlgoVariantLite() const
|
||||||
|
{
|
||||||
|
if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) {
|
||||||
|
return Cpu::hasAES() ? AV2_AESNI_DOUBLE : AV4_SOFT_AES_DOUBLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) {
|
||||||
|
return m_algoVariant + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_algoVariant;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
116
src/Options.h
Normal file
116
src/Options.h
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __OPTIONS_H__
|
||||||
|
#define __OPTIONS_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
class Url;
|
||||||
|
|
||||||
|
|
||||||
|
class Options
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Algo {
|
||||||
|
ALGO_CRYPTONIGHT, /* CryptoNight (Monero) */
|
||||||
|
ALGO_CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AlgoVariant {
|
||||||
|
AV0_AUTO,
|
||||||
|
AV1_AESNI,
|
||||||
|
AV2_AESNI_DOUBLE,
|
||||||
|
AV3_SOFT_AES,
|
||||||
|
AV4_SOFT_AES_DOUBLE,
|
||||||
|
AV_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline Options* i() { return m_self; }
|
||||||
|
static Options *parse(int argc, char **argv);
|
||||||
|
|
||||||
|
inline bool background() const { return m_background; }
|
||||||
|
inline bool colors() const { return m_colors; }
|
||||||
|
inline bool doubleHash() const { return m_doubleHash; }
|
||||||
|
inline bool isReady() const { return m_ready; }
|
||||||
|
inline bool keepAlive() const { return m_keepAlive; }
|
||||||
|
inline bool nicehash() const { return m_nicehash; }
|
||||||
|
inline const char *pass() const { return m_pass; }
|
||||||
|
inline const char *user() const { return m_user; }
|
||||||
|
inline const Url *backupUrl() const { return m_backupUrl; }
|
||||||
|
inline const Url *url() const { return m_url; }
|
||||||
|
inline int algo() const { return m_algo; }
|
||||||
|
inline int algoVariant() const { return m_algoVariant; }
|
||||||
|
inline int donateLevel() const { return m_donateLevel; }
|
||||||
|
inline int printTime() const { return m_printTime; }
|
||||||
|
inline int retries() const { return m_retries; }
|
||||||
|
inline int retryPause() const { return m_retryPause; }
|
||||||
|
inline int threads() const { return m_threads; }
|
||||||
|
inline int64_t affinity() const { return m_affinity; }
|
||||||
|
|
||||||
|
const char *algoName() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Options(int argc, char **argv);
|
||||||
|
~Options();
|
||||||
|
|
||||||
|
static Options *m_self;
|
||||||
|
|
||||||
|
bool parseArg(int key, char *arg);
|
||||||
|
Url *parseUrl(const char *arg) const;
|
||||||
|
void showUsage(int status) const;
|
||||||
|
void showVersion(void);
|
||||||
|
|
||||||
|
bool setAlgo(const char *algo);
|
||||||
|
bool setUserpass(const char *userpass);
|
||||||
|
|
||||||
|
int getAlgoVariant() const;
|
||||||
|
# ifndef XMRIG_NO_AEON
|
||||||
|
int getAlgoVariantLite() const;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
bool m_background;
|
||||||
|
bool m_colors;
|
||||||
|
bool m_doubleHash;
|
||||||
|
bool m_keepAlive;
|
||||||
|
bool m_nicehash;
|
||||||
|
bool m_ready;
|
||||||
|
bool m_safe;
|
||||||
|
char *m_pass;
|
||||||
|
char *m_user;
|
||||||
|
int m_algo;
|
||||||
|
int m_algoVariant;
|
||||||
|
int m_donateLevel;
|
||||||
|
int m_maxCpuUsage;
|
||||||
|
int m_printTime;
|
||||||
|
int m_retries;
|
||||||
|
int m_retryPause;
|
||||||
|
int m_threads;
|
||||||
|
int64_t m_affinity;
|
||||||
|
Url *m_backupUrl;
|
||||||
|
Url *m_url;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __OPTIONS_H__ */
|
||||||
138
src/Summary.cpp
Normal file
138
src/Summary.cpp
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "Console.h"
|
||||||
|
#include "Cpu.h"
|
||||||
|
#include "Mem.h"
|
||||||
|
#include "net/Url.h"
|
||||||
|
#include "Options.h"
|
||||||
|
#include "Summary.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void print_versions()
|
||||||
|
{
|
||||||
|
char buf[16];
|
||||||
|
|
||||||
|
# if defined(__clang__)
|
||||||
|
snprintf(buf, 16, " clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__);
|
||||||
|
# elif defined(__GNUC__)
|
||||||
|
snprintf(buf, 16, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
|
||||||
|
# elif defined(_MSC_VER)
|
||||||
|
snprintf(buf, 16, " MSVC/%d", MSVC_VERSION);
|
||||||
|
# else
|
||||||
|
buf[0] = '\0';
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
if (Options::i()->colors()) {
|
||||||
|
Console::i()->text("\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36mXMRig/%s\x1B[01;37m libuv/%s%s", APP_VERSION, uv_version_string(), buf);
|
||||||
|
} else {
|
||||||
|
Console::i()->text(" * VERSIONS: XMRig/%s libuv/%s%s", APP_VERSION, uv_version_string(), buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void print_memory() {
|
||||||
|
if (Options::i()->colors()) {
|
||||||
|
Console::i()->text("\x1B[01;32m * \x1B[01;37mHUGE PAGES: %s, %s",
|
||||||
|
Mem::isHugepagesAvailable() ? "\x1B[01;32mavailable" : "\x1B[01;31munavailable",
|
||||||
|
Mem::isHugepagesEnabled() ? "\x1B[01;32menabled" : "\x1B[01;31mdisabled");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Console::i()->text(" * HUGE PAGES: %s, %s", Mem::isHugepagesAvailable() ? "available" : "unavailable", Mem::isHugepagesEnabled() ? "enabled" : "disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void print_cpu()
|
||||||
|
{
|
||||||
|
if (Options::i()->colors()) {
|
||||||
|
Console::i()->text("\x1B[01;32m * \x1B[01;37mCPU: %s (%d) %sx64 %sAES-NI",
|
||||||
|
Cpu::brand(),
|
||||||
|
Cpu::sockets(),
|
||||||
|
Cpu::isX64() ? "\x1B[01;32m" : "\x1B[01;31m-",
|
||||||
|
Cpu::hasAES() ? "\x1B[01;32m" : "\x1B[01;31m-");
|
||||||
|
# ifndef XMRIG_NO_LIBCPUID
|
||||||
|
Console::i()->text("\x1B[01;32m * \x1B[01;37mCPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Console::i()->text(" * CPU: %s (%d) %sx64 %sAES-NI", Cpu::brand(), Cpu::sockets(), Cpu::isX64() ? "" : "-", Cpu::hasAES() ? "" : "-");
|
||||||
|
# ifndef XMRIG_NO_LIBCPUID
|
||||||
|
Console::i()->text(" * CPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void print_threads()
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
if (Options::i()->affinity() != -1L) {
|
||||||
|
snprintf(buf, 32, ", affinity=0x%llX", Options::i()->affinity());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buf[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
Console::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, donate=%d%%%s%s" : " * THREADS: %d, %s, av=%d, donate=%d%%%s%s",
|
||||||
|
Options::i()->threads(),
|
||||||
|
Options::i()->algoName(),
|
||||||
|
Options::i()->algoVariant(),
|
||||||
|
Options::i()->donateLevel(),
|
||||||
|
Options::i()->nicehash() ? ", nicehash" : "", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void print_pools()
|
||||||
|
{
|
||||||
|
Console::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mPOOL #1: \x1B[01;36m%s:%d" : " * POOL #1: %s:%d",
|
||||||
|
Options::i()->url()->host(),
|
||||||
|
Options::i()->url()->port());
|
||||||
|
|
||||||
|
if (!Options::i()->backupUrl()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mPOOL #2: \x1B[01;36m%s:%d" : " * POOL #2: %s:%d",
|
||||||
|
Options::i()->backupUrl()->host(),
|
||||||
|
Options::i()->backupUrl()->port());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Summary::print()
|
||||||
|
{
|
||||||
|
print_versions();
|
||||||
|
print_memory();
|
||||||
|
print_cpu();
|
||||||
|
print_threads();
|
||||||
|
print_pools();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -24,6 +24,12 @@
|
|||||||
#ifndef __SUMMARY_H__
|
#ifndef __SUMMARY_H__
|
||||||
#define __SUMMARY_H__
|
#define __SUMMARY_H__
|
||||||
|
|
||||||
void print_summary();
|
|
||||||
|
class Summary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void print();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* __SUMMARY_H__ */
|
#endif /* __SUMMARY_H__ */
|
||||||
144
src/crypto/CryptoNight.cpp
Normal file
144
src/crypto/CryptoNight.cpp
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "crypto/CryptoNight.h"
|
||||||
|
#include "crypto/CryptoNight_p.h"
|
||||||
|
#include "crypto/CryptoNight_test.h"
|
||||||
|
#include "net/Job.h"
|
||||||
|
#include "net/JobResult.h"
|
||||||
|
#include "Options.h"
|
||||||
|
|
||||||
|
|
||||||
|
void (*cryptonight_hash_ctx)(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
static void cryptonight_av1_aesni(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
|
||||||
|
cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cryptonight_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
|
||||||
|
cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cryptonight_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
|
||||||
|
cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cryptonight_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
|
||||||
|
cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef XMRIG_NO_AEON
|
||||||
|
static void cryptonight_lite_av1_aesni(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
|
||||||
|
cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cryptonight_lite_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
|
||||||
|
cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cryptonight_lite_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
|
||||||
|
cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cryptonight_lite_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
|
||||||
|
cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*cryptonight_variations[8])(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = {
|
||||||
|
cryptonight_av1_aesni,
|
||||||
|
cryptonight_av2_aesni_double,
|
||||||
|
cryptonight_av3_softaes,
|
||||||
|
cryptonight_av4_softaes_double,
|
||||||
|
cryptonight_lite_av1_aesni,
|
||||||
|
cryptonight_lite_av2_aesni_double,
|
||||||
|
cryptonight_lite_av3_softaes,
|
||||||
|
cryptonight_lite_av4_softaes_double
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
void (*cryptonight_variations[4])(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = {
|
||||||
|
cryptonight_av1_aesni,
|
||||||
|
cryptonight_av2_aesni_double,
|
||||||
|
cryptonight_av3_softaes,
|
||||||
|
cryptonight_av4_softaes_double
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
bool CryptoNight::hash(const Job &job, JobResult &result, cryptonight_ctx *ctx)
|
||||||
|
{
|
||||||
|
cryptonight_hash_ctx(job.blob(), job.size(), result.result, ctx);
|
||||||
|
|
||||||
|
return *reinterpret_cast<uint64_t*>(result.result + 24) < job.target();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CryptoNight::init(int algo, int variant)
|
||||||
|
{
|
||||||
|
if (variant < 1 || variant > 4) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifndef XMRIG_NO_AEON
|
||||||
|
const int index = algo == Options::ALGO_CRYPTONIGHT_LITE ? (variant + 3) : (variant - 1);
|
||||||
|
# else
|
||||||
|
const int index = variant - 1;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
cryptonight_hash_ctx = cryptonight_variations[index];
|
||||||
|
|
||||||
|
return selfTest(algo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CryptoNight::hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx)
|
||||||
|
{
|
||||||
|
cryptonight_hash_ctx(input, size, output, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CryptoNight::selfTest(int algo) {
|
||||||
|
if (cryptonight_hash_ctx == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char output[64];
|
||||||
|
|
||||||
|
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) _mm_malloc(sizeof(struct cryptonight_ctx), 16);
|
||||||
|
ctx->memory = (uint8_t *) _mm_malloc(MEMORY * 2, 16);
|
||||||
|
|
||||||
|
cryptonight_hash_ctx(test_input, 76, output, ctx);
|
||||||
|
|
||||||
|
_mm_free(ctx->memory);
|
||||||
|
_mm_free(ctx);
|
||||||
|
|
||||||
|
return memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output1 : test_output0, (Options::i()->doubleHash() ? 64 : 32)) == 0;
|
||||||
|
}
|
||||||
61
src/crypto/CryptoNight.h
Normal file
61
src/crypto/CryptoNight.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CRYPTONIGHT_H__
|
||||||
|
#define __CRYPTONIGHT_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "align.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define MEMORY 2097152 /* 2 MiB */
|
||||||
|
#define MEMORY_LITE 1048576 /* 1 MiB */
|
||||||
|
|
||||||
|
|
||||||
|
struct cryptonight_ctx {
|
||||||
|
VAR_ALIGN(16, uint8_t state0[200]);
|
||||||
|
VAR_ALIGN(16, uint8_t state1[200]);
|
||||||
|
VAR_ALIGN(16, uint8_t* memory);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Job;
|
||||||
|
class JobResult;
|
||||||
|
|
||||||
|
|
||||||
|
class CryptoNight
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool hash(const Job &job, JobResult &result, cryptonight_ctx *ctx);
|
||||||
|
static bool init(int algo, int variant);
|
||||||
|
static void hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool selfTest(int algo);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __CRYPTONIGHT_H__ */
|
||||||
452
src/crypto/CryptoNight_p.h
Normal file
452
src/crypto/CryptoNight_p.h
Normal file
@@ -0,0 +1,452 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CRYPTONIGHT_P_H__
|
||||||
|
#define __CRYPTONIGHT_P_H__
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
# include <x86intrin.h>
|
||||||
|
#else
|
||||||
|
# include <intrin.h>
|
||||||
|
# define __restrict__ __restrict
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include "crypto/CryptoNight.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "crypto/c_keccak.h"
|
||||||
|
#include "crypto/c_groestl.h"
|
||||||
|
#include "crypto/c_blake256.h"
|
||||||
|
#include "crypto/c_jh.h"
|
||||||
|
#include "crypto/c_skein.h"
|
||||||
|
|
||||||
|
__m128i soft_aesenc(__m128i in, __m128i key);
|
||||||
|
__m128i soft_aeskeygenassist(__m128i key, uint8_t rcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void do_blake_hash(const void* input, size_t len, char* output) {
|
||||||
|
blake256_hash(reinterpret_cast<uint8_t*>(output), static_cast<const uint8_t*>(input), len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void do_groestl_hash(const void* input, size_t len, char* output) {
|
||||||
|
groestl(static_cast<const uint8_t*>(input), len * 8, reinterpret_cast<uint8_t*>(output));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void do_jh_hash(const void* input, size_t len, char* output) {
|
||||||
|
jh_hash(32 * 8, static_cast<const uint8_t*>(input), 8 * len, reinterpret_cast<uint8_t*>(output));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void do_skein_hash(const void* input, size_t len, char* output) {
|
||||||
|
skein_hash(8 * 32, static_cast<const uint8_t*>(input), 8 * len, reinterpret_cast<uint8_t*>(output));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__x86_64__) || defined(_M_AMD64)
|
||||||
|
# define EXTRACT64(X) _mm_cvtsi128_si64(X)
|
||||||
|
|
||||||
|
# ifdef __GNUC__
|
||||||
|
static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi)
|
||||||
|
{
|
||||||
|
unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
|
||||||
|
*hi = r >> 64;
|
||||||
|
return (uint64_t) r;
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
#define __umul128 _umul128
|
||||||
|
# endif
|
||||||
|
#elif defined(__i386__) || defined(_M_IX86)
|
||||||
|
# define HI32(X) \
|
||||||
|
_mm_srli_si128((X), 4)
|
||||||
|
|
||||||
|
|
||||||
|
# define EXTRACT64(X) \
|
||||||
|
((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
|
||||||
|
((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
|
||||||
|
|
||||||
|
static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
|
||||||
|
// multiplier = ab = a * 2^32 + b
|
||||||
|
// multiplicand = cd = c * 2^32 + d
|
||||||
|
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
||||||
|
uint64_t a = multiplier >> 32;
|
||||||
|
uint64_t b = multiplier & 0xFFFFFFFF;
|
||||||
|
uint64_t c = multiplicand >> 32;
|
||||||
|
uint64_t d = multiplicand & 0xFFFFFFFF;
|
||||||
|
|
||||||
|
//uint64_t ac = a * c;
|
||||||
|
uint64_t ad = a * d;
|
||||||
|
//uint64_t bc = b * c;
|
||||||
|
uint64_t bd = b * d;
|
||||||
|
|
||||||
|
uint64_t adbc = ad + (b * c);
|
||||||
|
uint64_t adbc_carry = adbc < ad ? 1 : 0;
|
||||||
|
|
||||||
|
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
||||||
|
uint64_t product_lo = bd + (adbc << 32);
|
||||||
|
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
|
||||||
|
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
|
||||||
|
|
||||||
|
return product_lo;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// This will shift and xor tmp1 into itself as 4 32-bit vals such as
|
||||||
|
// sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
|
||||||
|
static inline __m128i sl_xor(__m128i tmp1)
|
||||||
|
{
|
||||||
|
__m128i tmp4;
|
||||||
|
tmp4 = _mm_slli_si128(tmp1, 0x04);
|
||||||
|
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||||
|
return tmp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<uint8_t rcon>
|
||||||
|
static inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2)
|
||||||
|
{
|
||||||
|
__m128i xout1 = _mm_aeskeygenassist_si128(*xout2, rcon);
|
||||||
|
xout1 = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
|
||||||
|
*xout0 = sl_xor(*xout0);
|
||||||
|
*xout0 = _mm_xor_si128(*xout0, xout1);
|
||||||
|
xout1 = _mm_aeskeygenassist_si128(*xout0, 0x00);
|
||||||
|
xout1 = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem
|
||||||
|
*xout2 = sl_xor(*xout2);
|
||||||
|
*xout2 = _mm_xor_si128(*xout2, xout1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void soft_aes_genkey_sub(__m128i* xout0, __m128i* xout2, uint8_t rcon)
|
||||||
|
{
|
||||||
|
__m128i xout1 = soft_aeskeygenassist(*xout2, rcon);
|
||||||
|
xout1 = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
|
||||||
|
*xout0 = sl_xor(*xout0);
|
||||||
|
*xout0 = _mm_xor_si128(*xout0, xout1);
|
||||||
|
xout1 = soft_aeskeygenassist(*xout0, 0x00);
|
||||||
|
xout1 = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem
|
||||||
|
*xout2 = sl_xor(*xout2);
|
||||||
|
*xout2 = _mm_xor_si128(*xout2, xout1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<bool SOFT_AES>
|
||||||
|
static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
|
||||||
|
{
|
||||||
|
__m128i xout0 = _mm_load_si128(memory);
|
||||||
|
__m128i xout2 = _mm_load_si128(memory +1 );
|
||||||
|
*k0 = xout0;
|
||||||
|
*k1 = xout2;
|
||||||
|
|
||||||
|
SOFT_AES ? soft_aes_genkey_sub(&xout0, &xout2, 0x01) : aes_genkey_sub<0x01>(&xout0, &xout2);
|
||||||
|
*k2 = xout0;
|
||||||
|
*k3 = xout2;
|
||||||
|
|
||||||
|
SOFT_AES ? soft_aes_genkey_sub(&xout0, &xout2, 0x02) : aes_genkey_sub<0x02>(&xout0, &xout2);
|
||||||
|
*k4 = xout0;
|
||||||
|
*k5 = xout2;
|
||||||
|
|
||||||
|
SOFT_AES ? soft_aes_genkey_sub(&xout0, &xout2, 0x04) : aes_genkey_sub<0x04>(&xout0, &xout2);
|
||||||
|
*k6 = xout0;
|
||||||
|
*k7 = xout2;
|
||||||
|
|
||||||
|
SOFT_AES ? soft_aes_genkey_sub(&xout0, &xout2, 0x08) : aes_genkey_sub<0x08>(&xout0, &xout2);
|
||||||
|
*k8 = xout0;
|
||||||
|
*k9 = xout2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<bool SOFT_AES>
|
||||||
|
static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
|
||||||
|
{
|
||||||
|
if (SOFT_AES) {
|
||||||
|
*x0 = soft_aesenc(*x0, key);
|
||||||
|
*x1 = soft_aesenc(*x1, key);
|
||||||
|
*x2 = soft_aesenc(*x2, key);
|
||||||
|
*x3 = soft_aesenc(*x3, key);
|
||||||
|
*x4 = soft_aesenc(*x4, key);
|
||||||
|
*x5 = soft_aesenc(*x5, key);
|
||||||
|
*x6 = soft_aesenc(*x6, key);
|
||||||
|
*x7 = soft_aesenc(*x7, key);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*x0 = _mm_aesenc_si128(*x0, key);
|
||||||
|
*x1 = _mm_aesenc_si128(*x1, key);
|
||||||
|
*x2 = _mm_aesenc_si128(*x2, key);
|
||||||
|
*x3 = _mm_aesenc_si128(*x3, key);
|
||||||
|
*x4 = _mm_aesenc_si128(*x4, key);
|
||||||
|
*x5 = _mm_aesenc_si128(*x5, key);
|
||||||
|
*x6 = _mm_aesenc_si128(*x6, key);
|
||||||
|
*x7 = _mm_aesenc_si128(*x7, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<size_t MEM, bool SOFT_AES>
|
||||||
|
static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
|
||||||
|
{
|
||||||
|
__m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
|
||||||
|
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
|
||||||
|
|
||||||
|
aes_genkey<SOFT_AES>(input, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
|
||||||
|
|
||||||
|
xin0 = _mm_load_si128(input + 4);
|
||||||
|
xin1 = _mm_load_si128(input + 5);
|
||||||
|
xin2 = _mm_load_si128(input + 6);
|
||||||
|
xin3 = _mm_load_si128(input + 7);
|
||||||
|
xin4 = _mm_load_si128(input + 8);
|
||||||
|
xin5 = _mm_load_si128(input + 9);
|
||||||
|
xin6 = _mm_load_si128(input + 10);
|
||||||
|
xin7 = _mm_load_si128(input + 11);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) {
|
||||||
|
aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||||
|
aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||||
|
aes_round<SOFT_AES>(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||||
|
aes_round<SOFT_AES>(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||||
|
aes_round<SOFT_AES>(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||||
|
aes_round<SOFT_AES>(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||||
|
aes_round<SOFT_AES>(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||||
|
aes_round<SOFT_AES>(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||||
|
aes_round<SOFT_AES>(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||||
|
aes_round<SOFT_AES>(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||||
|
|
||||||
|
_mm_store_si128(output + i + 0, xin0);
|
||||||
|
_mm_store_si128(output + i + 1, xin1);
|
||||||
|
_mm_store_si128(output + i + 2, xin2);
|
||||||
|
_mm_store_si128(output + i + 3, xin3);
|
||||||
|
_mm_store_si128(output + i + 4, xin4);
|
||||||
|
_mm_store_si128(output + i + 5, xin5);
|
||||||
|
_mm_store_si128(output + i + 6, xin6);
|
||||||
|
_mm_store_si128(output + i + 7, xin7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<size_t MEM, bool SOFT_AES>
|
||||||
|
static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
|
||||||
|
{
|
||||||
|
__m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
|
||||||
|
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
|
||||||
|
|
||||||
|
aes_genkey<SOFT_AES>(output + 2, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
|
||||||
|
|
||||||
|
xout0 = _mm_load_si128(output + 4);
|
||||||
|
xout1 = _mm_load_si128(output + 5);
|
||||||
|
xout2 = _mm_load_si128(output + 6);
|
||||||
|
xout3 = _mm_load_si128(output + 7);
|
||||||
|
xout4 = _mm_load_si128(output + 8);
|
||||||
|
xout5 = _mm_load_si128(output + 9);
|
||||||
|
xout6 = _mm_load_si128(output + 10);
|
||||||
|
xout7 = _mm_load_si128(output + 11);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8)
|
||||||
|
{
|
||||||
|
xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
|
||||||
|
xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
|
||||||
|
xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
|
||||||
|
xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3);
|
||||||
|
xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4);
|
||||||
|
xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5);
|
||||||
|
xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
|
||||||
|
xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
|
||||||
|
|
||||||
|
aes_round<SOFT_AES>(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||||
|
aes_round<SOFT_AES>(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||||
|
aes_round<SOFT_AES>(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||||
|
aes_round<SOFT_AES>(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||||
|
aes_round<SOFT_AES>(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||||
|
aes_round<SOFT_AES>(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||||
|
aes_round<SOFT_AES>(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||||
|
aes_round<SOFT_AES>(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||||
|
aes_round<SOFT_AES>(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||||
|
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||||
|
}
|
||||||
|
|
||||||
|
_mm_store_si128(output + 4, xout0);
|
||||||
|
_mm_store_si128(output + 5, xout1);
|
||||||
|
_mm_store_si128(output + 6, xout2);
|
||||||
|
_mm_store_si128(output + 7, xout3);
|
||||||
|
_mm_store_si128(output + 8, xout4);
|
||||||
|
_mm_store_si128(output + 9, xout5);
|
||||||
|
_mm_store_si128(output + 10, xout6);
|
||||||
|
_mm_store_si128(output + 11, xout7);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES>
|
||||||
|
inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, cryptonight_ctx *__restrict__ ctx)
|
||||||
|
{
|
||||||
|
keccak(static_cast<const uint8_t*>(input), size, ctx->state0, 200);
|
||||||
|
|
||||||
|
cn_explode_scratchpad<MEM, SOFT_AES>((__m128i*) ctx->state0, (__m128i*) ctx->memory);
|
||||||
|
|
||||||
|
const uint8_t* l0 = ctx->memory;
|
||||||
|
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx->state0);
|
||||||
|
|
||||||
|
uint64_t al0 = h0[0] ^ h0[4];
|
||||||
|
uint64_t ah0 = h0[1] ^ h0[5];
|
||||||
|
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
|
||||||
|
|
||||||
|
uint64_t idx0 = h0[0] ^ h0[4];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ITERATIONS; i++) {
|
||||||
|
__m128i cx;
|
||||||
|
cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
|
||||||
|
|
||||||
|
if (SOFT_AES) {
|
||||||
|
cx = soft_aesenc(cx, _mm_set_epi64x(ah0, al0));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
|
||||||
|
}
|
||||||
|
|
||||||
|
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
|
||||||
|
idx0 = EXTRACT64(cx);
|
||||||
|
bx0 = cx;
|
||||||
|
|
||||||
|
uint64_t hi, lo, cl, ch;
|
||||||
|
cl = ((uint64_t*) &l0[idx0 & MASK])[0];
|
||||||
|
ch = ((uint64_t*) &l0[idx0 & MASK])[1];
|
||||||
|
lo = __umul128(idx0, cl, &hi);
|
||||||
|
|
||||||
|
al0 += hi;
|
||||||
|
ah0 += lo;
|
||||||
|
|
||||||
|
((uint64_t*)&l0[idx0 & MASK])[0] = al0;
|
||||||
|
((uint64_t*)&l0[idx0 & MASK])[1] = ah0;
|
||||||
|
|
||||||
|
ah0 ^= ch;
|
||||||
|
al0 ^= cl;
|
||||||
|
idx0 = al0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cn_implode_scratchpad<MEM, SOFT_AES>((__m128i*) ctx->memory, (__m128i*) ctx->state0);
|
||||||
|
|
||||||
|
keccakf(h0, 24);
|
||||||
|
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast<char*>(output));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES>
|
||||||
|
inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
|
||||||
|
{
|
||||||
|
keccak((const uint8_t *) input, size, ctx->state0, 200);
|
||||||
|
keccak((const uint8_t *) input + size, size, ctx->state1, 200);
|
||||||
|
|
||||||
|
const uint8_t* l0 = ctx->memory;
|
||||||
|
const uint8_t* l1 = ctx->memory + MEM;
|
||||||
|
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx->state0);
|
||||||
|
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx->state1);
|
||||||
|
|
||||||
|
cn_explode_scratchpad<MEM, SOFT_AES>((__m128i*) h0, (__m128i*) l0);
|
||||||
|
cn_explode_scratchpad<MEM, SOFT_AES>((__m128i*) h1, (__m128i*) l1);
|
||||||
|
|
||||||
|
uint64_t al0 = h0[0] ^ h0[4];
|
||||||
|
uint64_t al1 = h1[0] ^ h1[4];
|
||||||
|
uint64_t ah0 = h0[1] ^ h0[5];
|
||||||
|
uint64_t ah1 = h1[1] ^ h1[5];
|
||||||
|
|
||||||
|
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
|
||||||
|
__m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
|
||||||
|
|
||||||
|
uint64_t idx0 = h0[0] ^ h0[4];
|
||||||
|
uint64_t idx1 = h1[0] ^ h1[4];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ITERATIONS; i++) {
|
||||||
|
__m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
|
||||||
|
__m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]);
|
||||||
|
|
||||||
|
if (SOFT_AES) {
|
||||||
|
cx0 = soft_aesenc(cx0, _mm_set_epi64x(ah0, al0));
|
||||||
|
cx1 = soft_aesenc(cx1, _mm_set_epi64x(ah1, al1));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0));
|
||||||
|
cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
|
||||||
|
}
|
||||||
|
|
||||||
|
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
|
||||||
|
_mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
|
||||||
|
|
||||||
|
idx0 = EXTRACT64(cx0);
|
||||||
|
idx1 = EXTRACT64(cx1);
|
||||||
|
|
||||||
|
bx0 = cx0;
|
||||||
|
bx1 = cx1;
|
||||||
|
|
||||||
|
uint64_t hi, lo, cl, ch;
|
||||||
|
cl = ((uint64_t*) &l0[idx0 & MASK])[0];
|
||||||
|
ch = ((uint64_t*) &l0[idx0 & MASK])[1];
|
||||||
|
lo = __umul128(idx0, cl, &hi);
|
||||||
|
|
||||||
|
al0 += hi;
|
||||||
|
ah0 += lo;
|
||||||
|
|
||||||
|
((uint64_t*) &l0[idx0 & MASK])[0] = al0;
|
||||||
|
((uint64_t*) &l0[idx0 & MASK])[1] = ah0;
|
||||||
|
|
||||||
|
ah0 ^= ch;
|
||||||
|
al0 ^= cl;
|
||||||
|
idx0 = al0;
|
||||||
|
|
||||||
|
cl = ((uint64_t*) &l1[idx1 & MASK])[0];
|
||||||
|
ch = ((uint64_t*) &l1[idx1 & MASK])[1];
|
||||||
|
lo = __umul128(idx1, cl, &hi);
|
||||||
|
|
||||||
|
al1 += hi;
|
||||||
|
ah1 += lo;
|
||||||
|
|
||||||
|
((uint64_t*) &l1[idx1 & MASK])[0] = al1;
|
||||||
|
((uint64_t*) &l1[idx1 & MASK])[1] = ah1;
|
||||||
|
|
||||||
|
ah1 ^= ch;
|
||||||
|
al1 ^= cl;
|
||||||
|
idx1 = al1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cn_implode_scratchpad<MEM, SOFT_AES>((__m128i*) l0, (__m128i*) h0);
|
||||||
|
cn_implode_scratchpad<MEM, SOFT_AES>((__m128i*) l1, (__m128i*) h1);
|
||||||
|
|
||||||
|
keccakf(h0, 24);
|
||||||
|
keccakf(h1, 24);
|
||||||
|
|
||||||
|
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast<char*>(output));
|
||||||
|
extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast<char*>(output) + 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __CRYPTONIGHT_P_H__ */
|
||||||
60
src/crypto/CryptoNight_test.h
Normal file
60
src/crypto/CryptoNight_test.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CRYPTONIGHT_TEST_H__
|
||||||
|
#define __CRYPTONIGHT_TEST_H__
|
||||||
|
|
||||||
|
|
||||||
|
const static uint8_t test_input[152] = {
|
||||||
|
0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19,
|
||||||
|
0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9,
|
||||||
|
0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F,
|
||||||
|
0xA9, 0x3E, 0xE7, 0x24, 0xDE, 0xB5, 0x7D, 0x12, 0xCB, 0xC6, 0xC6, 0xF3, 0xB9, 0x24, 0xD9, 0x46,
|
||||||
|
0x12, 0x7C, 0x7A, 0x97, 0x41, 0x8F, 0x93, 0x48, 0x82, 0x8F, 0x0F, 0x02,
|
||||||
|
0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00,
|
||||||
|
0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B,
|
||||||
|
0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62,
|
||||||
|
0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92,
|
||||||
|
0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const static uint8_t test_output0[64] = {
|
||||||
|
0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66,
|
||||||
|
0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F,
|
||||||
|
0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7,
|
||||||
|
0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef XMRIG_NO_AEON
|
||||||
|
const static uint8_t test_output1[64] = {
|
||||||
|
0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE,
|
||||||
|
0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD,
|
||||||
|
0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E,
|
||||||
|
0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __CRYPTONIGHT_TEST_H__ */
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user