1
0
mirror of https://github.com/xmrig/xmrig.git synced 2025-12-08 08:23:34 -05:00

Compare commits

..

151 Commits

Author SHA1 Message Date
XMRig
ed0972da85 Update version. 2017-06-17 15:37:33 +03:00
xmrig
815f8cbb96 Update CHANGELOG.md 2017-06-17 15:34:42 +03:00
XMRig
ccc7fba2c4 Fix software AES. 2017-06-17 15:23:25 +03:00
xmrig
bf56ee00bc Update CHANGELOG.md 2017-06-16 16:43:16 +03:00
xmrig
0d4b908bfe Update CHANGELOG.md 2017-06-16 16:26:25 +03:00
XMRig
8bd2582416 Merge branch 'dev' of github.com:xmrig/xmrig into dev 2017-06-16 16:13:48 +03:00
XMRig
09e859d41e Fix for linux. 2017-06-16 16:13:29 +03:00
xmrig
6fd4d99fa1 Update README.md 2017-06-16 14:36:24 +03:00
XMRig
b8089e637a Print pool urls in summary. 2017-06-16 11:32:34 +03:00
XMRig
fed163568e Add option "--print-time". 2017-06-16 11:08:10 +03:00
XMRig
4e4c54314b New hashtable report. 2017-06-16 10:19:14 +03:00
XMRig
e759ddca49 Handle "Unauthenticated" error. 2017-06-15 22:30:56 +03:00
XMRig
fcb7b0fb3e Rename Telemetry class to Hashrate. 2017-06-15 21:00:25 +03:00
XMRig
d1bf9ddc3f Add missing file. 2017-06-15 18:09:29 +03:00
xmrig
ccc2d77592 Update CHANGELOG.md 2017-06-15 09:41:27 +03:00
xmrig
70b0a39dc8 Update CHANGELOG.md 2017-06-14 22:18:29 +03:00
XMRig
b34084b961 Merge remote-tracking branch 'remotes/origin/libuv' into dev 2017-06-14 21:34:21 +03:00
XMRig
1587fb27d2 Fixes. 2017-06-14 21:33:20 +03:00
Admin
faf14f5e5a Fixes for OS X. 2017-06-14 21:13:04 +03:00
XMRig
555eee8236 Add Cpu_mac.cpp 2017-06-14 20:51:47 +03:00
Admin
1bf428f8da Initial OS X support 2017-06-14 20:37:59 +03:00
XMRig
c86f9816d3 Merge branch 'libuv' of github.com:xmrig/xmrig into libuv 2017-06-14 19:13:48 +03:00
XMRig
599117abde Prepare for OS X. 2017-06-14 19:13:02 +03:00
xmrig
e3689ccb1a Move build instructions to Wiki 2017-06-14 16:49:47 +03:00
xmrig
babc48f767 Update README.md 2017-06-14 16:42:00 +03:00
xmrig
33d752bcaa Update README.md 2017-06-14 16:18:13 +03:00
XMRig
5af169fd7b Fix linux build. 2017-06-14 16:11:01 +03:00
XMRig
8ebb659cd6 Fix AEON donate port. 2017-06-14 09:03:03 +03:00
XMRig
7c8a9677a1 Fix crash. 2017-06-13 20:03:43 +03:00
XMRig
981e043ada Add DoubleWorker class. 2017-06-13 19:58:31 +03:00
XMRig
8c2951db2d Add signal handlers. 2017-06-13 13:20:15 +03:00
XMRig
2d08f59184 Remove obsolete source files. 2017-06-13 11:51:49 +03:00
XMRig
827e611911 Fix libcpuid support for MSVC. 2017-06-13 11:17:40 +03:00
XMRig
de2c351a66 Add MSVC optimization options. 2017-06-13 10:08:32 +03:00
XMRig
42bf85d10b Fixes for MSVC. 2017-06-13 06:31:25 +03:00
XMRig
9580c30d8a Fix cpuid stub for MSVC. 2017-06-12 16:55:21 +03:00
XMRig
3df545cfc5 Initial MSVC support. 2017-06-12 16:19:07 +03:00
XMRig
a370b8fd30 Add class Telemetry. 2017-06-12 07:18:14 +03:00
XMRig
6774f86fcd Implement job result submitting. 2017-06-11 15:32:15 +03:00
XMRig
a0a8711dab Add class JobResult. 2017-06-11 10:58:46 +03:00
XMRig
3ad11685cc Job flow WIP. 2017-06-11 06:52:23 +03:00
XMRig
bcef4b12ec Job flow. 2017-06-10 13:32:27 +03:00
XMRig
f9c244f0aa Add Workers class. 2017-06-10 09:41:08 +03:00
XMRig
29aa466023 Add IWorker, Handle, SingleWorker, Worker classes. 2017-06-10 07:05:00 +03:00
XMRig
b772349f69 Add memory summary. 2017-06-10 01:20:54 +03:00
XMRig
c5fbc1a182 Restore persistent memory. 2017-06-10 00:43:23 +03:00
XMRig
30642881bf Add Mem class. 2017-06-09 15:09:21 +03:00
XMRig
ef3af1c4fd Restore autoconf. 2017-06-09 03:37:56 +03:00
XMRig
04c5d6d00a Print threads summary. 2017-06-09 02:47:46 +03:00
XMRig
8b83a5fe2e Implemented CryptoNight with C++ templates. 2017-06-08 23:31:42 +03:00
XMRig
878e021ff6 Initial CryptoNight. 2017-06-08 09:47:25 +03:00
XMRig
5a606be8be Move crypto/* 2017-06-08 04:20:10 +03:00
XMRig
da02e9a3a2 Reduce libcpuid size. 2017-06-08 04:16:55 +03:00
XMRig
b11f95d248 Restore libcpuid support. 2017-06-08 01:51:24 +03:00
XMRig
9797f49456 Add Summary. 2017-06-08 01:16:45 +03:00
XMRig
0556fd664c Add Cpu class. 2017-06-08 00:10:26 +03:00
XMRig
1cf5ad5212 Implemented switch to donate pool. 2017-06-07 22:34:23 +03:00
XMRig
c31ea00399 Basic failover support. 2017-06-07 09:07:31 +03:00
XMRig
387524e1c5 Fix for error notification. 2017-06-07 07:34:14 +03:00
XMRig
5f1f901649 Add support for keepAlive. 2017-06-07 06:48:00 +03:00
XMRig
c29dc8bcf4 Implemented reconnect. 2017-06-07 04:19:32 +03:00
XMRig
b8cc1136a4 More flexible pools configuration. 2017-06-07 02:46:52 +03:00
XMRig
4c06d8b080 Handle job notification. 2017-06-07 01:19:59 +03:00
XMRig
1ecee56eb6 Add Job class. 2017-06-06 20:43:52 +03:00
XMRig
26b8206332 Basic login parse. 2017-06-06 06:35:17 +03:00
XMRig
7deee3240b Handle jsonrpc errors. 2017-06-06 06:05:17 +03:00
XMRig
668b23c5b0 Initial libuv support build. 2017-06-04 20:52:21 +03:00
Admin
7741c341c7 Huge pages support on OS X. 2017-05-27 10:34:42 +03:00
XMRig
8a70202a98 Fix. 2017-05-27 08:45:11 +03:00
Admin
bc2b7d1895 Initial OS X support. 2017-05-26 23:17:12 +03:00
xmrig
ebb0f81f2f Update CHANGELOG.md 2017-05-26 09:07:45 +03:00
XMRig
eb3e2b8868 Fix gcc7 support. 2017-05-25 09:32:39 +03:00
XMRig
583d892eb5 Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97 2017-05-24 18:50:24 +03:00
XMRig
b145f14ad8 Merge branch 'dev' 2017-05-20 23:53:16 +03:00
xmrig
ce19edf36c Update CHANGELOG.md 2017-05-20 23:48:53 +03:00
xmrig
108fd5690e Update README.md 2017-05-20 23:43:39 +03:00
XMRig
c19fe3cea7 Add "--nicehash" to help output. 2017-05-20 23:38:05 +03:00
XMRig
187c7680cc Show errors from pool. 2017-05-20 23:27:22 +03:00
XMRig
20061e1b8b Autodetect nicehash by url 2017-05-20 09:31:02 +03:00
XMRig
2baccab0f9 Initial test nicehash support. 2017-05-20 07:08:41 +03:00
XMRig
44782befea Fix 32 bit build. 2017-05-16 17:04:27 +03:00
XMRig
5b7a1bc6dc Merge branch 'dev' 2017-05-15 22:10:45 +03:00
XMRig
e67a95bd8b Version increment and update help. 2017-05-15 22:06:54 +03:00
xmrig
88dd218ad8 Update README.md 2017-05-15 19:57:20 +03:00
xmrig
ee9ba778f8 Update README.md 2017-05-15 18:32:27 +03:00
xmrig
6080f292e7 Update CHANGELOG.md 2017-05-13 22:39:40 +03:00
xmrig
cf8f81f5fa Update CHANGELOG.md 2017-05-13 22:32:29 +03:00
xmrig
aab48fde96 Update README.md 2017-05-13 20:31:27 +03:00
xmrig
bf25b4e5d4 Update README.md 2017-05-13 20:26:35 +03:00
XMRig
0c2bda9aa5 Remove default url. 2017-05-13 19:47:12 +03:00
XMRig
d71a15e8da Use --safe options to disable AES algo variations if CPU not support it. 2017-05-12 15:04:04 +03:00
XMRig
c4bccf410b * Implement --max-cpu-usage.
* Fix L2 cache size detect.
* Add test for get_optimal_threads_count.
2017-05-10 19:38:35 +03:00
XMRig
719601f92b Add test for cryptonight lite. 2017-05-10 15:31:29 +03:00
XMRig
ff7be00f6f Fix test. 2017-05-10 15:06:01 +03:00
XMRig
d3b0038bda Add optional CryptoNight-Lite support. 2017-05-10 12:58:52 +03:00
XMRig
3b46f5eb64 Remove BMI2 av. 2017-05-08 23:28:39 +03:00
XMRig
03dbb85c82 Update test values. 2017-05-08 23:06:00 +03:00
XMRig
a2574e1b1b Added message if huge pages was enabled, but reboot required. 2017-05-08 21:41:27 +03:00
XMRig
15b4244ea8 Added --max-cpu-usage and --safe stub. 2017-05-08 10:29:25 +03:00
XMRig
0dcf127c26 Version increment. 2017-05-06 09:44:50 +03:00
xmrig
9964952c92 Update CHANGELOG.md 2017-05-05 19:54:31 +03:00
XMRig
90648771c0 Fix 32bit build. 2017-05-05 19:51:53 +03:00
XMRig
985adcbc13 No more manual steps to enable huge pages on Windows. XMRig will do it automatically. 2017-05-05 15:49:38 +03:00
XMRig
16f3338e42 Fix crash when use Keepalived. 2017-05-05 10:48:56 +03:00
XMRig
2650545916 Code cleanup. 2017-05-04 14:18:14 +03:00
xmrig
c107547c6c Update CHANGELOG.md 2017-05-03 15:16:46 +03:00
XMRig
60f7f93408 Merge branch 'feature-libcpuid' 2017-05-03 15:07:09 +03:00
XMRig
dfbfde5b22 Fix Linux build. 2017-05-03 15:03:33 +03:00
XMRig
0c752ee018 Use libcpuid as internal dependence. 2017-05-03 14:36:42 +03:00
XMRig
f329410940 Use libcpuid for detect optimal threads count. 2017-05-03 13:48:08 +03:00
XMRig
0a6d70c499 Add optional libcpuid support to cmake. 2017-05-03 10:53:51 +03:00
XMRig
1678dc1d6d Implement low power mode (double hash). 2017-05-01 03:49:05 +03:00
XMRig
caf7cda1d5 Backport changes from xmrig-aeon. 2017-04-30 02:56:47 +03:00
XMRig
3de7983826 Fix for donate level. 2017-04-26 18:05:04 +03:00
XMRig
8dda8d293b Update README.md. 2017-04-25 03:35:03 +03:00
XMRig
e71e9486c6 Remove conflicting declaration for _mulx_u64. 2017-04-25 03:20:32 +03:00
XMRig
b35ecef06f Move common code to cryptonight_p.h 2017-04-24 13:23:49 +03:00
XMRig
454c78cf0a Fix const. 2017-04-23 23:56:47 +03:00
XMRig
c97693cd51 Merge branch 'master' of github.com:xmrig/xmrig 2017-04-22 18:08:44 +03:00
XMRig
d855ae2e36 Merge branch 'bug-128tx-exploit' 2017-04-22 18:08:15 +03:00
XMRig
42d2ab18ee Update tests. 2017-04-22 17:12:50 +03:00
XMRig
97a8d448c0 Pass blob size to cryptonight_hash_ctx. 2017-04-22 15:34:05 +03:00
XMRig
54cef68aa9 Optimize job_decode, support variable length blob and redume mutex lock
time.
2017-04-22 13:19:33 +03:00
xmrig
3492670839 Merge pull request #3 from esfomeado/patch-1
More detailed instructions to build on Windows
2017-04-21 18:39:04 +03:00
xmrig
c43c667fed Update CHANGELOG.md 2017-04-21 18:31:58 +03:00
XMRig
361394be21 Add automatic self test. 2017-04-21 17:29:03 +03:00
XMRig
8235ae0fa6 Add 32 bit support for software AES too. 2017-04-21 15:47:11 +03:00
XMRig
ac89023a79 Add support for 32 bit. 2017-04-21 15:20:08 +03:00
XMRig
f92b5ed9f6 Merge branch 'master' of github.com:xmrig/xmrig 2017-04-21 13:06:29 +03:00
XMRig
7ce21d458a Version increment. 2017-04-21 13:06:13 +03:00
xmrig
5513fab59b Update README.md 2017-04-21 12:34:59 +03:00
XMRig
5e6560cb07 Fix affinity for single thread mode. 2017-04-21 12:13:49 +03:00
Esfomeado
25d76626c1 More detailed instructions to build on Windows 2017-04-21 10:08:04 +01:00
XMRig
cad15069c8 Revert back BMI2 support. 2017-04-21 12:05:28 +03:00
XMRig
8ab4c1c8bd Add memory to cryptonight_ctx. 2017-04-21 11:56:11 +03:00
XMRig
f29d05bdde Simplify cryptonight_ctx. 2017-04-21 11:14:27 +03:00
XMRig
1474d3fe53 Rename algo variants again, should be final numbers. 2017-04-21 10:40:11 +03:00
XMRig
d2fd43ca03 Change algo variant numbers. 2017-04-21 09:20:19 +03:00
XMRig
95f48fd058 Add app.rc and app.ico for Windows. 2017-04-19 20:52:00 +03:00
XMRig
f8bda3a6b3 Add CHANGELOG.md. 2017-04-19 10:20:04 +03:00
XMRig
21c243ed8f Much better software AES implementation (--av 4). 2017-04-19 10:03:40 +03:00
XMRig
1013aa5004 Update av1/av6 2017-04-19 07:58:42 +03:00
XMRig
44875b0a94 Fix test. 2017-04-18 17:40:19 +03:00
XMRig
b1f1474438 Merge branch 'feature-xmr-stak-algo' 2017-04-18 16:04:50 +03:00
XMRig
4eb7e5bbfd Fix stak algo as --av 5, experimental algo now --av 6 2017-04-18 15:57:44 +03:00
XMRig
d874ede49e Fix. 2017-04-18 13:14:09 +03:00
XMRig
add10c829c No templates in C :( 2017-04-18 13:10:40 +03:00
XMRig
4acfb213b8 Add xmr-stak-cpu algo as experimental, use --av=5. 2017-04-18 12:06:46 +03:00
xmrig
78a4b9de0f Update README.md 2017-04-17 05:44:49 +03:00
xmrig
9fe2bbcd81 Update README.md 2017-04-16 16:37:12 +03:00
xmrig
adb778de8a Update README.md 2017-04-15 10:52:08 +03:00
156 changed files with 10353 additions and 7141 deletions

1
.gitignore vendored
View File

@@ -1 +1,2 @@
/build /build
/CMakeLists.txt.user

41
CHANGELOG.md Normal file
View 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.

View File

@@ -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})

View File

@@ -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/)

View File

@@ -1,2 +0,0 @@
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mbmi2")
add_library(cryptonight_av3_aesni_bmi2 STATIC ../cryptonight_av3_aesni_bmi2.c)

View File

@@ -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__ */

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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
View 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)

View File

@@ -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__ */

View File

@@ -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);
}

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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
View File

@@ -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
View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

37
res/app.rc Normal file
View 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

View File

@@ -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
View 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__) */

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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"

View File

@@ -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

View File

@@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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__ */

View 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__ */

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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__*/

View File

@@ -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;

View File

@@ -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
View 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
View 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__ */

View File

@@ -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);
}
}

View File

@@ -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
View 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
View 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
View 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
View File

@@ -0,0 +1,63 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 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__ */

View File

@@ -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)
{
}

View File

@@ -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;
} }
} }

View File

@@ -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);
} }

View File

@@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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();
}

View File

@@ -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
View 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
View 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
View 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__ */

View 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