Compare commits

...

33 Commits

Author SHA1 Message Date
Jay D Dee
c85fb3842b v3.15.0 2020-10-02 10:48:37 -04:00
Jay D Dee
cdd587537e v3.14.3 2020-06-18 17:30:26 -04:00
Jay D Dee
51a1d91abd v3.14.2 2020-05-30 21:20:44 -04:00
Jay D Dee
13563e2598 v3.14.1 2020-05-21 13:00:29 -04:00
Jay D Dee
9571f85d53 v3.14.0 2020-05-20 13:56:35 -04:00
Jay D Dee
0e69756634 v3.13.2-segwit-test 2020-05-18 18:17:27 -04:00
Jay D Dee
9653bca1e2 v3.13.1.1 2020-05-17 19:21:37 -04:00
Jay D Dee
1c0719e8a4 v3.13.1 2020-05-10 21:34:55 -04:00
Jay D Dee
8b4b4dc613 v3.13.0.1 2020-05-07 17:57:04 -04:00
Jay D Dee
e76feaced8 v3.13.0 2020-05-06 00:53:43 -04:00
Jay D Dee
5e088d00d0 v3.12.8.2 2020-04-24 21:18:56 -04:00
Jay D Dee
972d4d70db v3.12.8.1 2020-04-17 16:12:45 -04:00
Jay D Dee
e96a6bd699 v3.12.8 2020-04-09 12:56:18 -04:00
Jay D Dee
fb9163185a v3.12.7 2020-03-20 16:30:12 -04:00
Jay D Dee
6e8b8ed34f v3.12.6.1 2020-03-07 14:11:06 -05:00
Jay D Dee
c0aadbcc99 v3.12.6 2020-03-05 18:43:20 -05:00
Jay D Dee
3da149418a v3.12.5 2020-03-01 13:18:17 -05:00
Jay D Dee
720610cce5 v3.12.4.6 2020-02-28 18:20:32 -05:00
Jay D Dee
cedcf4d070 v3.12.4.5 2020-02-28 02:42:22 -05:00
Jay D Dee
81b50c3c71 v3.12.4.4 2020-02-25 14:07:32 -05:00
Jay D Dee
0e1e88f53e v3.12.4.3 2020-02-24 21:35:19 -05:00
Jay D Dee
45c77a5c81 v3.12.4.2 2020-02-23 15:31:06 -05:00
Jay D Dee
dbce7e0721 v3.12.4.1 2020-02-22 18:06:39 -05:00
Jay D Dee
6d66051de6 v3.12.4 2020-02-21 16:34:53 -05:00
Jay D Dee
b93be8816a v3.12.3.1 2020-02-18 12:05:47 -05:00
Jay D Dee
19b0ac6d5c v3.12.3 2020-02-13 04:25:33 -05:00
Jay D Dee
3da2b958cf v3.12.2 2020-02-09 13:30:40 -05:00
Jay D Dee
dc2f8d81d3 v3.12.1 2020-02-07 20:18:20 -05:00
Jay D Dee
fc97ef174a v3.12.0.1 2020-02-06 22:50:20 -05:00
Jay D Dee
13523a12f9 v3.12.0 2020-02-05 22:50:58 -05:00
Jay D Dee
1b76cee239 v3.11.9 2020-02-04 01:31:59 -05:00
Jay D Dee
0681ca996d v3.11.8 2020-01-30 03:47:11 -05:00
Jay D Dee
88f81fda0b v3.11.7 2020-01-26 04:33:39 -05:00
273 changed files with 13223 additions and 29452 deletions

View File

@@ -21,15 +21,6 @@ cpuminer_SOURCES = \
api.c \ api.c \
sysinfos.c \ sysinfos.c \
algo-gate-api.c\ algo-gate-api.c\
crypto/oaes_lib.c \
crypto/c_keccak.c \
crypto/c_groestl.c \
crypto/c_blake256.c \
crypto/c_jh.c \
crypto/c_skein.c \
crypto/hash.c \
crypto/aesb.c \
crypto/magimath.cpp \
algo/argon2/argon2a/argon2a.c \ algo/argon2/argon2a/argon2a.c \
algo/argon2/argon2a/ar2/argon2.c \ algo/argon2/argon2a/ar2/argon2.c \
algo/argon2/argon2a/ar2/opt.c \ algo/argon2/argon2a/ar2/opt.c \
@@ -76,11 +67,6 @@ cpuminer_SOURCES = \
algo/bmw/bmw512-gate.c \ algo/bmw/bmw512-gate.c \
algo/bmw/bmw512.c \ algo/bmw/bmw512.c \
algo/bmw/bmw512-4way.c \ algo/bmw/bmw512-4way.c \
algo/cryptonight/cryptolight.c \
algo/cryptonight/cryptonight-common.c\
algo/cryptonight/cryptonight-aesni.c\
algo/cryptonight/cryptonight.c\
algo/cubehash/sph_cubehash.c \
algo/cubehash/cubehash_sse2.c\ algo/cubehash/cubehash_sse2.c\
algo/cubehash/cube-hash-2way.c \ algo/cubehash/cube-hash-2way.c \
algo/echo/sph_echo.c \ algo/echo/sph_echo.c \
@@ -99,13 +85,11 @@ cpuminer_SOURCES = \
algo/groestl/aes_ni/hash-groestl.c \ algo/groestl/aes_ni/hash-groestl.c \
algo/groestl/aes_ni/hash-groestl256.c \ algo/groestl/aes_ni/hash-groestl256.c \
algo/fugue/sph_fugue.c \ algo/fugue/sph_fugue.c \
algo/fugue/fugue-aesni.c \
algo/hamsi/sph_hamsi.c \ algo/hamsi/sph_hamsi.c \
algo/hamsi/hamsi-hash-4way.c \ algo/hamsi/hamsi-hash-4way.c \
algo/haval/haval.c \ algo/haval/haval.c \
algo/haval/haval-hash-4way.c \ algo/haval/haval-hash-4way.c \
algo/heavy/sph_hefty1.c \
algo/heavy/heavy.c \
algo/heavy/bastion.c \
algo/hodl/aes.c \ algo/hodl/aes.c \
algo/hodl/hodl-gate.c \ algo/hodl/hodl-gate.c \
algo/hodl/hodl-wolf.c \ algo/hodl/hodl-wolf.c \
@@ -121,9 +105,9 @@ cpuminer_SOURCES = \
algo/keccak/keccak-hash-4way.c \ algo/keccak/keccak-hash-4way.c \
algo/keccak/keccak-4way.c\ algo/keccak/keccak-4way.c\
algo/keccak/keccak-gate.c \ algo/keccak/keccak-gate.c \
algo/keccak/sha3d-4way.c \
algo/keccak/sha3d.c \
algo/lanehash/lane.c \ algo/lanehash/lane.c \
algo/luffa/sph_luffa.c \
algo/luffa/luffa.c \
algo/luffa/luffa_for_sse2.c \ algo/luffa/luffa_for_sse2.c \
algo/luffa/luffa-hash-2way.c \ algo/luffa/luffa-hash-2way.c \
algo/lyra2/lyra2.c \ algo/lyra2/lyra2.c \
@@ -145,14 +129,14 @@ cpuminer_SOURCES = \
algo/lyra2/allium.c \ algo/lyra2/allium.c \
algo/lyra2/phi2-4way.c \ algo/lyra2/phi2-4way.c \
algo/lyra2/phi2.c \ algo/lyra2/phi2.c \
algo/m7m.c \ algo//m7m/m7m.c \
algo/m7m/magimath.cpp \
algo/nist5/nist5-gate.c \ algo/nist5/nist5-gate.c \
algo/nist5/nist5-4way.c \ algo/nist5/nist5-4way.c \
algo/nist5/nist5.c \ algo/nist5/nist5.c \
algo/nist5/zr5.c \ algo/nist5/zr5.c \
algo/panama/panama-hash-4way.c \ algo/panama/panama-hash-4way.c \
algo/panama/sph_panama.c \ algo/panama/sph_panama.c \
algo/radiogatun/sph_radiogatun.c \
algo/quark/quark-gate.c \ algo/quark/quark-gate.c \
algo/quark/quark.c \ algo/quark/quark.c \
algo/quark/quark-4way.c \ algo/quark/quark-4way.c \
@@ -175,11 +159,12 @@ cpuminer_SOURCES = \
algo/ripemd/lbry-4way.c \ algo/ripemd/lbry-4way.c \
algo/scrypt/scrypt.c \ algo/scrypt/scrypt.c \
algo/scrypt/neoscrypt.c \ algo/scrypt/neoscrypt.c \
algo/scrypt/pluck.c \
algo/sha/sph_sha2.c \ algo/sha/sph_sha2.c \
algo/sha/sph_sha2big.c \ algo/sha/sph_sha2big.c \
algo/sha/sha256-hash-4way.c \ algo/sha/sha256-hash-4way.c \
algo/sha/sha512-hash-4way.c \ algo/sha/sha512-hash-4way.c \
algo/sha/hmac-sha256-hash.c \
algo/sha/hmac-sha256-hash-4way.c \
algo/sha/sha2.c \ algo/sha/sha2.c \
algo/sha/sha256t-gate.c \ algo/sha/sha256t-gate.c \
algo/sha/sha256t-4way.c \ algo/sha/sha256t-4way.c \
@@ -193,7 +178,6 @@ cpuminer_SOURCES = \
algo/shavite/shavite-hash-2way.c \ algo/shavite/shavite-hash-2way.c \
algo/shavite/shavite-hash-4way.c \ algo/shavite/shavite-hash-4way.c \
algo/shavite/shavite.c \ algo/shavite/shavite.c \
algo/simd/sph_simd.c \
algo/simd/nist.c \ algo/simd/nist.c \
algo/simd/vector.c \ algo/simd/vector.c \
algo/simd/simd-hash-2way.c \ algo/simd/simd-hash-2way.c \
@@ -231,7 +215,6 @@ cpuminer_SOURCES = \
algo/x11/timetravel10-gate.c \ algo/x11/timetravel10-gate.c \
algo/x11/timetravel10.c \ algo/x11/timetravel10.c \
algo/x11/timetravel10-4way.c \ algo/x11/timetravel10-4way.c \
algo/x11/fresh.c \
algo/x11/x11evo.c \ algo/x11/x11evo.c \
algo/x11/x11evo-4way.c \ algo/x11/x11evo-4way.c \
algo/x11/x11evo-gate.c \ algo/x11/x11evo-gate.c \
@@ -250,7 +233,6 @@ cpuminer_SOURCES = \
algo/x13/skunk-gate.c \ algo/x13/skunk-gate.c \
algo/x13/skunk-4way.c \ algo/x13/skunk-4way.c \
algo/x13/skunk.c \ algo/x13/skunk.c \
algo/x13/drop.c \
algo/x13/x13bcd-4way.c \ algo/x13/x13bcd-4way.c \
algo/x13/x13bcd.c \ algo/x13/x13bcd.c \
algo/x14/x14-gate.c \ algo/x14/x14-gate.c \
@@ -276,6 +258,7 @@ cpuminer_SOURCES = \
algo/x16/hex.c \ algo/x16/hex.c \
algo/x16/x21s-4way.c \ algo/x16/x21s-4way.c \
algo/x16/x21s.c \ algo/x16/x21s.c \
algo/x16/minotaur.c \
algo/x17/x17-gate.c \ algo/x17/x17-gate.c \
algo/x17/x17.c \ algo/x17/x17.c \
algo/x17/x17-4way.c \ algo/x17/x17-4way.c \
@@ -285,19 +268,17 @@ cpuminer_SOURCES = \
algo/x17/sonoa-gate.c \ algo/x17/sonoa-gate.c \
algo/x17/sonoa-4way.c \ algo/x17/sonoa-4way.c \
algo/x17/sonoa.c \ algo/x17/sonoa.c \
algo/x20/x20r.c \
algo/x22/x22i-4way.c \ algo/x22/x22i-4way.c \
algo/x22/x22i.c \ algo/x22/x22i.c \
algo/x22/x22i-gate.c \ algo/x22/x22i-gate.c \
algo/x22/x25x.c \ algo/x22/x25x.c \
algo/x22/x25x-4way.c \ algo/x22/x25x-4way.c \
algo/yescrypt/yescrypt.c \ algo/yescrypt/yescrypt.c \
algo/yescrypt/sha256_Y.c \
algo/yescrypt/yescrypt-best.c \ algo/yescrypt/yescrypt-best.c \
algo/yespower/yespower-gate.c \ algo/yespower/yespower-gate.c \
algo/yespower/yespower-blake2b.c \ algo/yespower/yespower-blake2b.c \
algo/yespower/crypto/blake2b-yp.c \ algo/yespower/crypto/blake2b-yp.c \
algo/yespower/sha256_p.c \ algo/yespower/yescrypt-r8g.c \
algo/yespower/yespower-opt.c algo/yespower/yespower-opt.c
disable_flags = disable_flags =

View File

@@ -12,10 +12,24 @@ a false positive, they are flagged simply because they are cryptocurrency
miners. The source code is open for anyone to inspect. If you don't trust miners. The source code is open for anyone to inspect. If you don't trust
the software, don't use it. the software, don't use it.
New thread:
https://bitcointalk.org/index.php?topic=5226770.msg53865575#msg53865575
Old thread:
https://bitcointalk.org/index.php?topic=1326803.0 https://bitcointalk.org/index.php?topic=1326803.0
mailto://jayddee246@gmail.com mailto://jayddee246@gmail.com
This note is to confirm that bitcointalk users JayDDee and joblo are the
same person.
I created a new BCT user JayDDee to match my github user id.
The old thread has been locked but still contains useful information for
reading.
See file RELEASE_NOTES for change log and INSTALL_LINUX or INSTALL_WINDOWS See file RELEASE_NOTES for change log and INSTALL_LINUX or INSTALL_WINDOWS
for compile instructions. for compile instructions.
@@ -23,25 +37,25 @@ Requirements
------------ ------------
1. A x86_64 architecture CPU with a minimum of SSE2 support. This includes 1. A x86_64 architecture CPU with a minimum of SSE2 support. This includes
Intel Core2 and newer and AMD equivalents. In order to take advantage of AES_NI Intel Core2 and newer and AMD equivalents. Further optimizations are available
optimizations a CPU with AES_NI is required. This includes Intel Westmere on some algoritms for CPUs with AES, AVX, AVX2, SHA, AVX512 and VAES.
and newer and AMD equivalents. Further optimizations are available on some
algoritms for CPUs with AVX and AVX2, Sandybridge and Haswell respectively.
Older CPUs are supported by cpuminer-multi by TPruvot but at reduced Older CPUs are supported by cpuminer-multi by TPruvot but at reduced
performance. performance.
ARM CPUs are not supported. ARM and Aarch64 CPUs are not supported.
2. 64 bit Linux OS. Ubuntu and Fedora based distributions, including Mint and 2. 64 bit Linux or Windows OS. Ubuntu and Fedora based distributions,
Centos, are known to work and have all dependencies in their repositories. including Mint and Centos, are known to work and have all dependencies
Others may work but may require more effort. Older versions such as Centos 6 in their repositories. Others may work but may require more effort. Older
don't work due to missing features. versions such as Centos 6 don't work due to missing features.
64 bit Windows OS is supported with mingw_w64 and msys or pre-built binaries. 64 bit Windows OS is supported with mingw_w64 and msys or pre-built binaries.
MacOS, OSx and Android are not supported. MacOS, OSx and Android are not supported.
3. Stratum pool. Some algos may work wallet mining using getwork or GBT. YMMV. 3. Stratum pool supporting stratum+tcp:// or stratum+ssl:// protocols or
RPC getwork using http:// or https://.
GBT is YMMV.
Supported Algorithms Supported Algorithms
-------------------- --------------------
@@ -53,7 +67,6 @@ Supported Algorithms
argon2d500 argon2d-dyn, Dynamic (DYN) argon2d500 argon2d-dyn, Dynamic (DYN)
argon2d4096 argon2d-uis, Unitus, (UIS) argon2d4096 argon2d-uis, Unitus, (UIS)
axiom Shabal-256 MemoHash axiom Shabal-256 MemoHash
bastion
blake Blake-256 (SFR) blake Blake-256 (SFR)
blake2b Blake2b 256 blake2b Blake2b 256
blake2s Blake-2 S blake2s Blake-2 S
@@ -64,10 +77,7 @@ Supported Algorithms
decred decred
deep Deepcoin (DCN) deep Deepcoin (DCN)
dmd-gr Diamond-Groestl dmd-gr Diamond-Groestl
drop Dropcoin
fresh Fresh
groestl Groestl coin groestl Groestl coin
heavy Heavy
hex x16r-hex hex x16r-hex
hmq1725 Espers hmq1725 Espers
hodl Hodlcoin hodl Hodlcoin
@@ -83,6 +93,7 @@ Supported Algorithms
lyra2z lyra2z
lyra2z330 Lyra2 330 rows, Zoin (ZOI) lyra2z330 Lyra2 330 rows, Zoin (ZOI)
m7m Magi (XMG) m7m Magi (XMG)
minotaur Ringcoin (RNG)
myr-gr Myriad-Groestl myr-gr Myriad-Groestl
neoscrypt NeoScrypt(128, 2, 1) neoscrypt NeoScrypt(128, 2, 1)
nist5 Nist5 nist5 Nist5
@@ -97,10 +108,10 @@ Supported Algorithms
qubit Qubit qubit Qubit
scrypt scrypt(1024, 1, 1) (default) scrypt scrypt(1024, 1, 1) (default)
scrypt:N scrypt(N, 1, 1) scrypt:N scrypt(N, 1, 1)
scryptjane:nf
sha256d Double SHA-256 sha256d Double SHA-256
sha256q Quad SHA-256, Pyrite (PYE) sha256q Quad SHA-256, Pyrite (PYE)
sha256t Triple SHA-256, Onecoin (OC) sha256t Triple SHA-256, Onecoin (OC)
sha3d Double keccak256 (BSHA3)
shavite3 Shavite3 shavite3 Shavite3
skein Skein+Sha (Skeincoin) skein Skein+Sha (Skeincoin)
skein2 Double Skein (Woodcoin) skein2 Double Skein (Woodcoin)
@@ -134,6 +145,7 @@ Supported Algorithms
xevan Bitsend (BSD) xevan Bitsend (BSD)
yescrypt Globalboost-Y (BSTY) yescrypt Globalboost-Y (BSTY)
yescryptr8 BitZeny (ZNY) yescryptr8 BitZeny (ZNY)
yescryptr8g Koto (KOTO)
yescryptr16 Eli yescryptr16 Eli
yescryptr32 WAVI yescryptr32 WAVI
yespower Cryply yespower Cryply
@@ -141,6 +153,27 @@ Supported Algorithms
yespower-b2b generic yespower + blake2b yespower-b2b generic yespower + blake2b
zr5 Ziftr zr5 Ziftr
Many variations of scrypt based algos can be mine by specifying their
parameters:
scryptn2: --algo scrypt --param-n 1048576
cpupower: --algo yespower --param-key "CPUpower: The number of CPU working or available for proof-of-work mining"
power2b: --algo yespower-b2b --param-n 2048 --param-r 32 --param-key "Now I am become Death, the destroyer of worlds"
sugarchain: --algo yespower --param-n 2048 -param-r 32 --param-key "Satoshi Nakamoto 31/Oct/2008 Proof-of-work is essentially one-CPU-one-vote"
yespoweriots: --algo yespower --param-n 2048 --param-key "Iots is committed to the development of IOT"
yespowerlitb: --algo yespower --param-n 2048 --param-r 32 --param-key "LITBpower: The number of LITB working or available for proof-of-work mini"
yespoweric: --algo yespower --param-n 2048 --param-r 32 --param-key "IsotopeC"
yespowerurx: --algo yespower --param-n 2048 --param-r 32 --param-key "UraniumX"
yespowerltncg: --algo yespower --param-n 2048 --param-r 32 --param-key "LTNCGYES"
Errata Errata
------ ------

View File

@@ -1,8 +1,8 @@
This file is included in the Windows binary package. Compile instructions This file is included in the Windows binary package. Compile instructions
for Linux and Windows can be found in RELEASE_NOTES. for Linux and Windows can be found in RELEASE_NOTES.
cpuminer is a console program that is executed from a DOS command prompt. cpuminer is a console program that is executed from a DOS or Powershell
There is no GUI and no mouse support. prompt. There is no GUI and no mouse support.
Miner programs are often flagged as malware by antivirus programs. This is Miner programs are often flagged as malware by antivirus programs. This is
a false positive, they are flagged simply because they are cryptocurrency a false positive, they are flagged simply because they are cryptocurrency
@@ -15,8 +15,8 @@ the features listed at cpuminer startup to ensure you are mining at
optimum speed using the best available features. optimum speed using the best available features.
Architecture names and compile options used are only provided for Intel Architecture names and compile options used are only provided for Intel
Core series. Budget CPUs like Pentium and Celeron are often missing the Core series. Budget CPUs like Pentium and Celeron are often missing some
latest features. features.
AMD CPUs older than Piledriver, including Athlon x2 and Phenom II x4, are not AMD CPUs older than Piledriver, including Athlon x2 and Phenom II x4, are not
supported by cpuminer-opt due to an incompatible implementation of SSE2 on supported by cpuminer-opt due to an incompatible implementation of SSE2 on
@@ -31,14 +31,29 @@ https://en.wikipedia.org/wiki/List_of_Intel_CPU_microarchitectures
https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures
Exe name Compile flags Arch name Exe file name Compile flags Arch name
cpuminer-sse2.exe "-msse2" Core2, Nehalem cpuminer-sse2.exe "-msse2" Core2, Nehalem
cpuminer-aes-sse42.exe "-march=westmere" Westmere cpuminer-aes-sse42.exe "-march=westmere" Westmere
cpuminer-avx.exe "-march=corei7-avx" Sandybridge cpuminer-avx.exe "-march=corei7-avx" Sandybridge, Ivybridge
cpuminer-avx2.exe "-march=core-avx2 -maes" Haswell, Skylake, Coffeelake cpuminer-avx2.exe "-march=core-avx2 -maes" Haswell*
cpuminer-avx512.exe "-march=skylake-avx512" Skylake-X, Cascadelake-X cpuminer-avx512.exe "-march=skylake-avx512" Skylake-X, Cascadelake-X
cpuminer-zen "-march=znver1" AMD Ryzen, Threadripper cpuminer-zen.exe "-march=znver1" AMD Ryzen, Threadripper
cpuminer-avx512-sha-vaes.exe "-march=icelake-client" Icelake*
* Haswell includes Broadwell, Skylake, Kabylake, Coffeelake & Cometlake.
Icelake is only available on some laptops. Mining with a laptop is not
recommended. The icelake build is included in anticipation of Intel eventually
releasing a desktop CPU with a microarchitecture newer than Skylake.
Notes about included DLL files:
Downloading DLL files from alternative sources presents an inherent
security risk if their source is unknown. All DLL files included have
been copied from the Ubuntu-20.04 instalation or compiled by me from
source code obtained from the author's official repository. The exact
procedure is documented in the build instructions for Windows:
https://github.com/JayDDee/cpuminer-opt/wiki/Compiling-from-source
If you like this software feel free to donate: If you like this software feel free to donate:

View File

@@ -44,7 +44,7 @@ Please include the following information:
1. CPU model, operating system, cpuminer-opt version (must be latest), 1. CPU model, operating system, cpuminer-opt version (must be latest),
binary file for Windows, changes to default build procedure for Linux. binary file for Windows, changes to default build procedure for Linux.
2. Exact comand line (except user and pw) and intial output showing 2. Exact command line (except user and pw) and intial output showing
the above requested info. the above requested info.
3. Additional program output showing any error messages or other 3. Additional program output showing any error messages or other
@@ -65,6 +65,294 @@ If not what makes it happen or not happen?
Change Log Change Log
---------- ----------
v3.15.0
Fugue optimized with AES, improves many sha3 algos.
Minotaur algo optimized for all architectures.
Fixed neoscrypt BUG log.
v3.14.3
#265: more mutex changes to reduce blocking with high thread count.
#267: fixed hodl algo potential memory alignment issue,
add warning when thread count is not valid for mining hodl algo.
v3.14.2
The second line of the Share Accepted log is no longer displayed,
new Xnonce log is added and other small log tweaks.
#265: Cleanup use of mutex.
v3.14.1
GBT and getwork log changes:
fixed missing TTF in New Block log,
ntime no longer byte-swapped for display in New Work log,
fixed zero effective hash rate in Periodic Report log,
deleted "Current block is..." log.
Renamed stratum "New Job" log to "New Work" to be consistent with the solo
version of the log. Added more data to both versions.
v3.14.0
Changes to solo mining:
- segwit is supported by getblocktemplate,
- longpolling is not working and is disabled,
- Periodic Report log is output,
- New Block log includes TTF estimates,
- Stratum thread no longer created when using getwork or GBT.
Fixed BUG log mining sha256d.
v3.13.1.1
Fixed Windows crash mining minotaur algo.
Fixed GCC 10 compile again.
Added -fno-common to testing to be consistent with GCC 10 default.
v3.13.1
Added minotaur algo for Ringcoin.
v3.13.0.1
Issue #262: Fixed xevan AVX2 invalid shares.
v3.13.0
Updated Windows binaries compiled with GCC 9. Included DLLs also updated.
Icelake build (cpuminer-avx512-sha-vaes.exe) now included in Windows
binaries package.
No source code changes.
v3.12.8.2
Fixed x12 AVX2 rejects.
Fixed phi AVX2 crash.
v3.12.8.1
Issue #261: Fixed yescryptr8g invalid shares.
v3.12.8
Yespower sha256 prehash made thread safe.
Rewrote diff conversion functions from scratch to be simpler and use
long double (float80) and int128 arithmetic for improved accuracy and
precision.
Some code cleanup and assorted small changes.
v3.12.7
Issue #257: fixed a file descriptor leak which caused the CPU temperature
and frequency query to report zeros after mining for a couple of hours.
Issue #253: stale share reduction for yescrypt, sonoa.
v3.12.6.1
Issue #252: Fixed SSL mining (stratum+tcps://)
Issue #254 Fixed benchmark.
Issue #253: Implemented stale share reduction for yespower, x25x, x22i, x21s,
x16*, scryptn2, more to come.
v3.12.6
Issue #246: improved stale share detection for getwork.
Improved precision of target_to_diff conversion from 4 digits to 20+.
Display hash and target debug data for all rejected shares.
A graphical representation of CPU affinity is displayed when using --threads.
Added highest and lowest accepted share to summary log.
Other small changes to logs to improve consistency and clarity.
v3.12.5
Issues #246 & #251: fixed incorrect share diff for stratum and getwork,
fixed incorrect target diff for getwork. Stats should now be correct for
getwork as well as stratum.
Issue #252: Fixed stratum+tcps not using curl ssl.
Getwork: reduce stale blocks, faster response to new work.
Added ntime to new job/work logs.
README.md now lists the parameters for yespower variations that don't have
a specific algo name.
v3.12.4.6
Issue #246: fixed getwork repeated new block logs with same height. New work
for the same block is now reported as "New work" instead of "New block".
Also added a check that work is new before generating "New work" log.
Added target diff to getwork new block log.
Changed share ratio in share result log to simple fraction, no longer %.
Added debug log to display mininginfo, use -D.
v3.12.4.5
Issue #246: better stale share detection for getwork, and enhanced logging
of stale shares for stratum & getwork.
Issue #251: fixed incorrect share difficulty and share ratio in share
result log.
Changed submit log to include share diff and block height.
Small cosmetic changes to logs.
v3.12.4.4
Issue #246: Fixed net hashrate in getwork block log,
removed duplicate getwork block log,
other small tweaks to stats logs for getwork.
Issue #248: Fixed chronic stale shares with scrypt:1048576 (scryptn2).
v3.12.4.3
Fixed segfault in new block log for getwork.
Disabled silent discarding of stale work after the submit is logged.
v3.12.4.2
Issue #245: fixed getwork stale shares, solo mining with getwork now works.
Issue #246: implemented block and summary logs for getwork.
v3.12.4.1
Issue #245: fix scantime when mining solo with getwork.
Added debug logs for creation of stratum and longpoll threads, use -D to
enable.
v3.12.4
Issue #244: Change longpoll to ignore job id.
Lyra2rev2 AVX2 +3%, AVX512 +6%.
v3.12.3.1
Issue #241: Fixed regression that broke coinbase address in v3.11.7.
v3.12.3
Issue #238: Fixed skunk AVX2.
Issue #239: Faster AVX2 & AVX512 for skein +44%, skein2 +30%, plus marginal
increases for skunk, x16r, x16rv2, x16rt, x16rt-veil, x16s, x21s.
Faster anime VAES +57%, AVX512 +21%, AVX2 +3%.
Redesigned code reponsible for #236.
v3.12.2
Fixed xevan, skein, skein2 AVX2, #238.
Reversed polarity of AVX2 vector bit test utilities, and all users, to be
logically and semantically correct. Follow up to issue #236.
v3.12.1
Fixed anime AVX2 low difficulty shares, git issue #236.
Periodic summary now reports lost hash rate due to rejected and stale shares,
displayed only when non-zero.
v3.12.0.1
Fixed hodl rejects, git issue #237.
Fixed debug code added in v3.12.0 to work with AVX2 to be enabled only
after low difficulty share have been seen to avoid unnecessarily excessive
log outout.
Added more digits of precision to diff in log output to help diagnose
low difficulty shares.
v3.12.0
Faster phi2 AVX2 +62%, AVX512 +150% on Intel CPUs. AMD Ryzen AVX2 is
YMMV due to its inferiour AVX2 implementation.
Fixed Hodl stats, rejects are still an issue since v3.9.5, git issue #237.
API can now be enabled with "-b port" or "--api-bind port".
It will use the default address 127.0.0.1.
Editorial: Short form options should only be used on the command line to save
typing. Configuration files and scripts should always use the long form
"--api-bind addr:port" without relying on any defaults. This is a general
recommendation that applies to all options for any application.
Removed obsolete cryptonight, all variants, and supporting code for more
size reduction and faster compiling.
Tweaked the timing of the CPU temperature and frequency log (Linux only).
Added some debug code to collect more info aboout low difficulty rejects,
git issue #236.
v3.11.9
Fixed x16r invalid shares when Luffa was first in hash order.
API is disabled by default.
New startup message for status of stratum connection, API & extranonce.
New log report for CPU temperature, frequency of fastest and slowest cores.
Compile time is a little shorter and binary file size a little smaller
using conditional compilation..
Removed code for Bastion, Drop, Heavy, Luffa an Pluck algos and other unused
code.
v3.11.8
Fixed network hashrate showing incorrect data, should be close now.
Fixed compile errors when using GCC 10 with default flag -fno-common.
Faster x16r, x16rv2, x16rt, x16s, x21s, veil, hex with midstate prehash.
Decoupled sapling usage from block version 5 in yescryptr8g.
More detailed data reporting for low difficulty rejected shares.
v3.11.7
Added yescryptr8g algo for KOTO, including support for block version 5.
Added sha3d algo for BSHA3.
Removed memcmp and clean_job checks from get_new_work, now only check job_id.
Small improvement to sha512 and sha256 parallel implementations that don't
use SHA.
v3.11.6 v3.11.6
Fixed CPU temperature regression from v3.11.5. Fixed CPU temperature regression from v3.11.5.

193
aclocal.m4 vendored
View File

@@ -1,6 +1,6 @@
# generated automatically by aclocal 1.15.1 -*- Autoconf -*- # generated automatically by aclocal 1.16.1 -*- Autoconf -*-
# Copyright (C) 1996-2017 Free Software Foundation, Inc. # Copyright (C) 1996-2018 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -20,7 +20,7 @@ You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely. If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])]) To do so, use the procedure documented by the package, typically 'autoreconf'.])])
# Copyright (C) 2002-2017 Free Software Foundation, Inc. # Copyright (C) 2002-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -32,10 +32,10 @@ To do so, use the procedure documented by the package, typically 'autoreconf'.])
# generated from the m4 files accompanying Automake X.Y. # generated from the m4 files accompanying Automake X.Y.
# (This private macro should not be called outside this file.) # (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION], AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.15' [am__api_version='1.16'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro. dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.15.1], [], m4_if([$1], [1.16.1], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
]) ])
@@ -51,14 +51,14 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.15.1])dnl [AM_AUTOMAKE_VERSION([1.16.1])dnl
m4_ifndef([AC_AUTOCONF_VERSION], m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# Figure out how to run the assembler. -*- Autoconf -*- # Figure out how to run the assembler. -*- Autoconf -*-
# Copyright (C) 2001-2017 Free Software Foundation, Inc. # Copyright (C) 2001-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -78,7 +78,7 @@ _AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES([CCAS])])dnl
# AM_AUX_DIR_EXPAND -*- Autoconf -*- # AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001-2017 Free Software Foundation, Inc. # Copyright (C) 2001-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -130,7 +130,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
# AM_CONDITIONAL -*- Autoconf -*- # AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997-2017 Free Software Foundation, Inc. # Copyright (C) 1997-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -161,7 +161,7 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]]) Usually this means the macro was only invoked conditionally.]])
fi])]) fi])])
# Copyright (C) 1999-2017 Free Software Foundation, Inc. # Copyright (C) 1999-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -352,13 +352,12 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
# Generate code to set up dependency tracking. -*- Autoconf -*- # Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright (C) 1999-2017 Free Software Foundation, Inc. # Copyright (C) 1999-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved. # with or without modifications, as long as this notice is preserved.
# _AM_OUTPUT_DEPENDENCY_COMMANDS # _AM_OUTPUT_DEPENDENCY_COMMANDS
# ------------------------------ # ------------------------------
AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
@@ -366,49 +365,41 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
# Older Autoconf quotes --file arguments for eval, but not when files # Older Autoconf quotes --file arguments for eval, but not when files
# are listed without --file. Let's play safe and only enable the eval # are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting. # if we detect the quoting.
case $CONFIG_FILES in # TODO: see whether this extra hack can be removed once we start
*\'*) eval set x "$CONFIG_FILES" ;; # requiring Autoconf 2.70 or later.
*) set x $CONFIG_FILES ;; AS_CASE([$CONFIG_FILES],
esac [*\'*], [eval set x "$CONFIG_FILES"],
[*], [set x $CONFIG_FILES])
shift shift
for mf # Used to flag and report bootstrapping failures.
am_rc=0
for am_mf
do do
# Strip MF so we end up with the name of the file. # Strip MF so we end up with the name of the file.
mf=`echo "$mf" | sed -e 's/:.*$//'` am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile or not. # Check whether this is an Automake generated Makefile which includes
# We used to match only the files named 'Makefile.in', but # dependency-tracking related rules and includes.
# some people rename them; so instead we look at the file content. # Grep'ing the whole file directly is not great: AIX grep has a line
# Grep'ing the first line is not enough: some people post-process
# each Makefile.in and add a new line on top of each file to say so.
# Grep'ing the whole file is not good either: AIX grep has a line
# limit of 2048, but all sed's we know have understand at least 4000. # limit of 2048, but all sed's we know have understand at least 4000.
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
dirpart=`AS_DIRNAME("$mf")` || continue
else am_dirpart=`AS_DIRNAME(["$am_mf"])`
continue am_filepart=`AS_BASENAME(["$am_mf"])`
fi AM_RUN_LOG([cd "$am_dirpart" \
# Extract the definition of DEPDIR, am__include, and am__quote && sed -e '/# am--include-marker/d' "$am_filepart" \
# from the Makefile without running 'make'. | $MAKE -f - am--depfiles]) || am_rc=$?
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
test -z "$DEPDIR" && continue
am__include=`sed -n 's/^am__include = //p' < "$mf"`
test -z "$am__include" && continue
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
# Find all dependency output files, they are included files with
# $(DEPDIR) in their names. We invoke sed twice because it is the
# simplest approach to changing $(DEPDIR) to its actual value in the
# expansion.
for file in `sed -n "
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
# Make sure the directory exists.
test -f "$dirpart/$file" && continue
fdir=`AS_DIRNAME(["$file"])`
AS_MKDIR_P([$dirpart/$fdir])
# echo "creating $dirpart/$file"
echo '# dummy' > "$dirpart/$file"
done
done done
if test $am_rc -ne 0; then
AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
for automatic dependency tracking. Try re-running configure with the
'--disable-dependency-tracking' option to at least be able to build
the package (albeit without support for automatic dependency tracking).])
fi
AS_UNSET([am_dirpart])
AS_UNSET([am_filepart])
AS_UNSET([am_mf])
AS_UNSET([am_rc])
rm -f conftest-deps.mk
} }
])# _AM_OUTPUT_DEPENDENCY_COMMANDS ])# _AM_OUTPUT_DEPENDENCY_COMMANDS
@@ -417,18 +408,17 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
# ----------------------------- # -----------------------------
# This macro should only be invoked once -- use via AC_REQUIRE. # This macro should only be invoked once -- use via AC_REQUIRE.
# #
# This code is only required when automatic dependency tracking # This code is only required when automatic dependency tracking is enabled.
# is enabled. FIXME. This creates each '.P' file that we will # This creates each '.Po' and '.Plo' makefile fragment that we'll need in
# need in order to bootstrap the dependency handling code. # order to bootstrap the dependency handling code.
AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
[AC_CONFIG_COMMANDS([depfiles], [AC_CONFIG_COMMANDS([depfiles],
[test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
[AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])])
])
# Do all the work for Automake. -*- Autoconf -*- # Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996-2017 Free Software Foundation, Inc. # Copyright (C) 1996-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -515,8 +505,8 @@ AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
AC_REQUIRE([AC_PROG_MKDIR_P])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl
# For better backward compatibility. To be removed once Automake 1.9.x # For better backward compatibility. To be removed once Automake 1.9.x
# dies out for good. For more background, see: # dies out for good. For more background, see:
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> # <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> # <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
AC_SUBST([mkdir_p], ['$(MKDIR_P)']) AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
# We need awk for the "check" target (and possibly the TAP driver). The # We need awk for the "check" target (and possibly the TAP driver). The
# system "awk" is bad on some platforms. # system "awk" is bad on some platforms.
@@ -583,7 +573,7 @@ END
Aborting the configuration process, to ensure you take notice of the issue. Aborting the configuration process, to ensure you take notice of the issue.
You can download and install GNU coreutils to get an 'rm' implementation You can download and install GNU coreutils to get an 'rm' implementation
that behaves properly: <http://www.gnu.org/software/coreutils/>. that behaves properly: <https://www.gnu.org/software/coreutils/>.
If you want to complete the configuration process using your problematic If you want to complete the configuration process using your problematic
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
@@ -625,7 +615,7 @@ for _am_header in $config_headers :; do
done done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001-2017 Free Software Foundation, Inc. # Copyright (C) 2001-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -646,7 +636,7 @@ if test x"${install_sh+set}" != xset; then
fi fi
AC_SUBST([install_sh])]) AC_SUBST([install_sh])])
# Copyright (C) 2003-2017 Free Software Foundation, Inc. # Copyright (C) 2003-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -668,7 +658,7 @@ AC_SUBST([am__leading_dot])])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering # From Jim Meyering
# Copyright (C) 1996-2017 Free Software Foundation, Inc. # Copyright (C) 1996-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -703,7 +693,7 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
# Check to see how 'make' treats includes. -*- Autoconf -*- # Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001-2017 Free Software Foundation, Inc. # Copyright (C) 2001-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -711,49 +701,42 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
# AM_MAKE_INCLUDE() # AM_MAKE_INCLUDE()
# ----------------- # -----------------
# Check to see how make treats includes. # Check whether make has an 'include' directive that can support all
# the idioms we need for our automatic dependency tracking code.
AC_DEFUN([AM_MAKE_INCLUDE], AC_DEFUN([AM_MAKE_INCLUDE],
[am_make=${MAKE-make} [AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive])
cat > confinc << 'END' cat > confinc.mk << 'END'
am__doit: am__doit:
@echo this is the am__doit target @echo this is the am__doit target >confinc.out
.PHONY: am__doit .PHONY: am__doit
END END
# If we don't find an include directive, just comment out the code.
AC_MSG_CHECKING([for style of include used by $am_make])
am__include="#" am__include="#"
am__quote= am__quote=
_am_result=none # BSD make does it like this.
# First try GNU make style include. echo '.include "confinc.mk" # ignored' > confmf.BSD
echo "include confinc" > confmf # Other make implementations (GNU, Solaris 10, AIX) do it like this.
# Ignore all kinds of additional output from 'make'. echo 'include confinc.mk # ignored' > confmf.GNU
case `$am_make -s -f confmf 2> /dev/null` in #( _am_result=no
*the\ am__doit\ target*) for s in GNU BSD; do
am__include=include AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out])
am__quote= AS_CASE([$?:`cat confinc.out 2>/dev/null`],
_am_result=GNU ['0:this is the am__doit target'],
;; [AS_CASE([$s],
esac [BSD], [am__include='.include' am__quote='"'],
# Now try BSD make style include. [am__include='include' am__quote=''])])
if test "$am__include" = "#"; then if test "$am__include" != "#"; then
echo '.include "confinc"' > confmf _am_result="yes ($s style)"
case `$am_make -s -f confmf 2> /dev/null` in #( break
*the\ am__doit\ target*) fi
am__include=.include done
am__quote="\"" rm -f confinc.* confmf.*
_am_result=BSD AC_MSG_RESULT([${_am_result}])
;; AC_SUBST([am__include])])
esac AC_SUBST([am__quote])])
fi
AC_SUBST([am__include])
AC_SUBST([am__quote])
AC_MSG_RESULT([$_am_result])
rm -f confinc confmf
])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# Copyright (C) 1997-2017 Free Software Foundation, Inc. # Copyright (C) 1997-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -792,7 +775,7 @@ fi
# Helper functions for option handling. -*- Autoconf -*- # Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001-2017 Free Software Foundation, Inc. # Copyright (C) 2001-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -821,7 +804,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
AC_DEFUN([_AM_IF_OPTION], AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Copyright (C) 1999-2017 Free Software Foundation, Inc. # Copyright (C) 1999-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -868,7 +851,7 @@ AC_LANG_POP([C])])
# For backward compatibility. # For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
# Copyright (C) 2001-2017 Free Software Foundation, Inc. # Copyright (C) 2001-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -887,7 +870,7 @@ AC_DEFUN([AM_RUN_LOG],
# Check to make sure that the build environment is sane. -*- Autoconf -*- # Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996-2017 Free Software Foundation, Inc. # Copyright (C) 1996-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -968,7 +951,7 @@ AC_CONFIG_COMMANDS_PRE(
rm -f conftest.file rm -f conftest.file
]) ])
# Copyright (C) 2009-2017 Free Software Foundation, Inc. # Copyright (C) 2009-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -1028,7 +1011,7 @@ AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
]) ])
# Copyright (C) 2001-2017 Free Software Foundation, Inc. # Copyright (C) 2001-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -1056,7 +1039,7 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])]) AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006-2017 Free Software Foundation, Inc. # Copyright (C) 2006-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@@ -1075,7 +1058,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*- # Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004-2017 Free Software Foundation, Inc. # Copyright (C) 2004-2018 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,

View File

@@ -90,34 +90,172 @@ void algo_not_implemented()
} }
// default null functions // default null functions
// deprecated, use generic as default
int null_scanhash() int null_scanhash()
{ {
applog(LOG_WARNING,"SWERR: undefined scanhash function in algo_gate"); applog(LOG_WARNING,"SWERR: undefined scanhash function in algo_gate");
return 0; return 0;
} }
void null_hash() // Default generic scanhash can be used in many cases.
int scanhash_generic( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr )
{
uint32_t edata[20] __attribute__((aligned(64)));
uint32_t hash[8] __attribute__((aligned(64)));
uint32_t *pdata = work->data;
uint32_t *ptarget = work->target;
const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 1;
uint32_t n = first_nonce;
const int thr_id = mythr->id;
const bool bench = opt_benchmark;
mm128_bswap32_80( edata, pdata );
do
{
edata[19] = n;
if ( likely( algo_gate.hash( hash, edata, thr_id ) ) )
if ( unlikely( valid_hash( hash, ptarget ) && !bench ) )
{
pdata[19] = bswap_32( n );
submit_solution( work, hash, mythr );
}
n++;
} while ( n < last_nonce && !work_restart[thr_id].restart );
*hashes_done = n - first_nonce;
pdata[19] = n;
return 0;
}
#if defined(__AVX2__)
//int scanhash_4way_64_64( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr )
//int scanhash_4way_64_640( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr )
int scanhash_4way_64in_32out( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr )
{
uint32_t hash32[8*4] __attribute__ ((aligned (64)));
uint32_t vdata[20*4] __attribute__ ((aligned (64)));
uint32_t lane_hash[8] __attribute__ ((aligned (64)));
uint32_t *hash32_d7 = &(hash32[ 7*4 ]);
uint32_t *pdata = work->data;
const uint32_t *ptarget = work->target;
const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 4;
__m256i *noncev = (__m256i*)vdata + 9;
uint32_t n = first_nonce;
const int thr_id = mythr->id;
const uint32_t targ32_d7 = ptarget[7];
const bool bench = opt_benchmark;
mm256_bswap32_intrlv80_4x64( vdata, pdata );
*noncev = mm256_intrlv_blend_32(
_mm256_set_epi32( n+3, 0, n+2, 0, n+1, 0, n, 0 ), *noncev );
do
{
if ( likely( algo_gate.hash( hash32, vdata, thr_id ) ) )
for ( int lane = 0; lane < 4; lane++ )
if ( unlikely( hash32_d7[ lane ] <= targ32_d7 && !bench ) )
{
extr_lane_4x32( lane_hash, hash32, lane, 256 );
if ( valid_hash( lane_hash, ptarget ) )
{
pdata[19] = bswap_32( n + lane );
submit_solution( work, lane_hash, mythr );
}
}
*noncev = _mm256_add_epi32( *noncev,
m256_const1_64( 0x0000000400000000 ) );
n += 4;
} while ( likely( ( n <= last_nonce ) && !work_restart[thr_id].restart ) );
pdata[19] = n;
*hashes_done = n - first_nonce;
return 0;
}
//int scanhash_8way_32_32( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr )
#endif
#if defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512DQ__) && defined(__AVX512BW__)
//int scanhash_8way_64_64( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr )
//int scanhash_8way_64_640( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr )
int scanhash_8way_64in_32out( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr )
{
uint32_t hash32[8*8] __attribute__ ((aligned (128)));
uint32_t vdata[20*8] __attribute__ ((aligned (64)));
uint32_t lane_hash[8] __attribute__ ((aligned (64)));
uint32_t *hash32_d7 = &(hash32[7*8]);
uint32_t *pdata = work->data;
const uint32_t *ptarget = work->target;
const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 8;
__m512i *noncev = (__m512i*)vdata + 9;
uint32_t n = first_nonce;
const int thr_id = mythr->id;
const uint32_t targ32_d7 = ptarget[7];
const bool bench = opt_benchmark;
mm512_bswap32_intrlv80_8x64( vdata, pdata );
*noncev = mm512_intrlv_blend_32(
_mm512_set_epi32( n+7, 0, n+6, 0, n+5, 0, n+4, 0,
n+3, 0, n+2, 0, n+1, 0, n, 0 ), *noncev );
do
{
if ( likely( algo_gate.hash( hash32, vdata, thr_id ) ) )
for ( int lane = 0; lane < 8; lane++ )
if ( unlikely( ( hash32_d7[ lane ] <= targ32_d7 ) && !bench ) )
{
extr_lane_8x32( lane_hash, hash32, lane, 256 );
if ( likely( valid_hash( lane_hash, ptarget ) ) )
{
pdata[19] = bswap_32( n + lane );
submit_solution( work, lane_hash, mythr );
}
}
*noncev = _mm512_add_epi32( *noncev,
m512_const1_64( 0x0000000800000000 ) );
n += 8;
} while ( likely( ( n < last_nonce ) && !work_restart[thr_id].restart ) );
pdata[19] = n;
*hashes_done = n - first_nonce;
return 0;
}
//int scanhash_16way_32_32( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr )
#endif
int null_hash()
{ {
applog(LOG_WARNING,"SWERR: null_hash unsafe null function"); applog(LOG_WARNING,"SWERR: null_hash unsafe null function");
}; return 0;
void null_hash_suw()
{
applog(LOG_WARNING,"SWERR: null_hash_suw unsafe null function");
}; };
void init_algo_gate( algo_gate_t* gate ) void init_algo_gate( algo_gate_t* gate )
{ {
gate->miner_thread_init = (void*)&return_true; gate->miner_thread_init = (void*)&return_true;
gate->scanhash = (void*)&null_scanhash; gate->scanhash = (void*)&scanhash_generic;
gate->hash = (void*)&null_hash; gate->hash = (void*)&null_hash;
gate->hash_suw = (void*)&null_hash_suw;
gate->get_new_work = (void*)&std_get_new_work; gate->get_new_work = (void*)&std_get_new_work;
gate->get_nonceptr = (void*)&std_get_nonceptr;
gate->work_decode = (void*)&std_le_work_decode; gate->work_decode = (void*)&std_le_work_decode;
gate->decode_extra_data = (void*)&do_nothing; gate->decode_extra_data = (void*)&do_nothing;
gate->gen_merkle_root = (void*)&sha256d_gen_merkle_root; gate->gen_merkle_root = (void*)&sha256d_gen_merkle_root;
gate->stratum_gen_work = (void*)&std_stratum_gen_work;
gate->build_stratum_request = (void*)&std_le_build_stratum_request; gate->build_stratum_request = (void*)&std_le_build_stratum_request;
gate->malloc_txs_request = (void*)&std_malloc_txs_request; gate->malloc_txs_request = (void*)&std_malloc_txs_request;
gate->submit_getwork_result = (void*)&std_le_submit_getwork_result; gate->submit_getwork_result = (void*)&std_le_submit_getwork_result;
@@ -129,7 +267,6 @@ void init_algo_gate( algo_gate_t* gate )
gate->resync_threads = (void*)&do_nothing; gate->resync_threads = (void*)&do_nothing;
gate->do_this_thread = (void*)&return_true; gate->do_this_thread = (void*)&return_true;
gate->longpoll_rpc_call = (void*)&std_longpoll_rpc_call; gate->longpoll_rpc_call = (void*)&std_longpoll_rpc_call;
gate->stratum_handle_response = (void*)&std_stratum_handle_response;
gate->get_work_data_size = (void*)&std_get_work_data_size; gate->get_work_data_size = (void*)&std_get_work_data_size;
gate->optimizations = EMPTY_SET; gate->optimizations = EMPTY_SET;
gate->ntime_index = STD_NTIME_INDEX; gate->ntime_index = STD_NTIME_INDEX;
@@ -162,23 +299,16 @@ bool register_algo_gate( int algo, algo_gate_t *gate )
case ALGO_ARGON2D500: register_argon2d_dyn_algo ( gate ); break; case ALGO_ARGON2D500: register_argon2d_dyn_algo ( gate ); break;
case ALGO_ARGON2D4096: register_argon2d4096_algo ( gate ); break; case ALGO_ARGON2D4096: register_argon2d4096_algo ( gate ); break;
case ALGO_AXIOM: register_axiom_algo ( gate ); break; case ALGO_AXIOM: register_axiom_algo ( gate ); break;
case ALGO_BASTION: register_bastion_algo ( gate ); break;
case ALGO_BLAKE: register_blake_algo ( gate ); break; case ALGO_BLAKE: register_blake_algo ( gate ); break;
case ALGO_BLAKE2B: register_blake2b_algo ( gate ); break; case ALGO_BLAKE2B: register_blake2b_algo ( gate ); break;
case ALGO_BLAKE2S: register_blake2s_algo ( gate ); break; case ALGO_BLAKE2S: register_blake2s_algo ( gate ); break;
case ALGO_BLAKECOIN: register_blakecoin_algo ( gate ); break; case ALGO_BLAKECOIN: register_blakecoin_algo ( gate ); break;
case ALGO_BMW512: register_bmw512_algo ( gate ); break; case ALGO_BMW512: register_bmw512_algo ( gate ); break;
case ALGO_C11: register_c11_algo ( gate ); break; case ALGO_C11: register_c11_algo ( gate ); break;
case ALGO_CRYPTOLIGHT: register_cryptolight_algo ( gate ); break;
case ALGO_CRYPTONIGHT: register_cryptonight_algo ( gate ); break;
case ALGO_CRYPTONIGHTV7: register_cryptonightv7_algo ( gate ); break;
case ALGO_DECRED: register_decred_algo ( gate ); break; case ALGO_DECRED: register_decred_algo ( gate ); break;
case ALGO_DEEP: register_deep_algo ( gate ); break; case ALGO_DEEP: register_deep_algo ( gate ); break;
case ALGO_DMD_GR: register_dmd_gr_algo ( gate ); break; case ALGO_DMD_GR: register_dmd_gr_algo ( gate ); break;
case ALGO_DROP: register_drop_algo ( gate ); break;
case ALGO_FRESH: register_fresh_algo ( gate ); break;
case ALGO_GROESTL: register_groestl_algo ( gate ); break; case ALGO_GROESTL: register_groestl_algo ( gate ); break;
case ALGO_HEAVY: register_heavy_algo ( gate ); break;
case ALGO_HEX: register_hex_algo ( gate ); break; case ALGO_HEX: register_hex_algo ( gate ); break;
case ALGO_HMQ1725: register_hmq1725_algo ( gate ); break; case ALGO_HMQ1725: register_hmq1725_algo ( gate ); break;
case ALGO_HODL: register_hodl_algo ( gate ); break; case ALGO_HODL: register_hodl_algo ( gate ); break;
@@ -186,7 +316,6 @@ bool register_algo_gate( int algo, algo_gate_t *gate )
case ALGO_KECCAK: register_keccak_algo ( gate ); break; case ALGO_KECCAK: register_keccak_algo ( gate ); break;
case ALGO_KECCAKC: register_keccakc_algo ( gate ); break; case ALGO_KECCAKC: register_keccakc_algo ( gate ); break;
case ALGO_LBRY: register_lbry_algo ( gate ); break; case ALGO_LBRY: register_lbry_algo ( gate ); break;
case ALGO_LUFFA: register_luffa_algo ( gate ); break;
case ALGO_LYRA2H: register_lyra2h_algo ( gate ); break; case ALGO_LYRA2H: register_lyra2h_algo ( gate ); break;
case ALGO_LYRA2RE: register_lyra2re_algo ( gate ); break; case ALGO_LYRA2RE: register_lyra2re_algo ( gate ); break;
case ALGO_LYRA2REV2: register_lyra2rev2_algo ( gate ); break; case ALGO_LYRA2REV2: register_lyra2rev2_algo ( gate ); break;
@@ -194,13 +323,13 @@ bool register_algo_gate( int algo, algo_gate_t *gate )
case ALGO_LYRA2Z: register_lyra2z_algo ( gate ); break; case ALGO_LYRA2Z: register_lyra2z_algo ( gate ); break;
case ALGO_LYRA2Z330: register_lyra2z330_algo ( gate ); break; case ALGO_LYRA2Z330: register_lyra2z330_algo ( gate ); break;
case ALGO_M7M: register_m7m_algo ( gate ); break; case ALGO_M7M: register_m7m_algo ( gate ); break;
case ALGO_MINOTAUR: register_minotaur_algo ( gate ); break;
case ALGO_MYR_GR: register_myriad_algo ( gate ); break; case ALGO_MYR_GR: register_myriad_algo ( gate ); break;
case ALGO_NEOSCRYPT: register_neoscrypt_algo ( gate ); break; case ALGO_NEOSCRYPT: register_neoscrypt_algo ( gate ); break;
case ALGO_NIST5: register_nist5_algo ( gate ); break; case ALGO_NIST5: register_nist5_algo ( gate ); break;
case ALGO_PENTABLAKE: register_pentablake_algo ( gate ); break; case ALGO_PENTABLAKE: register_pentablake_algo ( gate ); break;
case ALGO_PHI1612: register_phi1612_algo ( gate ); break; case ALGO_PHI1612: register_phi1612_algo ( gate ); break;
case ALGO_PHI2: register_phi2_algo ( gate ); break; case ALGO_PHI2: register_phi2_algo ( gate ); break;
case ALGO_PLUCK: register_pluck_algo ( gate ); break;
case ALGO_POLYTIMOS: register_polytimos_algo ( gate ); break; case ALGO_POLYTIMOS: register_polytimos_algo ( gate ); break;
case ALGO_POWER2B: register_power2b_algo ( gate ); break; case ALGO_POWER2B: register_power2b_algo ( gate ); break;
case ALGO_QUARK: register_quark_algo ( gate ); break; case ALGO_QUARK: register_quark_algo ( gate ); break;
@@ -209,6 +338,7 @@ bool register_algo_gate( int algo, algo_gate_t *gate )
case ALGO_SHA256D: register_sha256d_algo ( gate ); break; case ALGO_SHA256D: register_sha256d_algo ( gate ); break;
case ALGO_SHA256Q: register_sha256q_algo ( gate ); break; case ALGO_SHA256Q: register_sha256q_algo ( gate ); break;
case ALGO_SHA256T: register_sha256t_algo ( gate ); break; case ALGO_SHA256T: register_sha256t_algo ( gate ); break;
case ALGO_SHA3D: register_sha3d_algo ( gate ); break;
case ALGO_SHAVITE3: register_shavite_algo ( gate ); break; case ALGO_SHAVITE3: register_shavite_algo ( gate ); break;
case ALGO_SKEIN: register_skein_algo ( gate ); break; case ALGO_SKEIN: register_skein_algo ( gate ); break;
case ALGO_SKEIN2: register_skein2_algo ( gate ); break; case ALGO_SKEIN2: register_skein2_algo ( gate ); break;
@@ -240,13 +370,9 @@ bool register_algo_gate( int algo, algo_gate_t *gate )
case ALGO_X22I: register_x22i_algo ( gate ); break; case ALGO_X22I: register_x22i_algo ( gate ); break;
case ALGO_X25X: register_x25x_algo ( gate ); break; case ALGO_X25X: register_x25x_algo ( gate ); break;
case ALGO_XEVAN: register_xevan_algo ( gate ); break; case ALGO_XEVAN: register_xevan_algo ( gate ); break;
/* case ALGO_YESCRYPT: register_yescrypt_05_algo ( gate ); break;
case ALGO_YESCRYPTR8: register_yescryptr8_05_algo ( gate ); break;
case ALGO_YESCRYPTR16: register_yescryptr16_05_algo ( gate ); break;
case ALGO_YESCRYPTR32: register_yescryptr32_05_algo ( gate ); break;
*/
case ALGO_YESCRYPT: register_yescrypt_algo ( gate ); break; case ALGO_YESCRYPT: register_yescrypt_algo ( gate ); break;
case ALGO_YESCRYPTR8: register_yescryptr8_algo ( gate ); break; case ALGO_YESCRYPTR8: register_yescryptr8_algo ( gate ); break;
case ALGO_YESCRYPTR8G: register_yescryptr8g_algo ( gate ); break;
case ALGO_YESCRYPTR16: register_yescryptr16_algo ( gate ); break; case ALGO_YESCRYPTR16: register_yescryptr16_algo ( gate ); break;
case ALGO_YESCRYPTR32: register_yescryptr32_algo ( gate ); break; case ALGO_YESCRYPTR32: register_yescryptr32_algo ( gate ); break;
case ALGO_YESPOWER: register_yespower_algo ( gate ); break; case ALGO_YESPOWER: register_yespower_algo ( gate ); break;
@@ -270,30 +396,6 @@ bool register_algo_gate( int algo, algo_gate_t *gate )
// restore warnings // restore warnings
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
// override std defaults with jr2 defaults
bool register_json_rpc2( algo_gate_t *gate )
{
applog(LOG_WARNING,"\nCryptonight algorithm and variants are no longer");
applog(LOG_WARNING,"supported by cpuminer-opt. Shares submitted will");
applog(LOG_WARNING,"likely be rejected. Proceed at your own risk.\n");
// gate->wait_for_diff = (void*)&do_nothing;
gate->get_new_work = (void*)&jr2_get_new_work;
gate->get_nonceptr = (void*)&jr2_get_nonceptr;
gate->stratum_gen_work = (void*)&jr2_stratum_gen_work;
gate->build_stratum_request = (void*)&jr2_build_stratum_request;
gate->submit_getwork_result = (void*)&jr2_submit_getwork_result;
gate->longpoll_rpc_call = (void*)&jr2_longpoll_rpc_call;
gate->work_decode = (void*)&jr2_work_decode;
gate->stratum_handle_response = (void*)&jr2_stratum_handle_response;
gate->nonce_index = JR2_NONCE_INDEX;
jsonrpc_2 = true; // still needed
opt_extranonce = false;
// have_gbt = false;
return true;
}
// run the alternate hash function for a specific algo
void exec_hash_function( int algo, void *output, const void *pdata ) void exec_hash_function( int algo, void *output, const void *pdata )
{ {
algo_gate_t gate; algo_gate_t gate;
@@ -313,39 +415,37 @@ void exec_hash_function( int algo, void *output, const void *pdata )
const char* const algo_alias_map[][2] = const char* const algo_alias_map[][2] =
{ {
// alias proper // alias proper
{ "argon2d-crds", "argon2d250" }, { "argon2d-crds", "argon2d250" },
{ "argon2d-dyn", "argon2d500" }, { "argon2d-dyn", "argon2d500" },
{ "argon2d-uis", "argon2d4096" }, { "argon2d-uis", "argon2d4096" },
{ "bcd", "x13bcd" }, { "bcd", "x13bcd" },
{ "bitcore", "timetravel10" }, { "bitcore", "timetravel10" },
{ "bitzeny", "yescryptr8" }, { "bitzeny", "yescryptr8" },
{ "blake256r8", "blakecoin" }, { "blake256r8", "blakecoin" },
{ "blake256r8vnl", "vanilla" }, { "blake256r8vnl", "vanilla" },
{ "blake256r14", "blake" }, { "blake256r14", "blake" },
{ "blake256r14dcr", "decred" }, { "blake256r14dcr", "decred" },
{ "cryptonote", "cryptonight" }, { "diamond", "dmd-gr" },
{ "cryptonight-light", "cryptolight" }, { "espers", "hmq1725" },
{ "diamond", "dmd-gr" }, { "flax", "c11" },
{ "droplp", "drop" }, { "hsr", "x13sm3" },
{ "espers", "hmq1725" }, { "jackpot", "jha" },
{ "flax", "c11" }, { "jane", "scryptjane" },
{ "hsr", "x13sm3" }, { "lyra2", "lyra2re" },
{ "jackpot", "jha" }, { "lyra2v2", "lyra2rev2" },
{ "jane", "scryptjane" }, { "lyra2v3", "lyra2rev3" },
{ "lyra2", "lyra2re" }, { "myrgr", "myr-gr" },
{ "lyra2v2", "lyra2rev2" }, { "myriad", "myr-gr" },
{ "lyra2v3", "lyra2rev3" }, { "neo", "neoscrypt" },
{ "myrgr", "myr-gr" }, { "phi", "phi1612" },
{ "myriad", "myr-gr" }, { "scryptn2", "scrypt:1048576" },
{ "neo", "neoscrypt" }, { "sib", "x11gost" },
{ "phi", "phi1612" }, { "timetravel8", "timetravel" },
{ "sib", "x11gost" }, { "veil", "x16rt-veil" },
{ "timetravel8", "timetravel" }, { "x16r-hex", "hex" },
{ "veil", "x16rt-veil" }, { "yenten", "yescryptr16" },
{ "x16r-hex", "hex" }, { "ziftr", "zr5" },
{ "yenten", "yescryptr16" }, { NULL, NULL }
{ "ziftr", "zr5" },
{ NULL, NULL }
}; };
// if arg is a valid alias for a known algo it is updated with the proper // if arg is a valid alias for a known algo it is updated with the proper
@@ -358,7 +458,7 @@ void get_algo_alias( char** algo_or_alias )
if ( !strcasecmp( *algo_or_alias, algo_alias_map[i][ ALIAS ] ) ) if ( !strcasecmp( *algo_or_alias, algo_alias_map[i][ ALIAS ] ) )
{ {
// found valid alias, return proper name // found valid alias, return proper name
*algo_or_alias = (char* const)( algo_alias_map[i][ PROPER ] ); *algo_or_alias = (char*)( algo_alias_map[i][ PROPER ] );
return; return;
} }
} }

View File

@@ -75,7 +75,7 @@
// my hack at creating a set data type using bit masks. Set inclusion, // my hack at creating a set data type using bit masks. Set inclusion,
// exclusion union and intersection operations are provided for convenience. In // some cases it may be desireable to use boolean algebra directly on the // exclusion union and intersection operations are provided for convenience. In // some cases it may be desireable to use boolean algebra directly on the
// data to perfomr set operations. Sets can be represented as single // data to perform set operations. Sets can be represented as single
// elements, a bitwise OR of multiple elements, a bitwise OR of multiple // elements, a bitwise OR of multiple elements, a bitwise OR of multiple
// set variables or constants, or combinations of the above. // set variables or constants, or combinations of the above.
// Examples: // Examples:
@@ -110,65 +110,62 @@ inline bool set_excl ( set_t a, set_t b ) { return (a & b) == 0; }
typedef struct typedef struct
{ {
// mandatory functions, must be overwritten // Mandatory functions, one of these is mandatory. If a generic scanhash
// is used a custom hash function must be registered, with a custom scanhash
// the custom hash function can be called directly and doesn't need to be
// registered in the gate.
int ( *scanhash ) ( struct work*, uint32_t, uint64_t*, struct thr_info* ); int ( *scanhash ) ( struct work*, uint32_t, uint64_t*, struct thr_info* );
// optional unsafe, must be overwritten if algo uses function int ( *hash ) ( void*, const void*, int );
void ( *hash ) ( void*, const void*, uint32_t ) ;
void ( *hash_suw ) ( void*, const void* );
//optional, safe to use default in most cases //optional, safe to use default in most cases
// Allocate thread local buffers and other initialization specific to miner // Allocate thread local buffers and other initialization specific to miner
// threads. // threads.
bool ( *miner_thread_init ) ( int ); bool ( *miner_thread_init ) ( int );
// Generate global blockheader from stratum data.
void ( *stratum_gen_work ) ( struct stratum_ctx*, struct work* );
// Get thread local copy of blockheader with unique nonce. // Get thread local copy of blockheader with unique nonce.
void ( *get_new_work ) ( struct work*, struct work*, int, uint32_t*, void ( *get_new_work ) ( struct work*, struct work*, int, uint32_t* );
bool );
// Return pointer to nonce in blockheader.
uint32_t *( *get_nonceptr ) ( uint32_t* );
// Decode getwork blockheader // Decode getwork blockheader
bool ( *work_decode ) ( const json_t*, struct work* ); bool ( *work_decode ) ( struct work* );
// Extra getwork data // Extra getwork data
void ( *decode_extra_data ) ( struct work*, uint64_t* ); void ( *decode_extra_data ) ( struct work*, uint64_t* );
bool ( *submit_getwork_result ) ( CURL*, struct work* ); bool ( *submit_getwork_result ) ( CURL*, struct work* );
void ( *gen_merkle_root ) ( char*, struct stratum_ctx* ); void ( *gen_merkle_root ) ( char*, struct stratum_ctx* );
// Increment extranonce // Increment extranonce
void ( *build_extraheader ) ( struct work*, struct stratum_ctx* ); void ( *build_extraheader ) ( struct work*, struct stratum_ctx* );
void ( *build_block_header ) ( struct work*, uint32_t, uint32_t*,
uint32_t*, uint32_t, uint32_t,
unsigned char* );
void ( *build_block_header ) ( struct work*, uint32_t, uint32_t*,
uint32_t*, uint32_t, uint32_t );
// Build mining.submit message // Build mining.submit message
void ( *build_stratum_request ) ( char*, struct work*, struct stratum_ctx* ); void ( *build_stratum_request ) ( char*, struct work*, struct stratum_ctx* );
char* ( *malloc_txs_request ) ( struct work* ); char* ( *malloc_txs_request ) ( struct work* );
// Big or little // Big or little
void ( *set_work_data_endian ) ( struct work* ); void ( *set_work_data_endian ) ( struct work* );
double ( *calc_network_diff ) ( struct work* ); double ( *calc_network_diff ) ( struct work* );
// Wait for first work // Wait for first work
bool ( *ready_to_mine ) ( struct work*, struct stratum_ctx*, int ); bool ( *ready_to_mine ) ( struct work*, struct stratum_ctx*, int );
// Diverge mining threads // Diverge mining threads
bool ( *do_this_thread ) ( int ); bool ( *do_this_thread ) ( int );
// After do_this_thread // After do_this_thread
void ( *resync_threads ) ( struct work* ); void ( *resync_threads ) ( struct work* );
// No longer needed
json_t* (*longpoll_rpc_call) ( CURL*, int*, char* );
json_t* (*longpoll_rpc_call) ( CURL*, int*, char* );
bool ( *stratum_handle_response )( json_t* );
set_t optimizations; set_t optimizations;
int ( *get_work_data_size ) (); int ( *get_work_data_size ) ();
int ntime_index; int ntime_index;
@@ -206,46 +203,80 @@ void four_way_not_tested();
#define STD_WORK_DATA_SIZE 128 #define STD_WORK_DATA_SIZE 128
#define STD_WORK_CMP_SIZE 76 #define STD_WORK_CMP_SIZE 76
#define JR2_NONCE_INDEX 39 // 8 bit offset //#define JR2_NONCE_INDEX 39 // 8 bit offset
// These indexes are only used with JSON RPC2 and are not gated. // These indexes are only used with JSON RPC2 and are not gated.
#define JR2_WORK_CMP_INDEX_2 43 //#define JR2_WORK_CMP_INDEX_2 43
#define JR2_WORK_CMP_SIZE_2 33 //#define JR2_WORK_CMP_SIZE_2 33
// allways returns failure // deprecated, use generic instead
int null_scanhash(); int null_scanhash();
// Default generic, may be used in many cases.
// N-way is more complicated, requires many different implementations
// depending on architecture, input format, and output format.
// Naming convention is scanhash_[N]way_[input format]in_[output format]out
// N = number of lanes
// input/output format:
// 32: 32 bit interleaved parallel lanes
// 64: 64 bit interleaved parallel lanes
// 640: input only, not interleaved, contiguous serial 640 bit lanes.
// 256: output only, not interleaved, contiguous serial 256 bit lanes.
int scanhash_generic( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr );
#if defined(__AVX2__)
//int scanhash_4way_64in_64out( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr );
//int scanhash_4way_64in_256out( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr );
int scanhash_4way_64in_32out( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr );
//int scanhash_8way_32in_32out( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr );
#endif
#if defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512DQ__) && defined(__AVX512BW__)
//int scanhash_8way_64in_64out( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr );
//int scanhash_8way_64in_256out( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr );
int scanhash_8way_64in_32out( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr );
//int scanhash_16way_32in_32out( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr );
#endif
// displays warning // displays warning
void null_hash (); int null_hash ();
void null_hash_suw();
// optional safe targets, default listed first unless noted. // optional safe targets, default listed first unless noted.
uint32_t *std_get_nonceptr( uint32_t *work_data );
uint32_t *jr2_get_nonceptr( uint32_t *work_data );
void std_get_new_work( struct work *work, struct work *g_work, int thr_id, void std_get_new_work( struct work *work, struct work *g_work, int thr_id,
uint32_t* end_nonce_ptr, bool clean_job );
void jr2_get_new_work( struct work *work, struct work *g_work, int thr_id,
uint32_t* end_nonce_ptr ); uint32_t* end_nonce_ptr );
void std_stratum_gen_work( struct stratum_ctx *sctx, struct work *work );
void jr2_stratum_gen_work( struct stratum_ctx *sctx, struct work *work );
void sha256d_gen_merkle_root( char *merkle_root, struct stratum_ctx *sctx ); void sha256d_gen_merkle_root( char *merkle_root, struct stratum_ctx *sctx );
void SHA256_gen_merkle_root ( char *merkle_root, struct stratum_ctx *sctx ); void SHA256_gen_merkle_root ( char *merkle_root, struct stratum_ctx *sctx );
bool std_le_work_decode( const json_t *val, struct work *work ); bool std_le_work_decode( struct work *work );
bool std_be_work_decode( const json_t *val, struct work *work ); bool std_be_work_decode( struct work *work );
bool jr2_work_decode( const json_t *val, struct work *work );
bool std_le_submit_getwork_result( CURL *curl, struct work *work ); bool std_le_submit_getwork_result( CURL *curl, struct work *work );
bool std_be_submit_getwork_result( CURL *curl, struct work *work ); bool std_be_submit_getwork_result( CURL *curl, struct work *work );
bool jr2_submit_getwork_result( CURL *curl, struct work *work );
void std_le_build_stratum_request( char *req, struct work *work ); void std_le_build_stratum_request( char *req, struct work *work );
void std_be_build_stratum_request( char *req, struct work *work ); void std_be_build_stratum_request( char *req, struct work *work );
void jr2_build_stratum_request ( char *req, struct work *work );
char* std_malloc_txs_request( struct work *work ); char* std_malloc_txs_request( struct work *work );
@@ -256,15 +287,12 @@ double std_calc_network_diff( struct work *work );
void std_build_block_header( struct work* g_work, uint32_t version, void std_build_block_header( struct work* g_work, uint32_t version,
uint32_t *prevhash, uint32_t *merkle_root, uint32_t *prevhash, uint32_t *merkle_root,
uint32_t ntime, uint32_t nbits ); uint32_t ntime, uint32_t nbits,
unsigned char *final_sapling_hash );
void std_build_extraheader( struct work *work, struct stratum_ctx *sctx ); void std_build_extraheader( struct work *work, struct stratum_ctx *sctx );
json_t* std_longpoll_rpc_call( CURL *curl, int *err, char *lp_url ); json_t* std_longpoll_rpc_call( CURL *curl, int *err, char *lp_url );
json_t* jr2_longpoll_rpc_call( CURL *curl, int *err );
bool std_stratum_handle_response( json_t *val );
bool jr2_stratum_handle_response( json_t *val );
bool std_ready_to_mine( struct work* work, struct stratum_ctx* stratum, bool std_ready_to_mine( struct work* work, struct stratum_ctx* stratum,
int thr_id ); int thr_id );
@@ -277,17 +305,12 @@ int std_get_work_data_size();
// by calling the algo's register function. // by calling the algo's register function.
bool register_algo_gate( int algo, algo_gate_t *gate ); bool register_algo_gate( int algo, algo_gate_t *gate );
// Called by algos toverride any default gate functions that are applicable // Called by algos to verride any default gate functions that are applicable
// and do any other algo-specific initialization. // and do any other algo-specific initialization.
// The register functions for all the algos can be declared here to reduce // The register functions for all the algos can be declared here to reduce
// compiler warnings but that's just more work for devs adding new algos. // compiler warnings but that's just more work for devs adding new algos.
bool register_algo( algo_gate_t *gate ); bool register_algo( algo_gate_t *gate );
// Overrides a common set of functions used by RPC2 and other RPC2-specific
// init. Called by algo's register function before initializing algo-specific
// functions and data.
bool register_json_rpc2( algo_gate_t *gate );
// use this to call the hash function of an algo directly, ie util.c test. // use this to call the hash function of an algo directly, ie util.c test.
void exec_hash_function( int algo, void *output, const void *pdata ); void exec_hash_function( int algo, void *output, const void *pdata );

View File

@@ -1,4 +1,5 @@
#include "argon2d-gate.h" #include "argon2d-gate.h"
#include "simd-utils.h"
#include "argon2d/argon2.h" #include "argon2d/argon2.h"
static const size_t INPUT_BYTES = 80; // Lenth of a block header in bytes. Input Length = Salt Length (salt = input) static const size_t INPUT_BYTES = 80; // Lenth of a block header in bytes. Input Length = Salt Length (salt = input)
@@ -36,7 +37,7 @@ void argon2d_crds_hash( void *output, const void *input )
int scanhash_argon2d_crds( struct work *work, uint32_t max_nonce, int scanhash_argon2d_crds( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ) uint64_t *hashes_done, struct thr_info *mythr )
{ {
uint32_t _ALIGN(64) endiandata[20]; uint32_t _ALIGN(64) edata[20];
uint32_t _ALIGN(64) hash[8]; uint32_t _ALIGN(64) hash[8];
uint32_t *pdata = work->data; uint32_t *pdata = work->data;
uint32_t *ptarget = work->target; uint32_t *ptarget = work->target;
@@ -45,11 +46,11 @@ int scanhash_argon2d_crds( struct work *work, uint32_t max_nonce,
const uint32_t Htarg = ptarget[7]; const uint32_t Htarg = ptarget[7];
uint32_t nonce = first_nonce; uint32_t nonce = first_nonce;
swab32_array( endiandata, pdata, 20 ); swab32_array( edata, pdata, 20 );
do { do {
be32enc(&endiandata[19], nonce); be32enc(&edata[19], nonce);
argon2d_crds_hash( hash, endiandata ); argon2d_crds_hash( hash, edata );
if ( hash[7] <= Htarg && fulltest( hash, ptarget ) && !opt_benchmark ) if ( hash[7] <= Htarg && fulltest( hash, ptarget ) && !opt_benchmark )
{ {
pdata[19] = nonce; pdata[19] = nonce;
@@ -103,31 +104,32 @@ void argon2d_dyn_hash( void *output, const void *input )
int scanhash_argon2d_dyn( struct work *work, uint32_t max_nonce, int scanhash_argon2d_dyn( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ) uint64_t *hashes_done, struct thr_info *mythr )
{ {
uint32_t _ALIGN(64) endiandata[20]; uint32_t _ALIGN(64) edata[20];
uint32_t _ALIGN(64) hash[8]; uint32_t _ALIGN(64) hash[8];
uint32_t *pdata = work->data; uint32_t *pdata = work->data;
uint32_t *ptarget = work->target; uint32_t *ptarget = work->target;
int thr_id = mythr->id; // thr_id arg is deprecated const int thr_id = mythr->id;
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = (const uint32_t)pdata[19];
const uint32_t Htarg = ptarget[7]; const uint32_t last_nonce = (const uint32_t)max_nonce;
uint32_t nonce = first_nonce; uint32_t nonce = first_nonce;
const bool bench = opt_benchmark;
swab32_array( endiandata, pdata, 20 ); mm128_bswap32_80( edata, pdata );
do do
{ {
be32enc(&endiandata[19], nonce); edata[19] = nonce;
argon2d_dyn_hash( hash, endiandata ); argon2d_dyn_hash( hash, edata );
if ( hash[7] <= Htarg && fulltest( hash, ptarget ) && !opt_benchmark ) if ( unlikely( valid_hash( (uint64_t*)hash, (uint64_t*)ptarget )
&& !bench ) )
{ {
pdata[19] = nonce; pdata[19] = bswap_32( nonce );;
submit_solution( work, hash, mythr ); submit_solution( work, hash, mythr );
} }
nonce++; nonce++;
} while (nonce < max_nonce && !work_restart[thr_id].restart); } while ( likely( nonce < last_nonce && !work_restart[thr_id].restart ) );
pdata[19] = nonce; pdata[19] = nonce;
*hashes_done = pdata[19] - first_nonce + 1; *hashes_done = pdata[19] - first_nonce;
return 0; return 0;
} }
@@ -146,36 +148,34 @@ int scanhash_argon2d4096( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ) uint64_t *hashes_done, struct thr_info *mythr )
{ {
uint32_t _ALIGN(64) vhash[8]; uint32_t _ALIGN(64) vhash[8];
uint32_t _ALIGN(64) endiandata[20]; uint32_t _ALIGN(64) edata[20];
uint32_t *pdata = work->data; uint32_t *pdata = work->data;
uint32_t *ptarget = work->target; uint32_t *ptarget = work->target;
const uint32_t Htarg = ptarget[7];
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = (const uint32_t)max_nonce;
uint32_t n = first_nonce; uint32_t n = first_nonce;
int thr_id = mythr->id; // thr_id arg is deprecated const int thr_id = mythr->id; // thr_id arg is deprecated
uint32_t t_cost = 1; // 1 iteration uint32_t t_cost = 1; // 1 iteration
uint32_t m_cost = 4096; // use 4MB uint32_t m_cost = 4096; // use 4MB
uint32_t parallelism = 1; // 1 thread, 2 lanes uint32_t parallelism = 1; // 1 thread, 2 lanes
const bool bench = opt_benchmark;
for ( int i = 0; i < 19; i++ ) mm128_bswap32_80( edata, pdata );
be32enc( &endiandata[i], pdata[i] );
do { do {
be32enc( &endiandata[19], n ); edata[19] = n;
argon2d_hash_raw( t_cost, m_cost, parallelism, (char*) endiandata, 80, argon2d_hash_raw( t_cost, m_cost, parallelism, (char*) edata, 80,
(char*) endiandata, 80, (char*) vhash, 32, ARGON2_VERSION_13 ); (char*) edata, 80, (char*) vhash, 32, ARGON2_VERSION_13 );
if ( vhash[7] < Htarg && fulltest( vhash, ptarget ) && !opt_benchmark ) if ( unlikely( valid_hash( vhash, ptarget ) && !bench ) )
{ {
pdata[19] = n; be32enc( &pdata[19], n );
submit_solution( work, vhash, mythr ); submit_solution( work, vhash, mythr );
} }
n++; n++;
} while ( likely( n < last_nonce && !work_restart[thr_id].restart ) );
} while (n < max_nonce && !work_restart[thr_id].restart); *hashes_done = n - first_nonce;
*hashes_done = n - first_nonce + 1;
pdata[19] = n; pdata[19] = n;
return 0; return 0;
} }

View File

@@ -48,7 +48,7 @@ int scanhash_blake_4way( struct work *work, uint32_t max_nonce,
if ( fulltest( hash+(i<<3), ptarget ) && !opt_benchmark ) if ( fulltest( hash+(i<<3), ptarget ) && !opt_benchmark )
{ {
pdata[19] = n+i; pdata[19] = n+i;
submit_lane_solution( work, hash+(i<<3), mythr, i ); submit_solution( work, hash+(i<<3), mythr );
} }
n += 4; n += 4;
@@ -107,7 +107,7 @@ int scanhash_blake_8way( struct work *work, uint32_t max_nonce,
if ( (hash+i)[7] <= HTarget && fulltest( hash+i, ptarget ) ) if ( (hash+i)[7] <= HTarget && fulltest( hash+i, ptarget ) )
{ {
pdata[19] = n+i; pdata[19] = n+i;
submit_lane_solution( work, hash+(i<<3), mythr, i ); submit_solution( work, hash+(i<<3), mythr );
} }
n += 8; n += 8;

View File

@@ -45,7 +45,7 @@ int scanhash_blake2b_8way( struct work *work, uint32_t max_nonce,
if ( fulltest( lane_hash, ptarget ) && !opt_benchmark ) if ( fulltest( lane_hash, ptarget ) && !opt_benchmark )
{ {
pdata[19] = n + lane; pdata[19] = n + lane;
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
n += 8; n += 8;
@@ -100,7 +100,7 @@ int scanhash_blake2b_4way( struct work *work, uint32_t max_nonce,
if ( fulltest( lane_hash, ptarget ) && !opt_benchmark ) if ( fulltest( lane_hash, ptarget ) && !opt_benchmark )
{ {
pdata[19] = n + lane; pdata[19] = n + lane;
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
n += 4; n += 4;

View File

@@ -33,6 +33,8 @@
#include "blake2b-hash-4way.h" #include "blake2b-hash-4way.h"
#if defined(__AVX2__)
static const uint8_t sigma[12][16] = static const uint8_t sigma[12][16] =
{ {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
@@ -203,9 +205,9 @@ void blake2b_8way_final( blake2b_8way_ctx *ctx, void *out )
casti_m512i( out, 3 ) = ctx->h[3]; casti_m512i( out, 3 ) = ctx->h[3];
} }
#endif #endif // AVX512
#if defined(__AVX2__) // AVX2
// G Mixing function. // G Mixing function.
@@ -369,4 +371,4 @@ void blake2b_4way_final( blake2b_4way_ctx *ctx, void *out )
casti_m256i( out, 3 ) = ctx->h[3]; casti_m256i( out, 3 ) = ctx->h[3];
} }
#endif #endif // AVX2

View File

@@ -4,6 +4,9 @@
*/ */
#include "blake2b-gate.h" #include "blake2b-gate.h"
#if !defined(BLAKE2B_8WAY) && !defined(BLAKE2B_4WAY)
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include "algo/blake/sph_blake2b.h" #include "algo/blake/sph_blake2b.h"
@@ -58,3 +61,4 @@ int scanhash_blake2b( struct work *work, uint32_t max_nonce,
return 0; return 0;
} }
#endif

View File

@@ -49,7 +49,7 @@ int scanhash_blake2s_16way( struct work *work, uint32_t max_nonce,
if ( likely( fulltest( lane_hash, ptarget ) && !opt_benchmark ) ) if ( likely( fulltest( lane_hash, ptarget ) && !opt_benchmark ) )
{ {
pdata[19] = n + lane; pdata[19] = n + lane;
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
n += 16; n += 16;
@@ -104,7 +104,7 @@ int scanhash_blake2s_8way( struct work *work, uint32_t max_nonce,
if ( likely( fulltest( lane_hash, ptarget ) && !opt_benchmark ) ) if ( likely( fulltest( lane_hash, ptarget ) && !opt_benchmark ) )
{ {
pdata[19] = n + lane; pdata[19] = n + lane;
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
n += 8; n += 8;
@@ -157,7 +157,7 @@ int scanhash_blake2s_4way( struct work *work, uint32_t max_nonce,
if ( fulltest( lane_hash, ptarget ) && !opt_benchmark ) if ( fulltest( lane_hash, ptarget ) && !opt_benchmark )
{ {
pdata[19] = n + lane; pdata[19] = n + lane;
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
n += 4; n += 4;

View File

@@ -1,5 +1,7 @@
#include "blake2s-gate.h" #include "blake2s-gate.h"
#if !defined(BLAKE2S_16WAY) && !defined(BLAKE2S_8WAY) && !defined(BLAKE2S)
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
@@ -70,3 +72,4 @@ int scanhash_blake2s( struct work *work,
return 0; return 0;
} }
#endif

View File

@@ -49,7 +49,7 @@ int scanhash_blakecoin_4way( struct work *work, uint32_t max_nonce,
&& !opt_benchmark ) && !opt_benchmark )
{ {
pdata[19] = n+i; pdata[19] = n+i;
submit_lane_solution( work, hash+(i<<3), mythr, i ); submit_solution( work, hash+(i<<3), mythr );
} }
n += 4; n += 4;
@@ -108,7 +108,7 @@ int scanhash_blakecoin_8way( struct work *work, uint32_t max_nonce,
&& !opt_benchmark ) && !opt_benchmark )
{ {
pdata[19] = n+i; pdata[19] = n+i;
submit_lane_solution( work, hash+(i<<3), mythr, i ); submit_solution( work, hash+(i<<3), mythr );
} }
n += 8; n += 8;
} while ( (n < max_nonce) && !work_restart[thr_id].restart ); } while ( (n < max_nonce) && !work_restart[thr_id].restart );

View File

@@ -1,4 +1,7 @@
#include "blakecoin-gate.h" #include "blakecoin-gate.h"
#if !defined(BLAKECOIN_8WAY) && !defined(BLAKECOIN_4WAY)
#define BLAKE32_ROUNDS 8 #define BLAKE32_ROUNDS 8
#include "sph_blake.h" #include "sph_blake.h"
@@ -93,3 +96,4 @@ int scanhash_blakecoin( struct work *work, uint32_t max_nonce,
return 0; return 0;
} }
#endif

View File

@@ -62,7 +62,7 @@ int scanhash_decred_4way( struct work *work, uint32_t max_nonce,
if ( fulltest( hash+(i<<3), ptarget ) && !opt_benchmark ) if ( fulltest( hash+(i<<3), ptarget ) && !opt_benchmark )
{ {
pdata[DECRED_NONCE_INDEX] = n+i; pdata[DECRED_NONCE_INDEX] = n+i;
submit_lane_solution( work, hash+(i<<3), mythr, i ); submit_solution( work, hash+(i<<3), mythr );
} }
n += 4; n += 4;
} while ( (n < max_nonce) && !work_restart[thr_id].restart ); } while ( (n < max_nonce) && !work_restart[thr_id].restart );

View File

@@ -78,7 +78,6 @@ void decred_build_extraheader( struct work* g_work, struct stratum_ctx* sctx )
uint32_t extraheader[32] = { 0 }; uint32_t extraheader[32] = { 0 };
int headersize = 0; int headersize = 0;
uint32_t* extradata = (uint32_t*) sctx->xnonce1; uint32_t* extradata = (uint32_t*) sctx->xnonce1;
size_t t;
int i; int i;
// getwork over stratum, getwork merkle + header passed in coinb1 // getwork over stratum, getwork merkle + header passed in coinb1
@@ -87,9 +86,6 @@ void decred_build_extraheader( struct work* g_work, struct stratum_ctx* sctx )
sizeof(extraheader) ); sizeof(extraheader) );
memcpy( extraheader, &sctx->job.coinbase[32], headersize ); memcpy( extraheader, &sctx->job.coinbase[32], headersize );
// Increment extranonce2
for ( t = 0; t < sctx->xnonce2_size && !( ++sctx->job.xnonce2[t] ); t++ );
// Assemble block header // Assemble block header
memset( g_work->data, 0, sizeof(g_work->data) ); memset( g_work->data, 0, sizeof(g_work->data) );
g_work->data[0] = le32dec( sctx->job.version ); g_work->data[0] = le32dec( sctx->job.version );
@@ -153,7 +149,7 @@ bool register_decred_algo( algo_gate_t* gate )
gate->hash = (void*)&decred_hash; gate->hash = (void*)&decred_hash;
#endif #endif
gate->optimizations = AVX2_OPT; gate->optimizations = AVX2_OPT;
gate->get_nonceptr = (void*)&decred_get_nonceptr; // gate->get_nonceptr = (void*)&decred_get_nonceptr;
gate->decode_extra_data = (void*)&decred_decode_extradata; gate->decode_extra_data = (void*)&decred_decode_extradata;
gate->build_stratum_request = (void*)&decred_be_build_stratum_request; gate->build_stratum_request = (void*)&decred_be_build_stratum_request;
gate->work_decode = (void*)&std_be_work_decode; gate->work_decode = (void*)&std_be_work_decode;

View File

@@ -1,4 +1,7 @@
#include "decred-gate.h" #include "decred-gate.h"
#if !defined(DECRED_8WAY) && !defined(DECRED_4WAY)
#include "sph_blake.h" #include "sph_blake.h"
#include <string.h> #include <string.h>
@@ -275,3 +278,5 @@ bool register_decred_algo( algo_gate_t* gate )
return true; return true;
} }
*/ */
#endif

View File

@@ -105,7 +105,7 @@ int scanhash_pentablake_4way( struct work *work,
&& fulltest( hash+(i<<3), ptarget ) && !opt_benchmark ) && fulltest( hash+(i<<3), ptarget ) && !opt_benchmark )
{ {
pdata[19] = n + i; pdata[19] = n + i;
submit_lane_solution( work, hash+(i<<3), mythr, i ); submit_solution( work, hash+(i<<3), mythr );
} }
n += 4; n += 4;

View File

@@ -1,4 +1,7 @@
#include "pentablake-gate.h" #include "pentablake-gate.h"
#if !defined(PENTABLAKE_8WAY) && !defined(PENTABLAKE_4WAY)
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@@ -111,3 +114,4 @@ int scanhash_pentablake( struct work *work, uint32_t max_nonce,
return 0; return 0;
} }
#endif

View File

@@ -138,7 +138,7 @@ void bmw512_2way_close( bmw512_2way_context *ctx, void *dst );
#if defined(__AVX2__) #if defined(__AVX2__)
// BMW-512 4 way 64 // BMW-512 64 bit 4 way
typedef struct { typedef struct {
__m256i buf[16]; __m256i buf[16];
@@ -149,7 +149,6 @@ typedef struct {
typedef bmw_4way_big_context bmw512_4way_context; typedef bmw_4way_big_context bmw512_4way_context;
void bmw512_4way_init(void *cc); void bmw512_4way_init(void *cc);
void bmw512_4way_update(void *cc, const void *data, size_t len); void bmw512_4way_update(void *cc, const void *data, size_t len);
@@ -164,6 +163,7 @@ void bmw512_4way_addbits_and_close(
#if defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512DQ__) && defined(__AVX512BW__) #if defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512DQ__) && defined(__AVX512BW__)
// BMW-512 64 bit 8 way
typedef struct { typedef struct {
__m512i buf[16]; __m512i buf[16];
__m512i H[16]; __m512i H[16];
@@ -171,6 +171,8 @@ typedef struct {
uint64_t bit_count; uint64_t bit_count;
} bmw512_8way_context __attribute__((aligned(128))); } bmw512_8way_context __attribute__((aligned(128)));
void bmw512_8way_full( bmw512_8way_context *ctx, void *out, const void *data,
size_t len );
void bmw512_8way_init( bmw512_8way_context *ctx ); void bmw512_8way_init( bmw512_8way_context *ctx );
void bmw512_8way_update( bmw512_8way_context *ctx, const void *data, void bmw512_8way_update( bmw512_8way_context *ctx, const void *data,
size_t len ); size_t len );

View File

@@ -46,7 +46,7 @@ int scanhash_bmw512_8way( struct work *work, uint32_t max_nonce,
if ( fulltest( lane_hash, ptarget ) ) if ( fulltest( lane_hash, ptarget ) )
{ {
pdata[19] = n + lane; pdata[19] = n + lane;
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
n += 8; n += 8;
@@ -99,7 +99,7 @@ int scanhash_bmw512_4way( struct work *work, uint32_t max_nonce,
if ( fulltest( lane_hash, ptarget ) ) if ( fulltest( lane_hash, ptarget ) )
{ {
pdata[19] = n + lane; pdata[19] = n + lane;
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
n += 4; n += 4;

View File

@@ -1507,6 +1507,93 @@ void bmw512_8way_close( bmw512_8way_context *ctx, void *dst )
casti_m512i( dst, u ) = h1[ v ]; casti_m512i( dst, u ) = h1[ v ];
} }
void bmw512_8way_full( bmw512_8way_context *ctx, void *out, const void *data,
size_t len )
{
__m512i *vdata = (__m512i*)data;
__m512i *buf = ctx->buf;
__m512i htmp[16];
__m512i *H = ctx->H;
__m512i *h2 = htmp;
uint64_t bit_count = len * 8;
size_t ptr = 0;
const int buf_size = 128; // bytes of one lane, compatible with len
// Init
H[ 0] = m512_const1_64( 0x8081828384858687 );
H[ 1] = m512_const1_64( 0x88898A8B8C8D8E8F );
H[ 2] = m512_const1_64( 0x9091929394959697 );
H[ 3] = m512_const1_64( 0x98999A9B9C9D9E9F );
H[ 4] = m512_const1_64( 0xA0A1A2A3A4A5A6A7 );
H[ 5] = m512_const1_64( 0xA8A9AAABACADAEAF );
H[ 6] = m512_const1_64( 0xB0B1B2B3B4B5B6B7 );
H[ 7] = m512_const1_64( 0xB8B9BABBBCBDBEBF );
H[ 8] = m512_const1_64( 0xC0C1C2C3C4C5C6C7 );
H[ 9] = m512_const1_64( 0xC8C9CACBCCCDCECF );
H[10] = m512_const1_64( 0xD0D1D2D3D4D5D6D7 );
H[11] = m512_const1_64( 0xD8D9DADBDCDDDEDF );
H[12] = m512_const1_64( 0xE0E1E2E3E4E5E6E7 );
H[13] = m512_const1_64( 0xE8E9EAEBECEDEEEF );
H[14] = m512_const1_64( 0xF0F1F2F3F4F5F6F7 );
H[15] = m512_const1_64( 0xF8F9FAFBFCFDFEFF );
// Update
while ( len > 0 )
{
size_t clen;
clen = buf_size - ptr;
if ( clen > len )
clen = len;
memcpy_512( buf + (ptr>>3), vdata, clen >> 3 );
vdata = vdata + (clen>>3);
len -= clen;
ptr += clen;
if ( ptr == buf_size )
{
__m512i *ht;
compress_big_8way( buf, H, h2 );
ht = H;
H = h2;
h2 = ht;
ptr = 0;
}
}
if ( H != ctx->H )
memcpy_512( ctx->H, H, 16 );
// Close
{
__m512i h1[16], h2[16];
size_t u, v;
buf[ ptr>>3 ] = m512_const1_64( 0x80 );
ptr += 8;
if ( ptr > (buf_size - 8) )
{
memset_zero_512( buf + (ptr>>3), (buf_size - ptr) >> 3 );
compress_big_8way( buf, H, h1 );
ptr = 0;
H = h1;
}
memset_zero_512( buf + (ptr>>3), (buf_size - 8 - ptr) >> 3 );
buf[ (buf_size - 8) >> 3 ] = _mm512_set1_epi64( bit_count );
compress_big_8way( buf, H, h2 );
for ( u = 0; u < 16; u ++ )
buf[ u ] = h2[ u ];
compress_big_8way( buf, final_b8, h1 );
for (u = 0, v = 8; u < 8; u ++, v ++)
casti_m512i( out, u ) = h1[ v ];
}
}
#endif // AVX512 #endif // AVX512
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -1,5 +1,7 @@
#include "algo-gate-api.h" #include "algo-gate-api.h"
#if !defined(BMW512_8WAY) && !defined(BMW512_4WAY)
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
@@ -50,4 +52,4 @@ int scanhash_bmw512( struct work *work, uint32_t max_nonce,
pdata[19] = n; pdata[19] = n;
return 0; return 0;
} }
#endif

View File

@@ -48,6 +48,8 @@ extern "C"{
#pragma warning (disable: 4146) #pragma warning (disable: 4146)
#endif #endif
#if !defined(__AVX2__)
static const sph_u32 IV224[] = { static const sph_u32 IV224[] = {
SPH_C32(0x00010203), SPH_C32(0x04050607), SPH_C32(0x00010203), SPH_C32(0x04050607),
SPH_C32(0x08090A0B), SPH_C32(0x0C0D0E0F), SPH_C32(0x08090A0B), SPH_C32(0x0C0D0E0F),
@@ -70,6 +72,8 @@ static const sph_u32 IV256[] = {
SPH_C32(0x78797A7B), SPH_C32(0x7C7D7E7F) SPH_C32(0x78797A7B), SPH_C32(0x7C7D7E7F)
}; };
#endif // !AVX2
#if SPH_64 #if SPH_64
static const sph_u64 IV384[] = { static const sph_u64 IV384[] = {
@@ -135,6 +139,8 @@ static const sph_u64 IV512[] = {
#define M16_30 14, 15, 1, 2, 5, 8, 9 #define M16_30 14, 15, 1, 2, 5, 8, 9
#define M16_31 15, 16, 2, 3, 6, 9, 10 #define M16_31 15, 16, 2, 3, 6, 9, 10
#if !defined(__AVX2__)
#define ss0(x) (((x) >> 1) ^ SPH_T32((x) << 3) \ #define ss0(x) (((x) >> 1) ^ SPH_T32((x) << 3) \
^ SPH_ROTL32(x, 4) ^ SPH_ROTL32(x, 19)) ^ SPH_ROTL32(x, 4) ^ SPH_ROTL32(x, 19))
#define ss1(x) (((x) >> 1) ^ SPH_T32((x) << 2) \ #define ss1(x) (((x) >> 1) ^ SPH_T32((x) << 2) \
@@ -189,6 +195,8 @@ static const sph_u64 IV512[] = {
#define expand2s_(qf, mf, hf, i16, ix, iy) \ #define expand2s_(qf, mf, hf, i16, ix, iy) \
expand2s_inner LPAR qf, mf, hf, i16, ix, iy) expand2s_inner LPAR qf, mf, hf, i16, ix, iy)
#endif // !AVX2
#if SPH_64 #if SPH_64
#define sb0(x) (((x) >> 1) ^ SPH_T64((x) << 3) \ #define sb0(x) (((x) >> 1) ^ SPH_T64((x) << 3) \
@@ -291,6 +299,8 @@ static const sph_u64 Kb_tab[] = {
tt((M(i0) ^ H(i0)) op01 (M(i1) ^ H(i1)) op12 (M(i2) ^ H(i2)) \ tt((M(i0) ^ H(i0)) op01 (M(i1) ^ H(i1)) op12 (M(i2) ^ H(i2)) \
op23 (M(i3) ^ H(i3)) op34 (M(i4) ^ H(i4))) op23 (M(i3) ^ H(i3)) op34 (M(i4) ^ H(i4)))
#if !defined(__AVX2__)
#define Ws0 MAKE_W(SPH_T32, 5, -, 7, +, 10, +, 13, +, 14) #define Ws0 MAKE_W(SPH_T32, 5, -, 7, +, 10, +, 13, +, 14)
#define Ws1 MAKE_W(SPH_T32, 6, -, 8, +, 11, +, 14, -, 15) #define Ws1 MAKE_W(SPH_T32, 6, -, 8, +, 11, +, 14, -, 15)
#define Ws2 MAKE_W(SPH_T32, 0, +, 7, +, 9, -, 12, +, 15) #define Ws2 MAKE_W(SPH_T32, 0, +, 7, +, 9, -, 12, +, 15)
@@ -407,6 +417,8 @@ static const sph_u64 Kb_tab[] = {
#define Qs(j) (qt[j]) #define Qs(j) (qt[j])
#endif // !AVX2
#if SPH_64 #if SPH_64
#define Wb0 MAKE_W(SPH_T64, 5, -, 7, +, 10, +, 13, +, 14) #define Wb0 MAKE_W(SPH_T64, 5, -, 7, +, 10, +, 13, +, 14)
@@ -557,7 +569,6 @@ static const sph_u64 Kb_tab[] = {
+ ((xl >> 2) ^ qf(22) ^ qf(15))); \ + ((xl >> 2) ^ qf(22) ^ qf(15))); \
} while (0) } while (0)
#define FOLDs FOLD(sph_u32, MAKE_Qs, SPH_T32, SPH_ROTL32, M, Qs, dH)
#if SPH_64 #if SPH_64
@@ -565,6 +576,10 @@ static const sph_u64 Kb_tab[] = {
#endif #endif
#if !defined(__AVX2__)
#define FOLDs FOLD(sph_u32, MAKE_Qs, SPH_T32, SPH_ROTL32, M, Qs, dH)
static void static void
compress_small(const unsigned char *data, const sph_u32 h[16], sph_u32 dh[16]) compress_small(const unsigned char *data, const sph_u32 h[16], sph_u32 dh[16])
{ {
@@ -711,6 +726,8 @@ bmw32_close(sph_bmw_small_context *sc, unsigned ub, unsigned n,
sph_enc32le(out + 4 * u, h1[v]); sph_enc32le(out + 4 * u, h1[v]);
} }
#endif // !AVX2
#if SPH_64 #if SPH_64
static void static void
@@ -840,6 +857,8 @@ bmw64_close(sph_bmw_big_context *sc, unsigned ub, unsigned n,
#endif #endif
#if !defined(__AVX2__)
/* see sph_bmw.h */ /* see sph_bmw.h */
void void
sph_bmw224_init(void *cc) sph_bmw224_init(void *cc)
@@ -898,6 +917,8 @@ sph_bmw256_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)
// sph_bmw256_init(cc); // sph_bmw256_init(cc);
} }
#endif // !AVX2
#if SPH_64 #if SPH_64
/* see sph_bmw.h */ /* see sph_bmw.h */

View File

@@ -77,6 +77,9 @@ extern "C"{
* computation can be cloned by copying the context (e.g. with a simple * computation can be cloned by copying the context (e.g. with a simple
* <code>memcpy()</code>). * <code>memcpy()</code>).
*/ */
#if !defined(__AVX2__)
typedef struct { typedef struct {
#ifndef DOXYGEN_IGNORE #ifndef DOXYGEN_IGNORE
unsigned char buf[64]; /* first field, for alignment */ unsigned char buf[64]; /* first field, for alignment */
@@ -102,6 +105,8 @@ typedef sph_bmw_small_context sph_bmw224_context;
*/ */
typedef sph_bmw_small_context sph_bmw256_context; typedef sph_bmw_small_context sph_bmw256_context;
#endif // !AVX2
#if SPH_64 #if SPH_64
/** /**
@@ -137,6 +142,8 @@ typedef sph_bmw_big_context sph_bmw512_context;
#endif #endif
#if !defined(__AVX2__)
/** /**
* Initialize a BMW-224 context. This process performs no memory allocation. * Initialize a BMW-224 context. This process performs no memory allocation.
* *
@@ -227,6 +234,8 @@ void sph_bmw256_close(void *cc, void *dst);
void sph_bmw256_addbits_and_close( void sph_bmw256_addbits_and_close(
void *cc, unsigned ub, unsigned n, void *dst); void *cc, unsigned ub, unsigned n, void *dst);
#endif // !AVX2
#if SPH_64 #if SPH_64
/** /**

View File

@@ -1,368 +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 "algo-gate-api.h"
#if defined(__arm__) || defined(_MSC_VER)
#ifndef NOASM
#define NOASM
#endif
#endif
#include "crypto/oaes_lib.h"
#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"
#include "crypto/int-util.h"
#include "crypto/hash-ops.h"
#if USE_INT128
#if __GNUC__ == 4 && __GNUC_MINOR__ >= 4 && __GNUC_MINOR__ < 6
typedef unsigned int uint128_t __attribute__ ((__mode__ (TI)));
#elif defined (_MSC_VER)
/* only for mingw64 on windows */
#undef USE_INT128
#define USE_INT128 (0)
#else
typedef __uint128_t uint128_t;
#endif
#endif
#define LITE 1
#if LITE /* cryptonight-light */
#define MEMORY (1 << 20)
#define ITER (1 << 19)
#else
#define MEMORY (1 << 21) /* 2 MiB */
#define ITER (1 << 20)
#endif
#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)
#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)
static void do_blake_hash(const void* input, size_t len, char* output) {
blake256_hash((uint8_t*)output, input, len);
}
static void do_groestl_hash(const void* input, size_t len, char* output) {
groestl(input, len * 8, (uint8_t*)output);
}
static void do_jh_hash(const void* input, size_t len, char* output) {
int r = jh_hash(HASH_SIZE * 8, input, 8 * len, (uint8_t*)output);
assert(likely(SUCCESS == r));
}
static void do_skein_hash(const void* input, size_t len, char* output) {
int r = skein_hash(8 * HASH_SIZE, input, 8 * len, (uint8_t*)output);
assert(likely(SKEIN_SUCCESS == r));
}
extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey);
extern int aesb_pseudo_round_mut(uint8_t *val, uint8_t *expandedKey);
#if !defined(_MSC_VER) && !defined(NOASM)
extern int fast_aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey);
extern int fast_aesb_pseudo_round_mut(uint8_t *val, uint8_t *expandedKey);
#else
#define fast_aesb_single_round aesb_single_round
#define fast_aesb_pseudo_round_mut aesb_pseudo_round_mut
#endif
#if defined(NOASM) || !defined(__x86_64__)
static 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 = hi_dword(multiplier);
uint64_t b = lo_dword(multiplier);
uint64_t c = hi_dword(multiplicand);
uint64_t d = lo_dword(multiplicand);
uint64_t ac = a * c;
uint64_t ad = a * d;
uint64_t bc = b * c;
uint64_t bd = b * d;
uint64_t adbc = ad + bc;
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 = ac + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
assert(ac <= *product_hi);
return product_lo;
}
#else
extern uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi);
#endif
static void (* const extra_hashes[4])(const void *, size_t, char *) = {
do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash
};
static inline size_t e2i(const uint8_t* a) {
#if !LITE
return ((uint32_t *)a)[0] & 0x1FFFF0;
#else
return ((uint32_t *)a)[0] & 0xFFFF0;
#endif
}
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) {
#if USE_INT128
*((uint128_t*) a) ^= *((uint128_t*) b);
#else
((uint64_t*) a)[0] ^= ((uint64_t*) b)[0];
((uint64_t*) a)[1] ^= ((uint64_t*) b)[1];
#endif
}
static inline void xor_blocks_dst(const uint8_t* a, const uint8_t* b, uint8_t* dst) {
#if USE_INT128
*((uint128_t*) dst) = *((uint128_t*) a) ^ *((uint128_t*) b);
#else
((uint64_t*) dst)[0] = ((uint64_t*) a)[0] ^ ((uint64_t*) b)[0];
((uint64_t*) dst)[1] = ((uint64_t*) a)[1] ^ ((uint64_t*) b)[1];
#endif
}
struct cryptonight_ctx {
uint8_t _ALIGN(16) long_state[MEMORY];
union cn_slow_hash_state state;
uint8_t _ALIGN(16) text[INIT_SIZE_BYTE];
uint8_t _ALIGN(16) a[AES_BLOCK_SIZE];
uint8_t _ALIGN(16) b[AES_BLOCK_SIZE];
uint8_t _ALIGN(16) c[AES_BLOCK_SIZE];
oaes_ctx* aes_ctx;
};
static void cryptolight_hash_ctx(void* output, const void* input, int len, struct cryptonight_ctx* ctx)
{
len = 76;
hash_process(&ctx->state.hs, (const uint8_t*) input, len);
ctx->aes_ctx = (oaes_ctx*) oaes_alloc();
size_t i, j;
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
oaes_key_import_data(ctx->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], ctx->aes_ctx->key->exp_data);
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 1], ctx->aes_ctx->key->exp_data);
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 2], ctx->aes_ctx->key->exp_data);
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 3], ctx->aes_ctx->key->exp_data);
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 4], ctx->aes_ctx->key->exp_data);
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 5], ctx->aes_ctx->key->exp_data);
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 6], ctx->aes_ctx->key->exp_data);
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 7], ctx->aes_ctx->key->exp_data);
memcpy(&ctx->long_state[i], ctx->text, INIT_SIZE_BYTE);
}
xor_blocks_dst(&ctx->state.k[0], &ctx->state.k[32], ctx->a);
xor_blocks_dst(&ctx->state.k[16], &ctx->state.k[48], 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 = e2i(ctx->a);
aesb_single_round(&ctx->long_state[j], ctx->c, ctx->a);
xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j]);
/* Iteration 2 */
mul_sum_xor_dst(ctx->c, ctx->a, &ctx->long_state[e2i(ctx->c)]);
/* Iteration 3 */
j = e2i(ctx->a);
aesb_single_round(&ctx->long_state[j], ctx->b, ctx->a);
xor_blocks_dst(ctx->b, ctx->c, &ctx->long_state[j]);
/* Iteration 4 */
mul_sum_xor_dst(ctx->b, ctx->a, &ctx->long_state[e2i(ctx->b)]);
}
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
oaes_key_import_data(ctx->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], &ctx->long_state[i + 0 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx->text[0 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
xor_blocks(&ctx->text[1 * AES_BLOCK_SIZE], &ctx->long_state[i + 1 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx->text[1 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
xor_blocks(&ctx->text[2 * AES_BLOCK_SIZE], &ctx->long_state[i + 2 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx->text[2 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
xor_blocks(&ctx->text[3 * AES_BLOCK_SIZE], &ctx->long_state[i + 3 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx->text[3 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
xor_blocks(&ctx->text[4 * AES_BLOCK_SIZE], &ctx->long_state[i + 4 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx->text[4 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
xor_blocks(&ctx->text[5 * AES_BLOCK_SIZE], &ctx->long_state[i + 5 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx->text[5 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
xor_blocks(&ctx->text[6 * AES_BLOCK_SIZE], &ctx->long_state[i + 6 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx->text[6 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
xor_blocks(&ctx->text[7 * AES_BLOCK_SIZE], &ctx->long_state[i + 7 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx->text[7 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
}
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
hash_permutation(&ctx->state.hs);
/*memcpy(hash, &state, 32);*/
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
oaes_free((OAES_CTX **) &ctx->aes_ctx);
}
void cryptolight_hash(void* output, const void* input, int len) {
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx));
cryptolight_hash_ctx(output, input, len, ctx);
free(ctx);
}
#if defined(__AES__)
static void cryptolight_hash_ctx_aes_ni(void* output, const void* input,
int len, struct cryptonight_ctx* ctx)
{
hash_process(&ctx->state.hs, (const uint8_t*)input, len);
ctx->aes_ctx = (oaes_ctx*) oaes_alloc();
size_t i, j;
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
oaes_key_import_data(ctx->aes_ctx, ctx->state.hs.b, AES_KEY_SIZE);
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) {
fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 0], ctx->aes_ctx->key->exp_data);
fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 1], ctx->aes_ctx->key->exp_data);
fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 2], ctx->aes_ctx->key->exp_data);
fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 3], ctx->aes_ctx->key->exp_data);
fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 4], ctx->aes_ctx->key->exp_data);
fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 5], ctx->aes_ctx->key->exp_data);
fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 6], ctx->aes_ctx->key->exp_data);
fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 7], ctx->aes_ctx->key->exp_data);
memcpy(&ctx->long_state[i], ctx->text, INIT_SIZE_BYTE);
}
xor_blocks_dst(&ctx->state.k[0], &ctx->state.k[32], ctx->a);
xor_blocks_dst(&ctx->state.k[16], &ctx->state.k[48], 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 = e2i(ctx->a);
fast_aesb_single_round(&ctx->long_state[j], ctx->c, ctx->a);
xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j]);
/* Iteration 2 */
mul_sum_xor_dst(ctx->c, ctx->a, &ctx->long_state[e2i(ctx->c)]);
/* Iteration 3 */
j = e2i(ctx->a);
fast_aesb_single_round(&ctx->long_state[j], ctx->b, ctx->a);
xor_blocks_dst(ctx->b, ctx->c, &ctx->long_state[j]);
/* Iteration 4 */
mul_sum_xor_dst(ctx->b, ctx->a, &ctx->long_state[e2i(ctx->b)]);
}
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
oaes_key_import_data(ctx->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], &ctx->long_state[i + 0 * AES_BLOCK_SIZE]);
fast_aesb_pseudo_round_mut(&ctx->text[0 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
xor_blocks(&ctx->text[1 * AES_BLOCK_SIZE], &ctx->long_state[i + 1 * AES_BLOCK_SIZE]);
fast_aesb_pseudo_round_mut(&ctx->text[1 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
xor_blocks(&ctx->text[2 * AES_BLOCK_SIZE], &ctx->long_state[i + 2 * AES_BLOCK_SIZE]);
fast_aesb_pseudo_round_mut(&ctx->text[2 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
xor_blocks(&ctx->text[3 * AES_BLOCK_SIZE], &ctx->long_state[i + 3 * AES_BLOCK_SIZE]);
fast_aesb_pseudo_round_mut(&ctx->text[3 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
xor_blocks(&ctx->text[4 * AES_BLOCK_SIZE], &ctx->long_state[i + 4 * AES_BLOCK_SIZE]);
fast_aesb_pseudo_round_mut(&ctx->text[4 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
xor_blocks(&ctx->text[5 * AES_BLOCK_SIZE], &ctx->long_state[i + 5 * AES_BLOCK_SIZE]);
fast_aesb_pseudo_round_mut(&ctx->text[5 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
xor_blocks(&ctx->text[6 * AES_BLOCK_SIZE], &ctx->long_state[i + 6 * AES_BLOCK_SIZE]);
fast_aesb_pseudo_round_mut(&ctx->text[6 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
xor_blocks(&ctx->text[7 * AES_BLOCK_SIZE], &ctx->long_state[i + 7 * AES_BLOCK_SIZE]);
fast_aesb_pseudo_round_mut(&ctx->text[7 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data);
}
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
hash_permutation(&ctx->state.hs);
/*memcpy(hash, &state, 32);*/
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
oaes_free((OAES_CTX **) &ctx->aes_ctx);
}
#endif
int scanhash_cryptolight( struct work *work,
uint32_t max_nonce, uint64_t *hashes_done, struct thr_info *mythr)
{
uint32_t *pdata = work->data;
uint32_t *ptarget = work->target;
uint32_t *nonceptr = (uint32_t*) (((char*)pdata) + 39);
uint32_t n = *nonceptr - 1;
const uint32_t first_nonce = n + 1;
//const uint32_t Htarg = ptarget[7];
uint32_t _ALIGN(32) hash[HASH_SIZE / 4];
int thr_id = mythr->id;
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx));
#if defined(__AES__)
do {
*nonceptr = ++n;
cryptolight_hash_ctx_aes_ni(hash, pdata, 76, ctx);
if (unlikely(hash[7] < ptarget[7])) {
*hashes_done = n - first_nonce + 1;
free(ctx);
return true;
}
} while (likely((n <= max_nonce && !work_restart[thr_id].restart)));
#else
do {
*nonceptr = ++n;
cryptolight_hash_ctx(hash, pdata, 76, ctx);
if (unlikely(hash[7] < ptarget[7])) {
*hashes_done = n - first_nonce + 1;
free(ctx);
return true;
}
} while (likely((n <= max_nonce && !work_restart[thr_id].restart)));
#endif
free(ctx);
*hashes_done = n - first_nonce + 1;
return 0;
}
bool register_cryptolight_algo( algo_gate_t* gate )
{
register_json_rpc2( gate );
gate->optimizations = SSE2_OPT | AES_OPT;
gate->scanhash = (void*)&scanhash_cryptolight;
gate->hash = (void*)&cryptolight_hash;
gate->hash_suw = (void*)&cryptolight_hash;
return true;
};

View File

@@ -1,357 +0,0 @@
#if defined(__AES__)
#include <x86intrin.h>
#include <memory.h>
#include "cryptonight.h"
#include "miner.h"
#include "crypto/c_keccak.h"
#include <immintrin.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;
}
// align to 64 byte cache line
typedef struct
{
uint8_t long_state[MEMORY] __attribute((aligned(64)));
union cn_slow_hash_state state;
uint8_t text[INIT_SIZE_BYTE] __attribute((aligned(64)));
uint64_t a[AES_BLOCK_SIZE >> 3] __attribute__((aligned(64)));
uint64_t b[AES_BLOCK_SIZE >> 3] __attribute__((aligned(64)));
uint8_t c[AES_BLOCK_SIZE] __attribute__((aligned(64)));
} cryptonight_ctx;
static __thread cryptonight_ctx ctx;
void cryptonight_hash_aes( void *restrict output, const void *input, int len )
{
uint8_t ExpandedKey[256] __attribute__((aligned(64)));
__m128i *longoutput, *expkey, *xmminput;
size_t i, j;
keccak( (const uint8_t*)input, 76, (char*)&ctx.state.hs.b, 200 );
if ( cryptonightV7 && len < 43 )
return;
const uint64_t tweak = cryptonightV7
? *((const uint64_t*) (((const uint8_t*)input) + 35))
^ ctx.state.hs.w[24] : 0;
memcpy( ExpandedKey, ctx.state.hs.b, AES_KEY_SIZE );
ExpandAESKey256( ExpandedKey );
memcpy( ctx.text, ctx.state.init, INIT_SIZE_BYTE );
longoutput = (__m128i*)ctx.long_state;
xmminput = (__m128i*)ctx.text;
expkey = (__m128i*)ExpandedKey;
// prefetch expkey, xmminput and enough longoutput for 4 iterations
_mm_prefetch( xmminput, _MM_HINT_T0 );
_mm_prefetch( xmminput + 4, _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; i < 64; i += 16 )
{
__builtin_prefetch( longoutput + i, 1, 0 );
__builtin_prefetch( longoutput + i + 4, 1, 0 );
__builtin_prefetch( longoutput + i + 8, 1, 0 );
__builtin_prefetch( longoutput + i + 12, 1, 0 );
}
// n-4 iterations
for ( i = 0; likely( i < MEMORY_M128I - 4*INIT_SIZE_M128I );
i += INIT_SIZE_M128I )
{
// prefetch 4 iterations ahead.
__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] );
}
// last 4 iterations
for ( ; likely( i < MEMORY_M128I ); i += INIT_SIZE_M128I )
{
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];
uint64_t a[2] __attribute((aligned(16))),
b[2] __attribute((aligned(16))),
c[2] __attribute((aligned(16)));
a[0] = ctx.a[0];
a[1] = ctx.a[1];
__m128i b_x = _mm_load_si128( (__m128i*)ctx.b );
__m128i a_x = _mm_load_si128( (__m128i*)a );
__m128i* lsa = (__m128i*)&ctx.long_state[ a[0] & 0x1FFFF0 ];
__m128i c_x = _mm_load_si128( lsa );
uint64_t *nextblock;
uint64_t hi, lo;
// n-1 iterations
for( i = 0; __builtin_expect( i < 0x7ffff, 1 ); i++ )
{
c_x = _mm_aesenc_si128( c_x, a_x );
_mm_store_si128( (__m128i*)c, c_x );
b_x = _mm_xor_si128( b_x, c_x );
nextblock = (uint64_t *)&ctx.long_state[c[0] & 0x1FFFF0];
_mm_store_si128( lsa, b_x );
if ( cryptonightV7 )
{
const uint8_t tmp = ( (const uint8_t*)(lsa) )[11];
const uint8_t index = ( ( (tmp >> 3) & 6 ) | (tmp & 1) ) << 1;
((uint8_t*)(lsa))[11] = tmp ^ ( ( 0x75310 >> index) & 0x30 );
}
b[0] = nextblock[0];
b[1] = nextblock[1];
// 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" );
b_x = c_x;
a[0] += hi;
a[1] += lo;
nextblock[0] = a[0];
nextblock[1] = cryptonightV7 ? a[1] ^ tweak : a[1];
a[0] ^= b[0];
a[1] ^= b[1];
lsa = (__m128i*)&ctx.long_state[ a[0] & 0x1FFFF0 ];
a_x = _mm_load_si128( (__m128i*)a );
c_x = _mm_load_si128( lsa );
}
// abreviated nth iteration
c_x = _mm_aesenc_si128( c_x, a_x );
_mm_store_si128( (__m128i*)c, c_x );
b_x = _mm_xor_si128( b_x, c_x );
nextblock = (uint64_t *)&ctx.long_state[c[0] & 0x1FFFF0];
_mm_store_si128( lsa, b_x );
if ( cryptonightV7 )
{
const uint8_t tmp = ( (const uint8_t*)(lsa) )[11];
const uint8_t index = ( ( (tmp >> 3) & 6 ) | (tmp & 1) ) << 1;
((uint8_t*)(lsa))[11] = tmp ^ ( ( 0x75310 >> index) & 0x30 );
}
b[0] = nextblock[0];
b[1] = nextblock[1];
__asm__( "mulq %3\n\t"
: "=d" ( hi ),
"=a" ( lo )
: "%a" ( c[0] ),
"rm" ( b[0] )
: "cc" );
a[0] += hi;
a[1] += lo;
nextblock[0] = a[0];
nextblock[1] = cryptonightV7 ? a[1] ^ tweak : a[1];
a[0] ^= b[0];
a[1] ^= b[1];
memcpy( ExpandedKey, &ctx.state.hs.b[32], AES_KEY_SIZE );
ExpandAESKey256( ExpandedKey );
memcpy( ctx.text, ctx.state.init, INIT_SIZE_BYTE );
// 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 );
// n-4 iterations
for ( i = 0; likely( i < MEMORY_M128I - 4*INIT_SIZE_M128I );
i += INIT_SIZE_M128I )
{
// stay 4 iterations ahead.
_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] );
}
}
// last 4 iterations
for ( ; likely( i < MEMORY_M128I ); i += INIT_SIZE_M128I )
{
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.w, 24 );
extra_hashes[ctx.state.hs.b[0] & 3](&ctx.state, 200, output);
}
#endif

View File

@@ -1,127 +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.
// Modified for CPUminer by Lucas Jones
#include "cpuminer-config.h"
#include "algo-gate-api.h"
#if defined(__AES__)
#include "algo/groestl/aes_ni/hash-groestl256.h"
#else
#include "crypto/c_groestl.h"
#endif
#include "crypto/c_blake256.h"
#include "crypto/c_jh.h"
#include "crypto/c_skein.h"
#include "cryptonight.h"
/*
#if defined __unix__ && (!defined __APPLE__)
#include <sys/mman.h>
#elif defined _WIN32
#include <windows.h>
#endif
*/
void do_blake_hash(const void* input, size_t len, char* output) {
blake256_hash((uint8_t*)output, input, len);
}
void do_groestl_hash(const void* input, size_t len, char* output) {
#if defined(__AES__)
hashState_groestl256 ctx;
init_groestl256( &ctx, 32 );
update_and_final_groestl256( &ctx, output, input, len * 8 );
#else
groestl(input, len * 8, (uint8_t*)output);
#endif
}
void do_jh_hash(const void* input, size_t len, char* output) {
jh_hash(32 * 8, input, 8 * len, (uint8_t*)output);
}
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 *restrict output, const void *input, int len )
{
#if defined(__AES__)
cryptonight_hash_aes( output, input, len );
#else
cryptonight_hash_ctx ( output, input, len );
#endif
}
void cryptonight_hash_suw( void *restrict output, const void *input )
{
#if defined(__AES__)
cryptonight_hash_aes( output, input, 76 );
#else
cryptonight_hash_ctx ( output, input, 76 );
#endif
}
bool cryptonightV7 = false;
int scanhash_cryptonight( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr )
{
uint32_t *pdata = work->data;
uint32_t *ptarget = work->target;
int thr_id = mythr->id;
uint32_t *nonceptr = (uint32_t*) (((char*)pdata) + 39);
uint32_t n = *nonceptr - 1;
const uint32_t first_nonce = n + 1;
const uint32_t Htarg = ptarget[7];
uint32_t hash[32 / 4] __attribute__((aligned(32)));
// if ( ( cryptonightV7 && ( *(uint8_t*)pdata < 7 ) )
// || ( !cryptonightV7 && ( *(uint8_t*)pdata == 7 ) ) )
// applog(LOG_WARNING,"Cryptonight variant mismatch, shares may be rejected.");
do
{
*nonceptr = ++n;
cryptonight_hash( hash, pdata, 76 );
if (unlikely( hash[7] < Htarg ))
{
*hashes_done = n - first_nonce + 1;
// work_set_target_ratio( work, hash );
return true;
}
} while (likely((n <= max_nonce && !work_restart[thr_id].restart)));
*hashes_done = n - first_nonce + 1;
return 0;
}
bool register_cryptonight_algo( algo_gate_t* gate )
{
cryptonightV7 = false;
register_json_rpc2( gate );
gate->optimizations = SSE2_OPT | AES_OPT;
gate->scanhash = (void*)&scanhash_cryptonight;
gate->hash = (void*)&cryptonight_hash;
gate->hash_suw = (void*)&cryptonight_hash_suw;
return true;
};
bool register_cryptonightv7_algo( algo_gate_t* gate )
{
cryptonightV7 = true;
register_json_rpc2( gate );
gate->optimizations = SSE2_OPT | AES_OPT;
gate->scanhash = (void*)&scanhash_cryptonight;
gate->hash = (void*)&cryptonight_hash;
gate->hash_suw = (void*)&cryptonight_hash_suw;
return true;
};

View File

@@ -1,310 +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.
// Modified for CPUminer by Lucas Jones
#include "miner.h"
#include <memory.h>
#if defined(__arm__) || defined(_MSC_VER)
#ifndef NOASM
#define NOASM
#endif
#endif
#include "crypto/oaes_lib.h"
#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"
#include "crypto/int-util.h"
//#include "crypto/hash-ops.h"
#include "cryptonight.h"
#if USE_INT128
#if __GNUC__ == 4 && __GNUC_MINOR__ >= 4 && __GNUC_MINOR__ < 6
typedef unsigned int uint128_t __attribute__ ((__mode__ (TI)));
#elif defined (_MSC_VER)
/* only for mingw64 on windows */
#undef USE_INT128
#define USE_INT128 (0)
#else
typedef __uint128_t uint128_t;
#endif
#endif
#define LITE 0
#if LITE /* cryptonight-light */
#define MEMORY (1 << 20)
#define ITER (1 << 19)
#else
#define MEMORY (1 << 21) /* 2 MiB */
#define ITER (1 << 20)
#endif
#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)
/*
#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)
static void do_blake_hash(const void* input, size_t len, char* output) {
blake256_hash((uint8_t*)output, input, len);
}
static void do_groestl_hash(const void* input, size_t len, char* output) {
groestl(input, len * 8, (uint8_t*)output);
}
static void do_jh_hash(const void* input, size_t len, char* output) {
int r = jh_hash(HASH_SIZE * 8, input, 8 * len, (uint8_t*)output);
assert(likely(SUCCESS == r));
}
static void do_skein_hash(const void* input, size_t len, char* output) {
int r = skein_hash(8 * HASH_SIZE, input, 8 * len, (uint8_t*)output);
assert(likely(SKEIN_SUCCESS == r));
}
*/
extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey);
extern int aesb_pseudo_round_mut(uint8_t *val, uint8_t *expandedKey);
#if !defined(_MSC_VER) && !defined(NOASM)
extern int fast_aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey);
extern int fast_aesb_pseudo_round_mut(uint8_t *val, uint8_t *expandedKey);
#else
#define fast_aesb_single_round aesb_single_round
#define fast_aesb_pseudo_round_mut aesb_pseudo_round_mut
#endif
#if defined(NOASM) || !defined(__x86_64__)
static 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 = hi_dword(multiplier);
uint64_t b = lo_dword(multiplier);
uint64_t c = hi_dword(multiplicand);
uint64_t d = lo_dword(multiplicand);
uint64_t ac = a * c;
uint64_t ad = a * d;
uint64_t bc = b * c;
uint64_t bd = b * d;
uint64_t adbc = ad + bc;
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 = ac + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
assert(ac <= *product_hi);
return product_lo;
}
#else
extern uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi);
#endif
/*
static void (* const extra_hashes[4])(const void *, size_t, char *) = {
do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash
};
*/
static inline size_t e2i(const uint8_t* a) {
#if !LITE
return ((uint32_t *)a)[0] & 0x1FFFF0;
#else
return ((uint32_t *)a)[0] & 0xFFFF0;
#endif
}
static inline void mul_sum_xor_dst( const uint8_t* a, uint8_t* c, uint8_t* dst,
const uint64_t tweak )
{
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] = cryptonightV7 ? lo ^ tweak : lo;
}
static inline void xor_blocks(uint8_t* a, const uint8_t* b) {
#if USE_INT128
*((uint128_t*) a) ^= *((uint128_t*) b);
#else
((uint64_t*) a)[0] ^= ((uint64_t*) b)[0];
((uint64_t*) a)[1] ^= ((uint64_t*) b)[1];
#endif
}
static inline void xor_blocks_dst(const uint8_t* a, const uint8_t* b, uint8_t* dst) {
#if USE_INT128
*((uint128_t*) dst) = *((uint128_t*) a) ^ *((uint128_t*) b);
#else
((uint64_t*) dst)[0] = ((uint64_t*) a)[0] ^ ((uint64_t*) b)[0];
((uint64_t*) dst)[1] = ((uint64_t*) a)[1] ^ ((uint64_t*) b)[1];
#endif
}
typedef struct {
uint8_t _ALIGN(16) long_state[MEMORY];
union cn_slow_hash_state state;
uint8_t _ALIGN(16) text[INIT_SIZE_BYTE];
uint8_t _ALIGN(16) a[AES_BLOCK_SIZE];
uint8_t _ALIGN(16) b[AES_BLOCK_SIZE];
uint8_t _ALIGN(16) c[AES_BLOCK_SIZE];
oaes_ctx* aes_ctx;
} cryptonight_ctx;
static __thread cryptonight_ctx ctx;
void cryptonight_hash_ctx(void* output, const void* input, int len)
{
// hash_process(&ctx.state.hs, (const uint8_t*) input, len);
keccak( (const uint8_t*)input, 76, (char*)&ctx.state.hs.b, 200 );
if ( cryptonightV7 && len < 43 )
return;
const uint64_t tweak = cryptonightV7
? *((const uint64_t*) (((const uint8_t*)input) + 35))
^ ctx.state.hs.w[24] : 0;
ctx.aes_ctx = (oaes_ctx*) oaes_alloc();
__builtin_prefetch( ctx.text, 0, 3 );
__builtin_prefetch( ctx.text + 64, 0, 3 );
__builtin_prefetch( ctx.long_state, 1, 0 );
__builtin_prefetch( ctx.long_state + 64, 1, 0 );
__builtin_prefetch( ctx.long_state + 128, 1, 0 );
__builtin_prefetch( ctx.long_state + 192, 1, 0 );
__builtin_prefetch( ctx.long_state + 256, 1, 0 );
__builtin_prefetch( ctx.long_state + 320, 1, 0 );
__builtin_prefetch( ctx.long_state + 384, 1, 0 );
__builtin_prefetch( ctx.long_state + 448, 1, 0 );
size_t i, j;
memcpy(ctx.text, ctx.state.init, INIT_SIZE_BYTE);
oaes_key_import_data(ctx.aes_ctx, ctx.state.hs.b, AES_KEY_SIZE);
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) {
__builtin_prefetch( ctx.long_state + i + 512, 1, 0 );
__builtin_prefetch( ctx.long_state + i + 576, 1, 0 );
aesb_pseudo_round_mut(&ctx.text[AES_BLOCK_SIZE * 0], ctx.aes_ctx->key->exp_data);
aesb_pseudo_round_mut(&ctx.text[AES_BLOCK_SIZE * 1], ctx.aes_ctx->key->exp_data);
aesb_pseudo_round_mut(&ctx.text[AES_BLOCK_SIZE * 2], ctx.aes_ctx->key->exp_data);
aesb_pseudo_round_mut(&ctx.text[AES_BLOCK_SIZE * 3], ctx.aes_ctx->key->exp_data);
aesb_pseudo_round_mut(&ctx.text[AES_BLOCK_SIZE * 4], ctx.aes_ctx->key->exp_data);
aesb_pseudo_round_mut(&ctx.text[AES_BLOCK_SIZE * 5], ctx.aes_ctx->key->exp_data);
aesb_pseudo_round_mut(&ctx.text[AES_BLOCK_SIZE * 6], ctx.aes_ctx->key->exp_data);
aesb_pseudo_round_mut(&ctx.text[AES_BLOCK_SIZE * 7], ctx.aes_ctx->key->exp_data);
memcpy(&ctx.long_state[i], ctx.text, INIT_SIZE_BYTE);
}
xor_blocks_dst(&ctx.state.k[0], &ctx.state.k[32], ctx.a);
xor_blocks_dst(&ctx.state.k[16], &ctx.state.k[48], 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 = e2i(ctx.a);
aesb_single_round(&ctx.long_state[j], ctx.c, ctx.a);
xor_blocks_dst(ctx.c, ctx.b, &ctx.long_state[j]);
if ( cryptonightV7 )
{
uint8_t *lsa = (uint8_t*)&ctx.long_state[((uint64_t *)(ctx.a))[0] & 0x1FFFF0];
const uint8_t tmp = lsa[11];
const uint8_t index = ( ( (tmp >> 3) & 6 ) | (tmp & 1) ) << 1;
lsa[11] = tmp ^ ( ( 0x75310 >> index) & 0x30 );
}
/* Iteration 2 */
mul_sum_xor_dst(ctx.c, ctx.a, &ctx.long_state[e2i(ctx.c)], tweak );
/* Iteration 3 */
j = e2i(ctx.a);
aesb_single_round(&ctx.long_state[j], ctx.b, ctx.a);
xor_blocks_dst(ctx.b, ctx.c, &ctx.long_state[j]);
if ( cryptonightV7 )
{
uint8_t *lsa = (uint8_t*)&ctx.long_state[((uint64_t *)(ctx.a))[0] & 0x1FFFF0];
const uint8_t tmp = lsa[11];
const uint8_t index = ( ( (tmp >> 3) & 6 ) | (tmp & 1) ) << 1;
lsa[11] = tmp ^ ( ( 0x75310 >> index) & 0x30 );
}
/* Iteration 4 */
mul_sum_xor_dst(ctx.b, ctx.a, &ctx.long_state[e2i(ctx.b)], tweak );
}
__builtin_prefetch( ctx.text, 0, 3 );
__builtin_prefetch( ctx.text + 64, 0, 3 );
__builtin_prefetch( ctx.long_state, 1, 0 );
__builtin_prefetch( ctx.long_state + 64, 1, 0 );
__builtin_prefetch( ctx.long_state + 128, 1, 0 );
__builtin_prefetch( ctx.long_state + 192, 1, 0 );
__builtin_prefetch( ctx.long_state + 256, 1, 0 );
__builtin_prefetch( ctx.long_state + 320, 1, 0 );
__builtin_prefetch( ctx.long_state + 384, 1, 0 );
__builtin_prefetch( ctx.long_state + 448, 1, 0 );
memcpy(ctx.text, ctx.state.init, INIT_SIZE_BYTE);
oaes_key_import_data(ctx.aes_ctx, &ctx.state.hs.b[32], AES_KEY_SIZE);
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) {
__builtin_prefetch( ctx.long_state + i + 512, 1, 0 );
__builtin_prefetch( ctx.long_state + i + 576, 1, 0 );
xor_blocks(&ctx.text[0 * AES_BLOCK_SIZE], &ctx.long_state[i + 0 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx.text[0 * AES_BLOCK_SIZE], ctx.aes_ctx->key->exp_data);
xor_blocks(&ctx.text[1 * AES_BLOCK_SIZE], &ctx.long_state[i + 1 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx.text[1 * AES_BLOCK_SIZE], ctx.aes_ctx->key->exp_data);
xor_blocks(&ctx.text[2 * AES_BLOCK_SIZE], &ctx.long_state[i + 2 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx.text[2 * AES_BLOCK_SIZE], ctx.aes_ctx->key->exp_data);
xor_blocks(&ctx.text[3 * AES_BLOCK_SIZE], &ctx.long_state[i + 3 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx.text[3 * AES_BLOCK_SIZE], ctx.aes_ctx->key->exp_data);
xor_blocks(&ctx.text[4 * AES_BLOCK_SIZE], &ctx.long_state[i + 4 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx.text[4 * AES_BLOCK_SIZE], ctx.aes_ctx->key->exp_data);
xor_blocks(&ctx.text[5 * AES_BLOCK_SIZE], &ctx.long_state[i + 5 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx.text[5 * AES_BLOCK_SIZE], ctx.aes_ctx->key->exp_data);
xor_blocks(&ctx.text[6 * AES_BLOCK_SIZE], &ctx.long_state[i + 6 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx.text[6 * AES_BLOCK_SIZE], ctx.aes_ctx->key->exp_data);
xor_blocks(&ctx.text[7 * AES_BLOCK_SIZE], &ctx.long_state[i + 7 * AES_BLOCK_SIZE]);
aesb_pseudo_round_mut(&ctx.text[7 * AES_BLOCK_SIZE], ctx.aes_ctx->key->exp_data);
}
memcpy(ctx.state.init, ctx.text, INIT_SIZE_BYTE);
// hash_permutation(&ctx.state.hs);
keccakf( (uint64_t*)&ctx.state.hs.w, 24 );
/*memcpy(hash, &state, 32);*/
extra_hashes[ctx.state.hs.b[0] & 3](&ctx.state, 200, output);
oaes_free((OAES_CTX **) &ctx.aes_ctx);
}

View File

@@ -1,51 +0,0 @@
#ifndef __CRYPTONIGHT_H_INCLUDED
#define __CRYPTONIGHT_H_INCLUDED
#include <stddef.h>
#include "crypto/oaes_lib.h"
#include "miner.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)
void do_blake_hash(const void* input, size_t len, char* output);
void do_groestl_hash(const void* input, size_t len, char* output);
void do_jh_hash(const void* input, size_t len, char* output);
void do_skein_hash(const void* input, size_t len, char* output);
void cryptonight_hash_ctx(void* output, const void* input, int len);
void keccakf(uint64_t st[25], int rounds);
extern void (* const extra_hashes[4])(const void *, size_t, char *);
int scanhash_cryptonight( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr );
void cryptonight_hash_aes( void *restrict output, const void *input, int len );
extern bool cryptonightV7;
#endif

View File

@@ -179,14 +179,6 @@ int cube_4way_full( cube_4way_context *sp, void *output, int hashbitlen,
sp->rounds = 16; sp->rounds = 16;
sp->pos = 0; sp->pos = 0;
h[ 0] = m512_const1_128( iv[0] );
h[ 1] = m512_const1_128( iv[1] );
h[ 2] = m512_const1_128( iv[2] );
h[ 3] = m512_const1_128( iv[3] );
h[ 4] = m512_const1_128( iv[4] );
h[ 5] = m512_const1_128( iv[5] );
h[ 6] = m512_const1_128( iv[6] );
h[ 7] = m512_const1_128( iv[7] );
h[ 0] = m512_const1_128( iv[0] ); h[ 0] = m512_const1_128( iv[0] );
h[ 1] = m512_const1_128( iv[1] ); h[ 1] = m512_const1_128( iv[1] );
h[ 2] = m512_const1_128( iv[2] ); h[ 2] = m512_const1_128( iv[2] );
@@ -447,14 +439,6 @@ int cube_2way_full( cube_2way_context *sp, void *output, int hashbitlen,
sp->rounds = 16; sp->rounds = 16;
sp->pos = 0; sp->pos = 0;
h[ 0] = m256_const1_128( iv[0] );
h[ 1] = m256_const1_128( iv[1] );
h[ 2] = m256_const1_128( iv[2] );
h[ 3] = m256_const1_128( iv[3] );
h[ 4] = m256_const1_128( iv[4] );
h[ 5] = m256_const1_128( iv[5] );
h[ 6] = m256_const1_128( iv[6] );
h[ 7] = m256_const1_128( iv[7] );
h[ 0] = m256_const1_128( iv[0] ); h[ 0] = m256_const1_128( iv[0] );
h[ 1] = m256_const1_128( iv[1] ); h[ 1] = m256_const1_128( iv[1] );
h[ 2] = m256_const1_128( iv[2] ); h[ 2] = m256_const1_128( iv[2] );

View File

@@ -28,6 +28,27 @@ int cube_4way_update_close( cube_4way_context *sp, void *output,
int cube_4way_full( cube_4way_context *sp, void *output, int hashbitlen, int cube_4way_full( cube_4way_context *sp, void *output, int hashbitlen,
const void *data, size_t size ); const void *data, size_t size );
int cube_4x256_full( cube_4way_context *sp, void *output, int hashbitlen,
const void *data, size_t size );
#define cube512_4way_init( sp ) cube_4way_update( sp, 512 )
#define cube512_4way_update cube_4way_update
#define cube512_4way_update_close cube_4way_update
#define cube512_4way_close cube_4way_update
#define cube512_4way_full( sp, output, data, size ) \
cube_4way_full( sp, output, 512, data, size )
#define cube512_4x256_full( sp, output, data, size ) \
cube_4x256_full( sp, output, 512, data, size )
#define cube256_4way_init( sp ) cube_4way_update( sp, 256 )
#define cube256_4way_update cube_4way_update
#define cube256_4way_update_close cube_4way_update
#define cube256_4way_close cube_4way_update
#define cube256_4way_full( sp, output, data, size ) \
cube_4way_full( sp, output, 256, data, size )
#define cube256_4x256_full( sp, output, data, size ) \
cube_4x256_full( sp, output, 256, data, size )
#endif #endif
// 2x128, 2 way parallel SSE2 // 2x128, 2 way parallel SSE2

View File

@@ -230,11 +230,10 @@ int cubehashDigest( cubehashParam *sp, byte *digest )
// pos is zero for 64 byte data, 1 for 80 byte data. // pos is zero for 64 byte data, 1 for 80 byte data.
sp->x[ sp->pos ] = _mm_xor_si128( sp->x[ sp->pos ], sp->x[ sp->pos ] = _mm_xor_si128( sp->x[ sp->pos ],
_mm_set_epi8( 0,0,0,0, 0,0,0,0, m128_const_64( 0, 0x80 ) );
0,0,0,0, 0,0,0,0x80 ) );
transform( sp ); transform( sp );
sp->x[7] = _mm_xor_si128( sp->x[7], _mm_set_epi32( 1,0,0,0 ) ); sp->x[7] = _mm_xor_si128( sp->x[7], m128_const_64( 0x100000000, 0 ) );
transform( sp ); transform( sp );
transform( sp ); transform( sp );
transform( sp ); transform( sp );
@@ -276,11 +275,89 @@ int cubehashUpdateDigest( cubehashParam *sp, byte *digest,
// pos is zero for 64 byte data, 1 for 80 byte data. // pos is zero for 64 byte data, 1 for 80 byte data.
sp->x[ sp->pos ] = _mm_xor_si128( sp->x[ sp->pos ], sp->x[ sp->pos ] = _mm_xor_si128( sp->x[ sp->pos ],
_mm_set_epi8( 0,0,0,0, 0,0,0,0, m128_const_64( 0, 0x80 ) );
0,0,0,0, 0,0,0,0x80 ) );
transform( sp ); transform( sp );
sp->x[7] = _mm_xor_si128( sp->x[7], _mm_set_epi32( 1,0,0,0 ) ); sp->x[7] = _mm_xor_si128( sp->x[7], m128_const_64( 0x100000000, 0 ) );
transform( sp );
transform( sp );
transform( sp );
transform( sp );
transform( sp );
transform( sp );
transform( sp );
transform( sp );
transform( sp );
transform( sp );
for ( i = 0; i < sp->hashlen; i++ )
hash[i] = sp->x[i];
return SUCCESS;
}
int cubehash_full( cubehashParam *sp, byte *digest, int hashbitlen,
const byte *data, size_t size )
{
__m128i *x = (__m128i*)sp->x;
sp->hashlen = hashbitlen/128;
sp->blocksize = 32/16;
sp->rounds = 16;
sp->pos = 0;
if ( hashbitlen == 512 )
{
x[0] = m128_const_64( 0x4167D83E2D538B8B, 0x50F494D42AEA2A61 );
x[1] = m128_const_64( 0x50AC5695CC39968E, 0xC701CF8C3FEE2313 );
x[2] = m128_const_64( 0x825B453797CF0BEF, 0xA647A8B34D42C787 );
x[3] = m128_const_64( 0xA23911AED0E5CD33, 0xF22090C4EEF864D2 );
x[4] = m128_const_64( 0xB64445321B017BEF, 0x148FE485FCD398D9 );
x[5] = m128_const_64( 0x0DBADEA991FA7934, 0x2FF5781C6A536159 );
x[6] = m128_const_64( 0xBC796576B1C62456, 0xA5A70E75D65C8A2B );
x[7] = m128_const_64( 0xD43E3B447795D246, 0xE7989AF11921C8F7 );
}
else
{
x[0] = m128_const_64( 0x35481EAE63117E71, 0xCCD6F29FEA2BD4B4 );
x[1] = m128_const_64( 0xF4CC12BE7E624131, 0xE5D94E6322512D5B );
x[2] = m128_const_64( 0x3361DA8CD0720C35, 0x42AF2070C2D0B696 );
x[3] = m128_const_64( 0x40E5FBAB4680AC00, 0x8EF8AD8328CCECA4 );
x[4] = m128_const_64( 0xF0B266796C859D41, 0x6107FBD5D89041C3 );
x[5] = m128_const_64( 0x93CB628565C892FD, 0x5FA2560309392549 );
x[6] = m128_const_64( 0x85254725774ABFDD, 0x9E4B4E602AF2B5AE );
x[7] = m128_const_64( 0xD6032C0A9CDAF8AF, 0x4AB6AAD615815AEB );
}
const int len = size / 16;
const __m128i* in = (__m128i*)data;
__m128i* hash = (__m128i*)digest;
int i;
// It is assumed data is aligned to 256 bits and is a multiple of 128 bits.
// Current usage sata is either 64 or 80 bytes.
for ( i = 0; i < len; i++ )
{
sp->x[ sp->pos ] = _mm_xor_si128( sp->x[ sp->pos ], in[i] );
sp->pos++;
if ( sp->pos == sp->blocksize )
{
transform( sp );
sp->pos = 0;
}
}
// pos is zero for 64 byte data, 1 for 80 byte data.
sp->x[ sp->pos ] = _mm_xor_si128( sp->x[ sp->pos ],
m128_const_64( 0, 0x80 ) );
transform( sp );
sp->x[7] = _mm_xor_si128( sp->x[7], m128_const_64( 0x100000000, 0 ) );
transform( sp ); transform( sp );
transform( sp ); transform( sp );

View File

@@ -19,7 +19,7 @@ struct _cubehashParam
int rounds; int rounds;
int blocksize; // __m128i int blocksize; // __m128i
int pos; // number of __m128i read into x from current block int pos; // number of __m128i read into x from current block
__m128i _ALIGN(256) x[8]; // aligned for __m256i __m128i _ALIGN(64) x[8]; // aligned for __m256i
}; };
typedef struct _cubehashParam cubehashParam; typedef struct _cubehashParam cubehashParam;
@@ -39,6 +39,9 @@ int cubehashDigest(cubehashParam* sp, byte *digest);
int cubehashUpdateDigest( cubehashParam *sp, byte *digest, const byte *data, int cubehashUpdateDigest( cubehashParam *sp, byte *digest, const byte *data,
size_t size ); size_t size );
int cubehash_full( cubehashParam* sp, byte *digest, int hashbitlen,
const byte *data, size_t size );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -22,18 +22,26 @@ typedef struct
} echo_4way_context __attribute__ ((aligned (64))); } echo_4way_context __attribute__ ((aligned (64)));
int echo_4way_init( echo_4way_context *state, int hashbitlen ); int echo_4way_init( echo_4way_context *state, int hashbitlen );
#define echo512_4way_init( state ) echo_4way_init( state, 512 )
#define echo256_4way_init( state ) echo_4way_init( state, 256 )
int echo_4way_update( echo_4way_context *state, const void *data, int echo_4way_update( echo_4way_context *state, const void *data,
unsigned int databitlen); unsigned int databitlen);
#define echo512_4way_update echo_4way_update
int echo_close( echo_4way_context *state, void *hashval ); int echo_close( echo_4way_context *state, void *hashval );
#define echo512_4way_close echo_4way_close
int echo_4way_update_close( echo_4way_context *state, void *hashval, int echo_4way_update_close( echo_4way_context *state, void *hashval,
const void *data, int databitlen ); const void *data, int databitlen );
#define echo512_4way_update_close echo_4way_update_close
int echo_4way_full( echo_4way_context *ctx, void *hashval, int nHashSize, int echo_4way_full( echo_4way_context *ctx, void *hashval, int nHashSize,
const void *data, int datalen ); const void *data, int datalen );
#define echo512_4way_full( state, hashval, data, datalen ) \
echo_4way_full( state, hashval, 512, data, datalen )
#define echo256_4way_full( state, hashval, data, datalen ) \
echo_4way_full( state, hashval, 256, data, datalen )
#endif #endif
#endif #endif

View File

@@ -36,6 +36,8 @@
#include "sph_echo.h" #include "sph_echo.h"
#if !defined(__AES__)
#ifdef __cplusplus #ifdef __cplusplus
extern "C"{ extern "C"{
#endif #endif
@@ -1028,4 +1030,5 @@ sph_echo512_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif // !AES

View File

@@ -36,6 +36,8 @@
#ifndef SPH_ECHO_H__ #ifndef SPH_ECHO_H__
#define SPH_ECHO_H__ #define SPH_ECHO_H__
#if !defined(__AES__)
#ifdef __cplusplus #ifdef __cplusplus
extern "C"{ extern "C"{
#endif #endif
@@ -316,5 +318,5 @@ void sph_echo512_addbits_and_close(
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif // !AES
#endif #endif

567
algo/fugue/fugue-aesni.c Normal file
View File

@@ -0,0 +1,567 @@
/*
* file : fugue_vperm.c
* version : 1.0.208
* date : 14.12.2010
*
* - vperm and aes_ni implementations of hash function Fugue
* - implements NIST hash api
* - assumes that message lenght is multiple of 8-bits
* - _FUGUE_VPERM_ must be defined if compiling with ../main.c
* - default version is vperm, define AES_NI for aes_ni version
*
* Cagdas Calik
* ccalik@metu.edu.tr
* Institute of Applied Mathematics, Middle East Technical University, Turkey.
*
*/
#if defined(__AES__)
#include <x86intrin.h>
#include <memory.h>
#include "fugue-aesni.h"
MYALIGN const unsigned long long _supermix1a[] = {0x0202010807020100, 0x0a05000f06010c0b};
MYALIGN const unsigned long long _supermix1b[] = {0x0b0d080703060504, 0x0e0a090c050e0f0a};
MYALIGN const unsigned long long _supermix1c[] = {0x0402060c070d0003, 0x090a060580808080};
MYALIGN const unsigned long long _supermix1d[] = {0x808080800f0e0d0c, 0x0f0e0d0c80808080};
MYALIGN const unsigned long long _supermix2a[] = {0x07020d0880808080, 0x0b06010c050e0f0a};
MYALIGN const unsigned long long _supermix4a[] = {0x000f0a050c0b0601, 0x0302020404030e09};
MYALIGN const unsigned long long _supermix4b[] = {0x07020d08080e0d0d, 0x07070908050e0f0a};
MYALIGN const unsigned long long _supermix4c[] = {0x0706050403020000, 0x0302000007060504};
MYALIGN const unsigned long long _supermix7a[] = {0x010c0b060d080702, 0x0904030e03000104};
MYALIGN const unsigned long long _supermix7b[] = {0x8080808080808080, 0x0504070605040f06};
MYALIGN const unsigned long long _k_n[] = {0x4E4E4E4E4E4E4E4E, 0x1B1B1B1B0E0E0E0E};
MYALIGN const unsigned int _maskd3n[] = {0xffffffff, 0xffffffff, 0xffffffff, 0x00000000};
MYALIGN const unsigned char _shift_one_mask[] = {7, 4, 5, 6, 11, 8, 9, 10, 15, 12, 13, 14, 3, 0, 1, 2};
MYALIGN const unsigned char _shift_four_mask[] = {13, 14, 15, 12, 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8};
MYALIGN const unsigned char _shift_seven_mask[] = {10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6, 7, 4, 5};
MYALIGN const unsigned char _aes_shift_rows[] = {0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11};
MYALIGN const unsigned int _inv_shift_rows[] = {0x070a0d00, 0x0b0e0104, 0x0f020508, 0x0306090c};
MYALIGN const unsigned int _zero[] = {0x00000000, 0x00000000, 0x00000000, 0x00000000};
MYALIGN const unsigned int _mul2mask[] = {0x1b1b0000, 0x00000000, 0x00000000, 0x00000000};
MYALIGN const unsigned int _mul4mask[] = {0x2d361b00, 0x00000000, 0x00000000, 0x00000000};
MYALIGN const unsigned int _lsbmask2[] = {0x03030303, 0x03030303, 0x03030303, 0x03030303};
MYALIGN const unsigned int _IV512[] = {
0x00000000, 0x00000000, 0x7ea50788, 0x00000000,
0x75af16e6, 0xdbe4d3c5, 0x27b09aac, 0x00000000,
0x17f115d9, 0x54cceeb6, 0x0b02e806, 0x00000000,
0xd1ef924a, 0xc9e2c6aa, 0x9813b2dd, 0x00000000,
0x3858e6ca, 0x3f207f43, 0xe778ea25, 0x00000000,
0xd6dd1f95, 0x1dd16eda, 0x67353ee1, 0x00000000};
#if defined(__SSE4_1__)
#define PACK_S0(s0, s1, t1)\
s0 = _mm_castps_si128(_mm_insert_ps(_mm_castsi128_ps(s0), _mm_castsi128_ps(s1), 0x30))
#define UNPACK_S0(s0, s1, t1)\
s1 = _mm_castps_si128(_mm_insert_ps(_mm_castsi128_ps(s1), _mm_castsi128_ps(s0), 0xc0));\
s0 = _mm_and_si128(s0, M128(_maskd3n))
#define CMIX(s1, s2, r1, r2, t1, t2)\
t1 = s1;\
t1 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(t1), _mm_castsi128_ps(s2), _MM_SHUFFLE(3, 0, 2, 1)));\
r1 = _mm_xor_si128(r1, t1);\
r2 = _mm_xor_si128(r2, t1);
#else // SSE2
#define PACK_S0(s0, s1, t1)\
t1 = _mm_shuffle_epi32(s1, _MM_SHUFFLE(0, 3, 3, 3));\
s0 = _mm_xor_si128(s0, t1);
#define UNPACK_S0(s0, s1, t1)\
t1 = _mm_shuffle_epi32(s0, _MM_SHUFFLE(3, 3, 3, 3));\
s1 = _mm_castps_si128(_mm_move_ss(_mm_castsi128_ps(s1), _mm_castsi128_ps(t1)));\
s0 = _mm_and_si128(s0, M128(_maskd3n))
#define CMIX(s1, s2, r1, r2, t1, t2)\
t1 = _mm_shuffle_epi32(s1, 0xf9);\
t2 = _mm_shuffle_epi32(s2, 0xcf);\
t1 = _mm_xor_si128(t1, t2);\
r1 = _mm_xor_si128(r1, t1);\
r2 = _mm_xor_si128(r2, t1)
#endif
#define TIX256(msg, s10, s8, s24, s0, t1, t2, t3)\
t1 = _mm_shuffle_epi32(s0, _MM_SHUFFLE(3, 3, 0, 3));\
s10 = _mm_xor_si128(s10, t1);\
t1 = _mm_castps_si128(_mm_load_ss((float*)msg));\
s0 = _mm_castps_si128(_mm_move_ss(_mm_castsi128_ps(s0), _mm_castsi128_ps(t1)));\
t1 = _mm_slli_si128(t1, 8);\
s8 = _mm_xor_si128(s8, t1);\
t1 = _mm_shuffle_epi32(s24, _MM_SHUFFLE(3, 3, 0, 3));\
s0 = _mm_xor_si128(s0, t1)
#define TIX384(msg, s16, s8, s27, s30, s0, s4, t1, t2, t3)\
t1 = _mm_shuffle_epi32(s0, _MM_SHUFFLE(3, 3, 0, 3));\
s16 = _mm_xor_si128(s16, t1);\
t1 = _mm_castps_si128(_mm_load_ss((float*)msg));\
s0 = _mm_castps_si128(_mm_move_ss(_mm_castsi128_ps(s0), _mm_castsi128_ps(t1)));\
t1 = _mm_slli_si128(t1, 8);\
s8 = _mm_xor_si128(s8, t1);\
t1 = _mm_shuffle_epi32(s27, _MM_SHUFFLE(3, 3, 0, 3));\
s0 = _mm_xor_si128(s0, t1);\
t1 = _mm_shuffle_epi32(s30, _MM_SHUFFLE(3, 3, 0, 3));\
s4 = _mm_xor_si128(s4, t1)
#define TIX512(msg, s22, s8, s24, s27, s30, s0, s4, s7, t1, t2, t3)\
t1 = _mm_shuffle_epi32(s0, _MM_SHUFFLE(3, 3, 0, 3));\
s22 = _mm_xor_si128(s22, t1);\
t1 = _mm_castps_si128(_mm_load_ss((float*)msg));\
s0 = _mm_castps_si128(_mm_move_ss(_mm_castsi128_ps(s0), _mm_castsi128_ps(t1)));\
t1 = _mm_slli_si128(t1, 8);\
s8 = _mm_xor_si128(s8, t1);\
t1 = _mm_shuffle_epi32(s24, _MM_SHUFFLE(3, 3, 0, 3));\
s0 = _mm_xor_si128(s0, t1);\
t1 = _mm_shuffle_epi32(s27, _MM_SHUFFLE(3, 3, 0, 3));\
s4 = _mm_xor_si128(s4, t1);\
t1 = _mm_shuffle_epi32(s30, _MM_SHUFFLE(3, 3, 0, 3));\
s7 = _mm_xor_si128(s7, t1)
#define PRESUPERMIX(x, t1, s1, s2, t2)\
s1 = x;\
s2 = _mm_add_epi8(x, x);\
t2 = _mm_add_epi8(s2, s2);\
t1 = _mm_srli_epi16(x, 6);\
t1 = _mm_and_si128(t1, M128(_lsbmask2));\
s2 = _mm_xor_si128(s2, _mm_shuffle_epi8(M128(_mul2mask), t1));\
x = _mm_xor_si128(t2, _mm_shuffle_epi8(M128(_mul4mask), t1))
#define SUBSTITUTE(r0, _t1, _t2, _t3, _t0)\
_t2 = _mm_shuffle_epi8(r0, M128(_inv_shift_rows));\
_t2 = _mm_aesenclast_si128(_t2, M128(_zero))
#define SUPERMIX(t0, t1, t2, t3, t4)\
PRESUPERMIX(t0, t1, t2, t3, t4);\
POSTSUPERMIX(t0, t1, t2, t3, t4)
#define POSTSUPERMIX(t0, t1, t2, t3, t4)\
t1 = t2;\
t1 = _mm_shuffle_epi8(t1, M128(_supermix1b));\
t4 = t1;\
t1 = _mm_shuffle_epi8(t1, M128(_supermix1c));\
t4 = _mm_xor_si128(t4, t1);\
t1 = t4;\
t1 = _mm_shuffle_epi8(t1, M128(_supermix1d));\
t4 = _mm_xor_si128(t4, t1);\
t1 = t2;\
t1 = _mm_shuffle_epi8(t1, M128(_supermix1a));\
t4 = _mm_xor_si128(t4, t1);\
t2 = _mm_xor_si128(t2, t3);\
t2 = _mm_xor_si128(t2, t0);\
t2 = _mm_shuffle_epi8(t2, M128(_supermix7a));\
t4 = _mm_xor_si128(t4, t2);\
t2 = _mm_shuffle_epi8(t2, M128(_supermix7b));\
t4 = _mm_xor_si128(t4, t2);\
t3 = _mm_shuffle_epi8(t3, M128(_supermix2a));\
t1 = t0;\
t1 = _mm_shuffle_epi8(t1, M128(_supermix4a));\
t4 = _mm_xor_si128(t4, t1);\
t0 = _mm_shuffle_epi8(t0, M128(_supermix4b));\
t0 = _mm_xor_si128(t0, t3);\
t4 = _mm_xor_si128(t4, t0);\
t0 = _mm_shuffle_epi8(t0, M128(_supermix4c));\
t4 = _mm_xor_si128(t4, t0)
#define SUBROUND512_3(r1a, r1b, r1c, r1d, r2a, r2b, r2c, r2d, r3a, r3b, r3c, r3d)\
CMIX(r1a, r1b, r1c, r1d, _t0, _t1);\
PACK_S0(r1c, r1a, _t0);\
SUBSTITUTE(r1c, _t1, _t2, _t3, _t0);\
SUPERMIX(_t2, _t3, _t0, _t1, r1c);\
_t0 = _mm_shuffle_epi32(r1c, 0x39);\
r2c = _mm_xor_si128(r2c, _t0);\
_t0 = _mm_and_si128(_t0, M128(_maskd3n));\
r2d = _mm_xor_si128(r2d, _t0);\
UNPACK_S0(r1c, r1a, _t3);\
SUBSTITUTE(r2c, _t1, _t2, _t3, _t0);\
SUPERMIX(_t2, _t3, _t0, _t1, r2c);\
_t0 = _mm_shuffle_epi32(r2c, 0x39);\
r3c = _mm_xor_si128(r3c, _t0);\
_t0 = _mm_and_si128(_t0, M128(_maskd3n));\
r3d = _mm_xor_si128(r3d, _t0);\
UNPACK_S0(r2c, r2a, _t3);\
SUBSTITUTE(r3c, _t1, _t2, _t3, _t0);\
SUPERMIX(_t2, _t3, _t0, _t1, r3c);\
UNPACK_S0(r3c, r3a, _t3)
#define SUBROUND512_4(r1a, r1b, r1c, r1d, r2a, r2b, r2c, r2d, r3a, r3b, r3c, r3d, r4a, r4b, r4c, r4d)\
CMIX(r1a, r1b, r1c, r1d, _t0, _t1);\
PACK_S0(r1c, r1a, _t0);\
SUBSTITUTE(r1c, _t1, _t2, _t3, _t0);\
SUPERMIX(_t2, _t3, _t0, _t1, r1c);\
_t0 = _mm_shuffle_epi32(r1c, 0x39);\
r2c = _mm_xor_si128(r2c, _t0);\
_t0 = _mm_and_si128(_t0, M128(_maskd3n));\
r2d = _mm_xor_si128(r2d, _t0);\
UNPACK_S0(r1c, r1a, _t3);\
SUBSTITUTE(r2c, _t1, _t2, _t3, _t0);\
SUPERMIX(_t2, _t3, _t0, _t1, r2c);\
_t0 = _mm_shuffle_epi32(r2c, 0x39);\
r3c = _mm_xor_si128(r3c, _t0);\
_t0 = _mm_and_si128(_t0, M128(_maskd3n));\
r3d = _mm_xor_si128(r3d, _t0);\
UNPACK_S0(r2c, r2a, _t3);\
SUBSTITUTE(r3c, _t1, _t2, _t3, _t0);\
SUPERMIX(_t2, _t3, _t0, _t1, r3c);\
_t0 = _mm_shuffle_epi32(r3c, 0x39);\
r4c = _mm_xor_si128(r4c, _t0);\
_t0 = _mm_and_si128(_t0, M128(_maskd3n));\
r4d = _mm_xor_si128(r4d, _t0);\
UNPACK_S0(r3c, r3a, _t3);\
SUBSTITUTE(r4c, _t1, _t2, _t3, _t0);\
SUPERMIX(_t2, _t3, _t0, _t1, r4c);\
UNPACK_S0(r4c, r4a, _t3)
#define LOADCOLUMN(x, s, a)\
block[0] = col[(base + a + 0) % s];\
block[1] = col[(base + a + 1) % s];\
block[2] = col[(base + a + 2) % s];\
block[3] = col[(base + a + 3) % s];\
x = _mm_load_si128((__m128i*)block)
#define STORECOLUMN(x, s)\
_mm_store_si128((__m128i*)block, x);\
col[(base + 0) % s] = block[0];\
col[(base + 1) % s] = block[1];\
col[(base + 2) % s] = block[2];\
col[(base + 3) % s] = block[3]
void Compress512(hashState_fugue *ctx, const unsigned char *pmsg, unsigned int uBlockCount)
{
__m128i _t0, _t1, _t2, _t3;
switch(ctx->base)
{
case 1:
TIX512( pmsg, ctx->state[3], ctx->state[10], ctx->state[4],
ctx->state[5], ctx->state[ 6], ctx->state[8],
ctx->state[9], ctx->state[10], _t0, _t1, _t2 );
SUBROUND512_4( ctx->state[8], ctx->state[9], ctx->state[7],
ctx->state[1], ctx->state[7], ctx->state[8],
ctx->state[6], ctx->state[0], ctx->state[6],
ctx->state[7], ctx->state[5], ctx->state[11],
ctx->state[5], ctx->state[6], ctx->state[4],
ctx->state[10] );
ctx->base++;
pmsg += 4;
uBlockCount--;
if( uBlockCount == 0 ) break;
case 2:
TIX512( pmsg, ctx->state[11], ctx->state[6], ctx->state[0],
ctx->state[ 1], ctx->state[2], ctx->state[4],
ctx->state[ 5], ctx->state[6], _t0, _t1, _t2);
SUBROUND512_4( ctx->state[4], ctx->state[5], ctx->state[3],
ctx->state[9], ctx->state[3], ctx->state[4],
ctx->state[2], ctx->state[8], ctx->state[2],
ctx->state[3], ctx->state[1], ctx->state[7],
ctx->state[1], ctx->state[2], ctx->state[0],
ctx->state[6]);
ctx->base = 0;
pmsg += 4;
uBlockCount--;
break;
}
while( uBlockCount > 0 )
{
TIX512( pmsg, ctx->state[ 7], ctx->state[2], ctx->state[8], ctx->state[9],
ctx->state[10], ctx->state[0], ctx->state[1], ctx->state[2],
_t0, _t1, _t2 );
SUBROUND512_4( ctx->state[0], ctx->state[1], ctx->state[11],
ctx->state[5], ctx->state[11], ctx->state[0],
ctx->state[10], ctx->state[4], ctx->state[10],
ctx->state[11], ctx->state[9], ctx->state[3],
ctx->state[9], ctx->state[10], ctx->state[8],
ctx->state[2] );
ctx->base++;
pmsg += 4;
uBlockCount--;
if( uBlockCount == 0 ) break;
TIX512( pmsg, ctx->state[3], ctx->state[10], ctx->state[4], ctx->state[5],
ctx->state[6], ctx->state[8], ctx->state[9], ctx->state[10],
_t0, _t1, _t2 );
SUBROUND512_4( ctx->state[8], ctx->state[9], ctx->state[7], ctx->state[1], ctx->state[7], ctx->state[8], ctx->state[6], ctx->state[0],
ctx->state[6], ctx->state[7], ctx->state[5], ctx->state[11],
ctx->state[5], ctx->state[6, ctx->state[4], ctx->state[10]);
ctx->base++;
pmsg += 4;
uBlockCount--;
if( uBlockCount == 0 ) break;
TIX512( pmsg, ctx->state[11], ctx->state[6], ctx->state[0], ctx->state[1],
ctx->state[2], ctx->state[4], ctx->state[5], ctx->state[6],
_t0, _t1, _t2);
SUBROUND512_4( ctx->state[4], ctx->state[5], ctx->state[3], ctx->state[9],
ctx->state[3], ctx->state[4], ctx->state[2], ctx->state[8],
ctx->state[2], ctx->state[3], ctx->state[1], ctx->state[7],
ctx->state[1], ctx->state[2], ctx->state[0], ctx->state[6]);
ctx->base = 0;
pmsg += 4;
uBlockCount--;
}
}
void Final512(hashState_fugue *ctx, BitSequence *hashval)
{
unsigned int block[4] __attribute__ ((aligned (32)));
unsigned int col[36] __attribute__ ((aligned (16)));
unsigned int i, base;
__m128i r0, _t0, _t1, _t2, _t3;
for(i = 0; i < 12; i++)
{
_mm_store_si128((__m128i*)block, ctx->state[i]);
col[3 * i + 0] = block[0];
col[3 * i + 1] = block[1];
col[3 * i + 2] = block[2];
}
base = (36 - (12 * ctx->base)) % 36;
for(i = 0; i < 32; i++)
{
// ROR3
base = (base + 33) % 36;
// CMIX
col[(base + 0) % 36] ^= col[(base + 4) % 36];
col[(base + 1) % 36] ^= col[(base + 5) % 36];
col[(base + 2) % 36] ^= col[(base + 6) % 36];
col[(base + 18) % 36] ^= col[(base + 4) % 36];
col[(base + 19) % 36] ^= col[(base + 5) % 36];
col[(base + 20) % 36] ^= col[(base + 6) % 36];
// SMIX
LOADCOLUMN(r0, 36, 0);
SUBSTITUTE(r0, _t1, _t2, _t3, _t0);
SUPERMIX(_t2, _t3, _t0, _t1, r0);
STORECOLUMN(r0, 36);
}
for(i = 0; i < 13; i++)
{
// S4 += S0; S9 += S0; S18 += S0; S27 += S0;
col[(base + 4) % 36] ^= col[(base + 0) % 36];
col[(base + 9) % 36] ^= col[(base + 0) % 36];
col[(base + 18) % 36] ^= col[(base + 0) % 36];
col[(base + 27) % 36] ^= col[(base + 0) % 36];
// ROR9
base = (base + 27) % 36;
// SMIX
LOADCOLUMN(r0, 36, 0);
SUBSTITUTE(r0, _t1, _t2, _t3, _t0);
SUPERMIX(_t2, _t3, _t0, _t1, r0);
STORECOLUMN(r0, 36);
// S4 += S0; S10 += S0; S18 += S0; S27 += S0;
col[(base + 4) % 36] ^= col[(base + 0) % 36];
col[(base + 10) % 36] ^= col[(base + 0) % 36];
col[(base + 18) % 36] ^= col[(base + 0) % 36];
col[(base + 27) % 36] ^= col[(base + 0) % 36];
// ROR9
base = (base + 27) % 36;
// SMIX
LOADCOLUMN(r0, 36, 0);
SUBSTITUTE(r0, _t1, _t2, _t3, _t0);
SUPERMIX(_t2, _t3, _t0, _t1, r0);
STORECOLUMN(r0, 36);
// S4 += S0; S10 += S0; S19 += S0; S27 += S0;
col[(base + 4) % 36] ^= col[(base + 0) % 36];
col[(base + 10) % 36] ^= col[(base + 0) % 36];
col[(base + 19) % 36] ^= col[(base + 0) % 36];
col[(base + 27) % 36] ^= col[(base + 0) % 36];
// ROR9
base = (base + 27) % 36;
// SMIX
LOADCOLUMN(r0, 36, 0);
SUBSTITUTE(r0, _t1, _t2, _t3, _t0);
SUPERMIX(_t2, _t3, _t0, _t1, r0);
STORECOLUMN(r0, 36);
// S4 += S0; S10 += S0; S19 += S0; S28 += S0;
col[(base + 4) % 36] ^= col[(base + 0) % 36];
col[(base + 10) % 36] ^= col[(base + 0) % 36];
col[(base + 19) % 36] ^= col[(base + 0) % 36];
col[(base + 28) % 36] ^= col[(base + 0) % 36];
// ROR8
base = (base + 28) % 36;
// SMIX
LOADCOLUMN(r0, 36, 0);
SUBSTITUTE(r0, _t1, _t2, _t3, _t0);
SUPERMIX(_t2, _t3, _t0, _t1, r0);
STORECOLUMN(r0, 36);
}
// S4 += S0; S9 += S0; S18 += S0; S27 += S0;
col[(base + 4) % 36] ^= col[(base + 0) % 36];
col[(base + 9) % 36] ^= col[(base + 0) % 36];
col[(base + 18) % 36] ^= col[(base + 0) % 36];
col[(base + 27) % 36] ^= col[(base + 0) % 36];
// Transform to the standard basis and store output; S1 || S2 || S3 || S4
LOADCOLUMN(r0, 36, 1);
_mm_store_si128((__m128i*)hashval, r0);
// Transform to the standard basis and store output; S9 || S10 || S11 || S12
LOADCOLUMN(r0, 36, 9);
_mm_store_si128((__m128i*)hashval + 1, r0);
// Transform to the standard basis and store output; S18 || S19 || S20 || S21
LOADCOLUMN(r0, 36, 18);
_mm_store_si128((__m128i*)hashval + 2, r0);
// Transform to the standard basis and store output; S27 || S28 || S29 || S30
LOADCOLUMN(r0, 36, 27);
_mm_store_si128((__m128i*)hashval + 3, r0);
}
HashReturn fugue512_Init(hashState_fugue *ctx, int nHashSize)
{
int i;
ctx->processed_bits = 0;
ctx->uBufferBytes = 0;
ctx->base = 0;
ctx->uHashSize = 512;
ctx->uBlockLength = 4;
for(i = 0; i < 6; i++)
ctx->state[i] = _mm_setzero_si128();
ctx->state[6] = _mm_load_si128((__m128i*)_IV512 + 0);
ctx->state[7] = _mm_load_si128((__m128i*)_IV512 + 1);
ctx->state[8] = _mm_load_si128((__m128i*)_IV512 + 2);
ctx->state[9] = _mm_load_si128((__m128i*)_IV512 + 3);
ctx->state[10] = _mm_load_si128((__m128i*)_IV512 + 4);
ctx->state[11] = _mm_load_si128((__m128i*)_IV512 + 5);
return SUCCESS;
}
HashReturn fugue512_Update(hashState_fugue *state, const void *data, DataLength databitlen)
{
unsigned int uByteLength, uBlockCount, uRemainingBytes;
uByteLength = (unsigned int)(databitlen / 8);
if(state->uBufferBytes + uByteLength >= state->uBlockLength)
{
if(state->uBufferBytes != 0)
{
// Fill the buffer
memcpy(state->buffer + state->uBufferBytes, (void*)data, state->uBlockLength - state->uBufferBytes);
// Process the buffer
Compress512(state, state->buffer, 1);
state->processed_bits += state->uBlockLength * 8;
data += state->uBlockLength - state->uBufferBytes;
uByteLength -= state->uBlockLength - state->uBufferBytes;
}
// buffer now does not contain any unprocessed bytes
uBlockCount = uByteLength / state->uBlockLength;
uRemainingBytes = uByteLength % state->uBlockLength;
if(uBlockCount > 0)
{
Compress512(state, data, uBlockCount);
state->processed_bits += uBlockCount * state->uBlockLength * 8;
data += uBlockCount * state->uBlockLength;
}
if(uRemainingBytes > 0)
{
memcpy(state->buffer, (void*)data, uRemainingBytes);
}
state->uBufferBytes = uRemainingBytes;
}
else
{
memcpy(state->buffer + state->uBufferBytes, (void*)data, uByteLength);
state->uBufferBytes += uByteLength;
}
return SUCCESS;
}
HashReturn fugue512_Final(hashState_fugue *state, void *hashval)
{
unsigned int i;
BitSequence lengthbuf[8] __attribute__((aligned(64)));
// Update message bit count
state->processed_bits += state->uBufferBytes * 8;
// Pad the remaining buffer bytes with zero
if(state->uBufferBytes != 0)
{
if ( state->uBufferBytes != state->uBlockLength)
memset(state->buffer + state->uBufferBytes, 0, state->uBlockLength - state->uBufferBytes);
Compress512(state, state->buffer, 1);
}
// Last two blocks are message length in bits
for(i = 0; i < 8; i++)
lengthbuf[i] = ((state->processed_bits) >> (8 * (7 - i))) & 0xff;
// Process the last two blocks
Compress512(state, lengthbuf, 2);
// Finalization
Final512(state, hashval);
return SUCCESS;
}
HashReturn fugue512_full(hashState_fugue *hs, void *hashval, const void *data, DataLength databitlen)
{
fugue512_Init(hs, 512);
fugue512_Update(hs, data, databitlen*8);
fugue512_Final(hs, hashval);
return SUCCESS;
}
#endif // AES

46
algo/fugue/fugue-aesni.h Normal file
View File

@@ -0,0 +1,46 @@
/*
* file : hash_api.h
* version : 1.0.208
* date : 14.12.2010
*
* Fugue vperm implementation Hash API
*
* Cagdas Calik
* ccalik@metu.edu.tr
* Institute of Applied Mathematics, Middle East Technical University, Turkey.
*
*/
#ifndef FUGUE_HASH_API_H
#define FUGUE_HASH_API_H
#if defined(__AES__)
#include "algo/sha/sha3_common.h"
#include <x86intrin.h>
typedef struct
{
__m128i state[12];
unsigned int base;
unsigned int uHashSize;
unsigned int uBlockLength;
unsigned int uBufferBytes;
DataLength processed_bits;
BitSequence buffer[4];
} hashState_fugue __attribute__ ((aligned (64)));
HashReturn fugue512_Init(hashState_fugue *state, int hashbitlen);
HashReturn fugue512_Update(hashState_fugue *state, const void *data, DataLength databitlen);
HashReturn fugue512_Final(hashState_fugue *state, void *hashval);
HashReturn fugue512_full(hashState_fugue *hs, void *hashval, const void *data, DataLength databitlen);
#endif // AES
#endif // HASH_API_H

View File

@@ -74,6 +74,14 @@ void sph_fugue512_close(void *cc, void *dst);
void sph_fugue512_addbits_and_close( void sph_fugue512_addbits_and_close(
void *cc, unsigned ub, unsigned n, void *dst); void *cc, unsigned ub, unsigned n, void *dst);
#define sph_fugue512_full( cc, dst, data, len ) \
do{ \
sph_fugue512_init( cc ); \
sph_fugue512( cc, data, len ); \
sph_fugue512_close( cc, dst ); \
}while(0)
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,6 @@
#if !defined GROESTL_INTR_AES_H__
#define GROESTL_INTR_AES_H__
/* groestl-intr-aes.h Aug 2011 /* groestl-intr-aes.h Aug 2011
* *
* Groestl implementation with intrinsics using ssse3, sse4.1, and aes * Groestl implementation with intrinsics using ssse3, sse4.1, and aes
@@ -11,16 +14,51 @@
#include <wmmintrin.h> #include <wmmintrin.h>
#include "hash-groestl.h" #include "hash-groestl.h"
/* global constants */ static const __m128i round_const_p[] __attribute__ ((aligned (64))) =
__m128i ROUND_CONST_Lx; {
//__m128i ROUND_CONST_L0[ROUNDS512]; { 0x7060504030201000, 0xf0e0d0c0b0a09080 },
//__m128i ROUND_CONST_L7[ROUNDS512]; { 0x7161514131211101, 0xf1e1d1c1b1a19181 },
__m128i ROUND_CONST_P[ROUNDS1024]; { 0x7262524232221202, 0xf2e2d2c2b2a29282 },
__m128i ROUND_CONST_Q[ROUNDS1024]; { 0x7363534333231303, 0xf3e3d3c3b3a39383 },
__m128i TRANSP_MASK; { 0x7464544434241404, 0xf4e4d4c4b4a49484 },
__m128i SUBSH_MASK[8]; { 0x7565554535251505, 0xf5e5d5c5b5a59585 },
__m128i ALL_1B; { 0x7666564636261606, 0xf6e6d6c6b6a69686 },
__m128i ALL_FF; { 0x7767574737271707, 0xf7e7d7c7b7a79787 },
{ 0x7868584838281808, 0xf8e8d8c8b8a89888 },
{ 0x7969594939291909, 0xf9e9d9c9b9a99989 },
{ 0x7a6a5a4a3a2a1a0a, 0xfaeadacabaaa9a8a },
{ 0x7b6b5b4b3b2b1b0b, 0xfbebdbcbbbab9b8b },
{ 0x7c6c5c4c3c2c1c0c, 0xfcecdcccbcac9c8c },
{ 0x7d6d5d4d3d2d1d0d, 0xfdedddcdbdad9d8d }
};
static const __m128i round_const_q[] __attribute__ ((aligned (64))) =
{
{ 0x8f9fafbfcfdfefff, 0x0f1f2f3f4f5f6f7f },
{ 0x8e9eaebecedeeefe, 0x0e1e2e3e4e5e6e7e },
{ 0x8d9dadbdcdddedfd, 0x0d1d2d3d4d5d6d7d },
{ 0x8c9cacbcccdcecfc, 0x0c1c2c3c4c5c6c7c },
{ 0x8b9babbbcbdbebfb, 0x0b1b2b3b4b5b6b7b },
{ 0x8a9aaabacadaeafa, 0x0a1a2a3a4a5a6a7a },
{ 0x8999a9b9c9d9e9f9, 0x0919293949596979 },
{ 0x8898a8b8c8d8e8f8, 0x0818283848586878 },
{ 0x8797a7b7c7d7e7f7, 0x0717273747576777 },
{ 0x8696a6b6c6d6e6f6, 0x0616263646566676 },
{ 0x8595a5b5c5d5e5f5, 0x0515253545556575 },
{ 0x8494a4b4c4d4e4f4, 0x0414243444546474 },
{ 0x8393a3b3c3d3e3f3, 0x0313233343536373 },
{ 0x8292a2b2c2d2e2f2, 0x0212223242526272 }
};
static const __m128i TRANSP_MASK = { 0x0d0509010c040800, 0x0f070b030e060a02 };
static const __m128i SUBSH_MASK0 = { 0x0b0e0104070a0d00, 0x0306090c0f020508 };
static const __m128i SUBSH_MASK1 = { 0x0c0f0205080b0e01, 0x04070a0d00030609 };
static const __m128i SUBSH_MASK2 = { 0x0d000306090c0f02, 0x05080b0e0104070a };
static const __m128i SUBSH_MASK3 = { 0x0e0104070a0d0003, 0x06090c0f0205080b };
static const __m128i SUBSH_MASK4 = { 0x0f0205080b0e0104, 0x070a0d000306090c };
static const __m128i SUBSH_MASK5 = { 0x000306090c0f0205, 0x080b0e0104070a0d };
static const __m128i SUBSH_MASK6 = { 0x0104070a0d000306, 0x090c0f0205080b0e };
static const __m128i SUBSH_MASK7 = { 0x06090c0f0205080b, 0x0e0104070a0d0003 };
#define tos(a) #a #define tos(a) #a
#define tostr(a) tos(a) #define tostr(a) tos(a)
@@ -111,7 +149,7 @@ __m128i ALL_FF;
\ \
/* compute z_i : double x_i using temp xmm8 and 1B xmm9 */\ /* compute z_i : double x_i using temp xmm8 and 1B xmm9 */\
/* compute w_i : add y_{i+4} */\ /* compute w_i : add y_{i+4} */\
b1 = ALL_1B;\ b1 = m128_const1_64( 0x1b1b1b1b1b1b1b1b );\
MUL2(a0, b0, b1);\ MUL2(a0, b0, b1);\
a0 = _mm_xor_si128(a0, TEMP0);\ a0 = _mm_xor_si128(a0, TEMP0);\
MUL2(a1, b0, b1);\ MUL2(a1, b0, b1);\
@@ -152,25 +190,6 @@ __m128i ALL_FF;
}/*MixBytes*/ }/*MixBytes*/
#define SET_CONSTANTS(){\
ALL_FF = _mm_set_epi32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);\
ALL_1B = _mm_set_epi32(0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b);\
TRANSP_MASK = _mm_set_epi32(0x0f070b03, 0x0e060a02, 0x0d050901, 0x0c040800);\
SUBSH_MASK[0] = _mm_set_epi32(0x0306090c, 0x0f020508, 0x0b0e0104, 0x070a0d00);\
SUBSH_MASK[1] = _mm_set_epi32(0x04070a0d, 0x00030609, 0x0c0f0205, 0x080b0e01);\
SUBSH_MASK[2] = _mm_set_epi32(0x05080b0e, 0x0104070a, 0x0d000306, 0x090c0f02);\
SUBSH_MASK[3] = _mm_set_epi32(0x06090c0f, 0x0205080b, 0x0e010407, 0x0a0d0003);\
SUBSH_MASK[4] = _mm_set_epi32(0x070a0d00, 0x0306090c, 0x0f020508, 0x0b0e0104);\
SUBSH_MASK[5] = _mm_set_epi32(0x080b0e01, 0x04070a0d, 0x00030609, 0x0c0f0205);\
SUBSH_MASK[6] = _mm_set_epi32(0x090c0f02, 0x05080b0e, 0x0104070a, 0x0d000306);\
SUBSH_MASK[7] = _mm_set_epi32(0x0e010407, 0x0a0d0003, 0x06090c0f, 0x0205080b);\
for(i = 0; i < ROUNDS1024; i++)\
{\
ROUND_CONST_P[i] = _mm_set_epi32(0xf0e0d0c0 ^ (i * 0x01010101), 0xb0a09080 ^ (i * 0x01010101), 0x70605040 ^ (i * 0x01010101), 0x30201000 ^ (i * 0x01010101));\
ROUND_CONST_Q[i] = _mm_set_epi32(0x0f1f2f3f ^ (i * 0x01010101), 0x4f5f6f7f ^ (i * 0x01010101), 0x8f9fafbf ^ (i * 0x01010101), 0xcfdfefff ^ (i * 0x01010101));\
}\
}while(0);\
/* one round /* one round
* a0-a7 = input rows * a0-a7 = input rows
* b0-b7 = output rows * b0-b7 = output rows
@@ -194,30 +213,34 @@ __m128i ALL_FF;
u8 round_counter = 0;\ u8 round_counter = 0;\
for(round_counter = 0; round_counter < 14; round_counter+=2) {\ for(round_counter = 0; round_counter < 14; round_counter+=2) {\
/* AddRoundConstant P1024 */\ /* AddRoundConstant P1024 */\
xmm8 = _mm_xor_si128(xmm8, (ROUND_CONST_P[round_counter]));\ xmm8 = _mm_xor_si128( xmm8, \
casti_m128i( round_const_p, round_counter ) ); \
/* ShiftBytes P1024 + pre-AESENCLAST */\ /* ShiftBytes P1024 + pre-AESENCLAST */\
xmm8 = _mm_shuffle_epi8(xmm8, (SUBSH_MASK[0]));\ xmm8 = _mm_shuffle_epi8( xmm8, SUBSH_MASK0 ); \
xmm9 = _mm_shuffle_epi8(xmm9, (SUBSH_MASK[1]));\ xmm9 = _mm_shuffle_epi8( xmm9, SUBSH_MASK1 ); \
xmm10 = _mm_shuffle_epi8(xmm10, (SUBSH_MASK[2]));\ xmm10 = _mm_shuffle_epi8( xmm10, SUBSH_MASK2 ); \
xmm11 = _mm_shuffle_epi8(xmm11, (SUBSH_MASK[3]));\ xmm11 = _mm_shuffle_epi8( xmm11, SUBSH_MASK3 ); \
xmm12 = _mm_shuffle_epi8(xmm12, (SUBSH_MASK[4]));\ xmm12 = _mm_shuffle_epi8( xmm12, SUBSH_MASK4 ); \
xmm13 = _mm_shuffle_epi8(xmm13, (SUBSH_MASK[5]));\ xmm13 = _mm_shuffle_epi8( xmm13, SUBSH_MASK5 ); \
xmm14 = _mm_shuffle_epi8(xmm14, (SUBSH_MASK[6]));\ xmm14 = _mm_shuffle_epi8( xmm14, SUBSH_MASK6 ); \
xmm15 = _mm_shuffle_epi8(xmm15, (SUBSH_MASK[7]));\ xmm15 = _mm_shuffle_epi8( xmm15, SUBSH_MASK7 ); \
/* SubBytes + MixBytes */\ /* SubBytes + MixBytes */\
SUBMIX(xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\ SUBMIX( xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, \
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 ); \
\ \
/* AddRoundConstant P1024 */\ /* AddRoundConstant P1024 */\
xmm0 = _mm_xor_si128(xmm0, (ROUND_CONST_P[round_counter+1]));\ xmm0 = _mm_xor_si128( xmm0, \
xmm0 = _mm_shuffle_epi8(xmm0, (SUBSH_MASK[0]));\ casti_m128i( round_const_p, round_counter+1 ) ); \
xmm1 = _mm_shuffle_epi8(xmm1, (SUBSH_MASK[1]));\ xmm0 = _mm_shuffle_epi8( xmm0, SUBSH_MASK0 ); \
xmm2 = _mm_shuffle_epi8(xmm2, (SUBSH_MASK[2]));\ xmm1 = _mm_shuffle_epi8( xmm1, SUBSH_MASK1 ); \
xmm3 = _mm_shuffle_epi8(xmm3, (SUBSH_MASK[3]));\ xmm2 = _mm_shuffle_epi8( xmm2, SUBSH_MASK2 ); \
xmm4 = _mm_shuffle_epi8(xmm4, (SUBSH_MASK[4]));\ xmm3 = _mm_shuffle_epi8( xmm3, SUBSH_MASK3 ); \
xmm5 = _mm_shuffle_epi8(xmm5, (SUBSH_MASK[5]));\ xmm4 = _mm_shuffle_epi8( xmm4, SUBSH_MASK4 ); \
xmm6 = _mm_shuffle_epi8(xmm6, (SUBSH_MASK[6]));\ xmm5 = _mm_shuffle_epi8( xmm5, SUBSH_MASK5 ); \
xmm7 = _mm_shuffle_epi8(xmm7, (SUBSH_MASK[7]));\ xmm6 = _mm_shuffle_epi8( xmm6, SUBSH_MASK6 ); \
SUBMIX(xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\ xmm7 = _mm_shuffle_epi8( xmm7, SUBSH_MASK7 ); \
SUBMIX( xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, \
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 ); \
}\ }\
} }
@@ -225,48 +248,52 @@ __m128i ALL_FF;
u8 round_counter = 0;\ u8 round_counter = 0;\
for(round_counter = 0; round_counter < 14; round_counter+=2) {\ for(round_counter = 0; round_counter < 14; round_counter+=2) {\
/* AddRoundConstant Q1024 */\ /* AddRoundConstant Q1024 */\
xmm1 = ALL_FF;\ xmm1 = m128_neg1;\
xmm8 = _mm_xor_si128(xmm8, xmm1);\ xmm8 = _mm_xor_si128( xmm8, xmm1 ); \
xmm9 = _mm_xor_si128(xmm9, xmm1);\ xmm9 = _mm_xor_si128( xmm9, xmm1 ); \
xmm10 = _mm_xor_si128(xmm10, xmm1);\ xmm10 = _mm_xor_si128( xmm10, xmm1 ); \
xmm11 = _mm_xor_si128(xmm11, xmm1);\ xmm11 = _mm_xor_si128( xmm11, xmm1 ); \
xmm12 = _mm_xor_si128(xmm12, xmm1);\ xmm12 = _mm_xor_si128( xmm12, xmm1 ); \
xmm13 = _mm_xor_si128(xmm13, xmm1);\ xmm13 = _mm_xor_si128( xmm13, xmm1 ); \
xmm14 = _mm_xor_si128(xmm14, xmm1);\ xmm14 = _mm_xor_si128( xmm14, xmm1 ); \
xmm15 = _mm_xor_si128(xmm15, (ROUND_CONST_Q[round_counter]));\ xmm15 = _mm_xor_si128( xmm15, \
casti_m128i( round_const_q, round_counter ) ); \
/* ShiftBytes Q1024 + pre-AESENCLAST */\ /* ShiftBytes Q1024 + pre-AESENCLAST */\
xmm8 = _mm_shuffle_epi8(xmm8, (SUBSH_MASK[1]));\ xmm8 = _mm_shuffle_epi8( xmm8, SUBSH_MASK1 ); \
xmm9 = _mm_shuffle_epi8(xmm9, (SUBSH_MASK[3]));\ xmm9 = _mm_shuffle_epi8( xmm9, SUBSH_MASK3 ); \
xmm10 = _mm_shuffle_epi8(xmm10, (SUBSH_MASK[5]));\ xmm10 = _mm_shuffle_epi8( xmm10, SUBSH_MASK5 ); \
xmm11 = _mm_shuffle_epi8(xmm11, (SUBSH_MASK[7]));\ xmm11 = _mm_shuffle_epi8( xmm11, SUBSH_MASK7 ); \
xmm12 = _mm_shuffle_epi8(xmm12, (SUBSH_MASK[0]));\ xmm12 = _mm_shuffle_epi8( xmm12, SUBSH_MASK0 ); \
xmm13 = _mm_shuffle_epi8(xmm13, (SUBSH_MASK[2]));\ xmm13 = _mm_shuffle_epi8( xmm13, SUBSH_MASK2 ); \
xmm14 = _mm_shuffle_epi8(xmm14, (SUBSH_MASK[4]));\ xmm14 = _mm_shuffle_epi8( xmm14, SUBSH_MASK4 ); \
xmm15 = _mm_shuffle_epi8(xmm15, (SUBSH_MASK[6]));\ xmm15 = _mm_shuffle_epi8( xmm15, SUBSH_MASK6 ); \
/* SubBytes + MixBytes */\ /* SubBytes + MixBytes */\
SUBMIX(xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\ SUBMIX( xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, \
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6 , xmm7 ); \
\ \
/* AddRoundConstant Q1024 */\ /* AddRoundConstant Q1024 */\
xmm9 = ALL_FF;\ xmm9 = m128_neg1;\
xmm0 = _mm_xor_si128(xmm0, xmm9);\ xmm0 = _mm_xor_si128( xmm0, xmm9 ); \
xmm1 = _mm_xor_si128(xmm1, xmm9);\ xmm1 = _mm_xor_si128( xmm1, xmm9 ); \
xmm2 = _mm_xor_si128(xmm2, xmm9);\ xmm2 = _mm_xor_si128( xmm2, xmm9 ); \
xmm3 = _mm_xor_si128(xmm3, xmm9);\ xmm3 = _mm_xor_si128( xmm3, xmm9 ); \
xmm4 = _mm_xor_si128(xmm4, xmm9);\ xmm4 = _mm_xor_si128( xmm4, xmm9 ); \
xmm5 = _mm_xor_si128(xmm5, xmm9);\ xmm5 = _mm_xor_si128( xmm5, xmm9 ); \
xmm6 = _mm_xor_si128(xmm6, xmm9);\ xmm6 = _mm_xor_si128( xmm6, xmm9 ); \
xmm7 = _mm_xor_si128(xmm7, (ROUND_CONST_Q[round_counter+1]));\ xmm7 = _mm_xor_si128( xmm7, \
casti_m128i( round_const_q, round_counter+1 ) ); \
/* ShiftBytes Q1024 + pre-AESENCLAST */\ /* ShiftBytes Q1024 + pre-AESENCLAST */\
xmm0 = _mm_shuffle_epi8(xmm0, (SUBSH_MASK[1]));\ xmm0 = _mm_shuffle_epi8( xmm0, SUBSH_MASK1 ); \
xmm1 = _mm_shuffle_epi8(xmm1, (SUBSH_MASK[3]));\ xmm1 = _mm_shuffle_epi8( xmm1, SUBSH_MASK3 ); \
xmm2 = _mm_shuffle_epi8(xmm2, (SUBSH_MASK[5]));\ xmm2 = _mm_shuffle_epi8( xmm2, SUBSH_MASK5 ); \
xmm3 = _mm_shuffle_epi8(xmm3, (SUBSH_MASK[7]));\ xmm3 = _mm_shuffle_epi8( xmm3, SUBSH_MASK7 ); \
xmm4 = _mm_shuffle_epi8(xmm4, (SUBSH_MASK[0]));\ xmm4 = _mm_shuffle_epi8( xmm4, SUBSH_MASK0 ); \
xmm5 = _mm_shuffle_epi8(xmm5, (SUBSH_MASK[2]));\ xmm5 = _mm_shuffle_epi8( xmm5, SUBSH_MASK2 ); \
xmm6 = _mm_shuffle_epi8(xmm6, (SUBSH_MASK[4]));\ xmm6 = _mm_shuffle_epi8( xmm6, SUBSH_MASK4 ); \
xmm7 = _mm_shuffle_epi8(xmm7, (SUBSH_MASK[6]));\ xmm7 = _mm_shuffle_epi8( xmm7, SUBSH_MASK6 ); \
/* SubBytes + MixBytes */\ /* SubBytes + MixBytes */\
SUBMIX(xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\ SUBMIX( xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, \
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 ); \
}\ }\
} }
@@ -278,7 +305,7 @@ __m128i ALL_FF;
* clobbers: t0-t7 * clobbers: t0-t7
*/ */
#define Matrix_Transpose(i0, i1, i2, i3, i4, i5, i6, i7, t0, t1, t2, t3, t4, t5, t6, t7){\ #define Matrix_Transpose(i0, i1, i2, i3, i4, i5, i6, i7, t0, t1, t2, t3, t4, t5, t6, t7){\
t0 = TRANSP_MASK;\ t0 = TRANSP_MASK; \
\ \
i6 = _mm_shuffle_epi8(i6, t0);\ i6 = _mm_shuffle_epi8(i6, t0);\
i0 = _mm_shuffle_epi8(i0, t0);\ i0 = _mm_shuffle_epi8(i0, t0);\
@@ -366,7 +393,7 @@ __m128i ALL_FF;
i4 = _mm_unpacklo_epi64(i4, i5);\ i4 = _mm_unpacklo_epi64(i4, i5);\
t1 = _mm_unpackhi_epi64(t1, i5);\ t1 = _mm_unpackhi_epi64(t1, i5);\
t2 = i6;\ t2 = i6;\
o0 = TRANSP_MASK;\ o0 = TRANSP_MASK; \
i6 = _mm_unpacklo_epi64(i6, i7);\ i6 = _mm_unpacklo_epi64(i6, i7);\
t2 = _mm_unpackhi_epi64(t2, i7);\ t2 = _mm_unpackhi_epi64(t2, i7);\
/* load transpose mask into a register, because it will be used 8 times */\ /* load transpose mask into a register, because it will be used 8 times */\
@@ -607,3 +634,4 @@ void OF1024( __m128i* chaining )
return; return;
} }
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +0,0 @@
// specify assembly or intrinsics implementation
//#define TASM
#define TINTR
// Not to be confused with AVX512VAES
#define VAES
// #define VAVX
// #define VVPERM
//#endif

View File

@@ -1,529 +0,0 @@
/* groestl-asm-aes.h Aug 2011
*
* Groestl implementation with inline assembly using ssse3, sse4.1, and aes
* instructions.
* Authors: Günther A. Roland, Martin Schläffer, Krystian Matusiewicz
*
* This code is placed in the public domain
*/
#include "hash-groestl256.h"
/* global constants */
__attribute__ ((aligned (16))) unsigned char ROUND_CONST_Lx[16];
__attribute__ ((aligned (16))) unsigned char ROUND_CONST_L0[ROUNDS512*16];
__attribute__ ((aligned (16))) unsigned char ROUND_CONST_L7[ROUNDS512*16];
__attribute__ ((aligned (16))) unsigned char ROUND_CONST_P[ROUNDS1024*16];
__attribute__ ((aligned (16))) unsigned char ROUND_CONST_Q[ROUNDS1024*16];
__attribute__ ((aligned (16))) unsigned char TRANSP_MASK[16];
__attribute__ ((aligned (16))) unsigned char SUBSH_MASK[8*16];
__attribute__ ((aligned (16))) unsigned char ALL_1B[16];
__attribute__ ((aligned (16))) unsigned char ALL_FF[16];
/* temporary variables */
__attribute__ ((aligned (16))) unsigned char QTEMP[8*16];
__attribute__ ((aligned (16))) unsigned char TEMP[3*16];
#define tos(a) #a
#define tostr(a) tos(a)
/* xmm[i] will be multiplied by 2
* xmm[j] will be lost
* xmm[k] has to be all 0x1b */
#define MUL2(i, j, k){\
asm("pxor xmm"tostr(j)", xmm"tostr(j)"");\
asm("pcmpgtb xmm"tostr(j)", xmm"tostr(i)"");\
asm("paddb xmm"tostr(i)", xmm"tostr(i)"");\
asm("pand xmm"tostr(j)", xmm"tostr(k)"");\
asm("pxor xmm"tostr(i)", xmm"tostr(j)"");\
}/**/
/* Yet another implementation of MixBytes.
This time we use the formulae (3) from the paper "Byte Slicing Groestl".
Input: a0, ..., a7
Output: b0, ..., b7 = MixBytes(a0,...,a7).
but we use the relations:
t_i = a_i + a_{i+3}
x_i = t_i + t_{i+3}
y_i = t_i + t+{i+2} + a_{i+6}
z_i = 2*x_i
w_i = z_i + y_{i+4}
v_i = 2*w_i
b_i = v_{i+3} + y_{i+4}
We keep building b_i in registers xmm8..xmm15 by first building y_{i+4} there
and then adding v_i computed in the meantime in registers xmm0..xmm7.
We almost fit into 16 registers, need only 3 spills to memory.
This implementation costs 7.7 c/b giving total speed on SNB: 10.7c/b.
K. Matusiewicz, 2011/05/29 */
#define MixBytes(a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\
/* t_i = a_i + a_{i+1} */\
asm("movdqa xmm"tostr(b6)", xmm"tostr(a0)"");\
asm("movdqa xmm"tostr(b7)", xmm"tostr(a1)"");\
asm("pxor xmm"tostr(a0)", xmm"tostr(a1)"");\
asm("movdqa xmm"tostr(b0)", xmm"tostr(a2)"");\
asm("pxor xmm"tostr(a1)", xmm"tostr(a2)"");\
asm("movdqa xmm"tostr(b1)", xmm"tostr(a3)"");\
asm("pxor xmm"tostr(a2)", xmm"tostr(a3)"");\
asm("movdqa xmm"tostr(b2)", xmm"tostr(a4)"");\
asm("pxor xmm"tostr(a3)", xmm"tostr(a4)"");\
asm("movdqa xmm"tostr(b3)", xmm"tostr(a5)"");\
asm("pxor xmm"tostr(a4)", xmm"tostr(a5)"");\
asm("movdqa xmm"tostr(b4)", xmm"tostr(a6)"");\
asm("pxor xmm"tostr(a5)", xmm"tostr(a6)"");\
asm("movdqa xmm"tostr(b5)", xmm"tostr(a7)"");\
asm("pxor xmm"tostr(a6)", xmm"tostr(a7)"");\
asm("pxor xmm"tostr(a7)", xmm"tostr(b6)"");\
\
/* build y4 y5 y6 ... in regs xmm8, xmm9, xmm10 by adding t_i*/\
asm("pxor xmm"tostr(b0)", xmm"tostr(a4)"");\
asm("pxor xmm"tostr(b6)", xmm"tostr(a4)"");\
asm("pxor xmm"tostr(b1)", xmm"tostr(a5)"");\
asm("pxor xmm"tostr(b7)", xmm"tostr(a5)"");\
asm("pxor xmm"tostr(b2)", xmm"tostr(a6)"");\
asm("pxor xmm"tostr(b0)", xmm"tostr(a6)"");\
/* spill values y_4, y_5 to memory */\
asm("movaps [TEMP+0*16], xmm"tostr(b0)"");\
asm("pxor xmm"tostr(b3)", xmm"tostr(a7)"");\
asm("pxor xmm"tostr(b1)", xmm"tostr(a7)"");\
asm("movaps [TEMP+1*16], xmm"tostr(b1)"");\
asm("pxor xmm"tostr(b4)", xmm"tostr(a0)"");\
asm("pxor xmm"tostr(b2)", xmm"tostr(a0)"");\
/* save values t0, t1, t2 to xmm8, xmm9 and memory */\
asm("movdqa xmm"tostr(b0)", xmm"tostr(a0)"");\
asm("pxor xmm"tostr(b5)", xmm"tostr(a1)"");\
asm("pxor xmm"tostr(b3)", xmm"tostr(a1)"");\
asm("movdqa xmm"tostr(b1)", xmm"tostr(a1)"");\
asm("pxor xmm"tostr(b6)", xmm"tostr(a2)"");\
asm("pxor xmm"tostr(b4)", xmm"tostr(a2)"");\
asm("movaps [TEMP+2*16], xmm"tostr(a2)"");\
asm("pxor xmm"tostr(b7)", xmm"tostr(a3)"");\
asm("pxor xmm"tostr(b5)", xmm"tostr(a3)"");\
\
/* compute x_i = t_i + t_{i+3} */\
asm("pxor xmm"tostr(a0)", xmm"tostr(a3)"");\
asm("pxor xmm"tostr(a1)", xmm"tostr(a4)"");\
asm("pxor xmm"tostr(a2)", xmm"tostr(a5)"");\
asm("pxor xmm"tostr(a3)", xmm"tostr(a6)"");\
asm("pxor xmm"tostr(a4)", xmm"tostr(a7)"");\
asm("pxor xmm"tostr(a5)", xmm"tostr(b0)"");\
asm("pxor xmm"tostr(a6)", xmm"tostr(b1)"");\
asm("pxor xmm"tostr(a7)", [TEMP+2*16]");\
\
/* compute z_i : double x_i using temp xmm8 and 1B xmm9 */\
/* compute w_i : add y_{i+4} */\
asm("movaps xmm"tostr(b1)", [ALL_1B]");\
MUL2(a0, b0, b1);\
asm("pxor xmm"tostr(a0)", [TEMP+0*16]");\
MUL2(a1, b0, b1);\
asm("pxor xmm"tostr(a1)", [TEMP+1*16]");\
MUL2(a2, b0, b1);\
asm("pxor xmm"tostr(a2)", xmm"tostr(b2)"");\
MUL2(a3, b0, b1);\
asm("pxor xmm"tostr(a3)", xmm"tostr(b3)"");\
MUL2(a4, b0, b1);\
asm("pxor xmm"tostr(a4)", xmm"tostr(b4)"");\
MUL2(a5, b0, b1);\
asm("pxor xmm"tostr(a5)", xmm"tostr(b5)"");\
MUL2(a6, b0, b1);\
asm("pxor xmm"tostr(a6)", xmm"tostr(b6)"");\
MUL2(a7, b0, b1);\
asm("pxor xmm"tostr(a7)", xmm"tostr(b7)"");\
\
/* compute v_i : double w_i */\
/* add to y_4 y_5 .. v3, v4, ... */\
MUL2(a0, b0, b1);\
asm("pxor xmm"tostr(b5)", xmm"tostr(a0)"");\
MUL2(a1, b0, b1);\
asm("pxor xmm"tostr(b6)", xmm"tostr(a1)"");\
MUL2(a2, b0, b1);\
asm("pxor xmm"tostr(b7)", xmm"tostr(a2)"");\
MUL2(a5, b0, b1);\
asm("pxor xmm"tostr(b2)", xmm"tostr(a5)"");\
MUL2(a6, b0, b1);\
asm("pxor xmm"tostr(b3)", xmm"tostr(a6)"");\
MUL2(a7, b0, b1);\
asm("pxor xmm"tostr(b4)", xmm"tostr(a7)"");\
MUL2(a3, b0, b1);\
MUL2(a4, b0, b1);\
asm("movaps xmm"tostr(b0)", [TEMP+0*16]");\
asm("movaps xmm"tostr(b1)", [TEMP+1*16]");\
asm("pxor xmm"tostr(b0)", xmm"tostr(a3)"");\
asm("pxor xmm"tostr(b1)", xmm"tostr(a4)"");\
}/*MixBytes*/
#define SET_CONSTANTS(){\
((u64*)ALL_1B)[0] = 0x1b1b1b1b1b1b1b1bULL;\
((u64*)ALL_1B)[1] = 0x1b1b1b1b1b1b1b1bULL;\
((u64*)TRANSP_MASK)[0] = 0x0d0509010c040800ULL;\
((u64*)TRANSP_MASK)[1] = 0x0f070b030e060a02ULL;\
((u64*)SUBSH_MASK)[ 0] = 0x0c0f0104070b0e00ULL;\
((u64*)SUBSH_MASK)[ 1] = 0x03060a0d08020509ULL;\
((u64*)SUBSH_MASK)[ 2] = 0x0e090205000d0801ULL;\
((u64*)SUBSH_MASK)[ 3] = 0x04070c0f0a03060bULL;\
((u64*)SUBSH_MASK)[ 4] = 0x080b0306010f0a02ULL;\
((u64*)SUBSH_MASK)[ 5] = 0x05000e090c04070dULL;\
((u64*)SUBSH_MASK)[ 6] = 0x0a0d040702090c03ULL;\
((u64*)SUBSH_MASK)[ 7] = 0x0601080b0e05000fULL;\
((u64*)SUBSH_MASK)[ 8] = 0x0b0e0500030a0d04ULL;\
((u64*)SUBSH_MASK)[ 9] = 0x0702090c0f060108ULL;\
((u64*)SUBSH_MASK)[10] = 0x0d080601040c0f05ULL;\
((u64*)SUBSH_MASK)[11] = 0x00030b0e0907020aULL;\
((u64*)SUBSH_MASK)[12] = 0x0f0a0702050e0906ULL;\
((u64*)SUBSH_MASK)[13] = 0x01040d080b00030cULL;\
((u64*)SUBSH_MASK)[14] = 0x090c000306080b07ULL;\
((u64*)SUBSH_MASK)[15] = 0x02050f0a0d01040eULL;\
for(i = 0; i < ROUNDS512; i++)\
{\
((u64*)ROUND_CONST_L0)[i*2+1] = 0xffffffffffffffffULL;\
((u64*)ROUND_CONST_L0)[i*2+0] = (i * 0x0101010101010101ULL) ^ 0x7060504030201000ULL;\
((u64*)ROUND_CONST_L7)[i*2+1] = (i * 0x0101010101010101ULL) ^ 0x8f9fafbfcfdfefffULL;\
((u64*)ROUND_CONST_L7)[i*2+0] = 0x0000000000000000ULL;\
}\
((u64*)ROUND_CONST_Lx)[1] = 0xffffffffffffffffULL;\
((u64*)ROUND_CONST_Lx)[0] = 0x0000000000000000ULL;\
}while(0);
#define Push_All_Regs() do{\
/* not using any...
asm("push rax");\
asm("push rbx");\
asm("push rcx");*/\
}while(0);
#define Pop_All_Regs() do{\
/* not using any...
asm("pop rcx");\
asm("pop rbx");\
asm("pop rax");*/\
}while(0);
/* one round
* i = round number
* a0-a7 = input rows
* b0-b7 = output rows
*/
#define ROUND(i, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\
/* AddRoundConstant */\
asm ("movaps xmm"tostr(b1)", [ROUND_CONST_Lx]");\
asm ("pxor xmm"tostr(a0)", [ROUND_CONST_L0+"tostr(i)"*16]");\
asm ("pxor xmm"tostr(a1)", xmm"tostr(b1)"");\
asm ("pxor xmm"tostr(a2)", xmm"tostr(b1)"");\
asm ("pxor xmm"tostr(a3)", xmm"tostr(b1)"");\
asm ("pxor xmm"tostr(a4)", xmm"tostr(b1)"");\
asm ("pxor xmm"tostr(a5)", xmm"tostr(b1)"");\
asm ("pxor xmm"tostr(a6)", xmm"tostr(b1)"");\
asm ("pxor xmm"tostr(a7)", [ROUND_CONST_L7+"tostr(i)"*16]");\
/* ShiftBytes + SubBytes (interleaved) */\
asm ("pxor xmm"tostr(b0)", xmm"tostr(b0)"");\
asm ("pshufb xmm"tostr(a0)", [SUBSH_MASK+0*16]");\
asm ("aesenclast xmm"tostr(a0)", xmm"tostr(b0)"");\
asm ("pshufb xmm"tostr(a1)", [SUBSH_MASK+1*16]");\
asm ("aesenclast xmm"tostr(a1)", xmm"tostr(b0)"");\
asm ("pshufb xmm"tostr(a2)", [SUBSH_MASK+2*16]");\
asm ("aesenclast xmm"tostr(a2)", xmm"tostr(b0)"");\
asm ("pshufb xmm"tostr(a3)", [SUBSH_MASK+3*16]");\
asm ("aesenclast xmm"tostr(a3)", xmm"tostr(b0)"");\
asm ("pshufb xmm"tostr(a4)", [SUBSH_MASK+4*16]");\
asm ("aesenclast xmm"tostr(a4)", xmm"tostr(b0)"");\
asm ("pshufb xmm"tostr(a5)", [SUBSH_MASK+5*16]");\
asm ("aesenclast xmm"tostr(a5)", xmm"tostr(b0)"");\
asm ("pshufb xmm"tostr(a6)", [SUBSH_MASK+6*16]");\
asm ("aesenclast xmm"tostr(a6)", xmm"tostr(b0)"");\
asm ("pshufb xmm"tostr(a7)", [SUBSH_MASK+7*16]");\
asm ("aesenclast xmm"tostr(a7)", xmm"tostr(b0)"");\
/* MixBytes */\
MixBytes(a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7);\
}
/* 10 rounds, P and Q in parallel */
#define ROUNDS_P_Q(){\
ROUND(0, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
ROUND(2, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(3, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
ROUND(4, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(5, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
ROUND(6, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
ROUND(8, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
}
/* Matrix Transpose Step 1
* input is a 512-bit state with two columns in one xmm
* output is a 512-bit state with two rows in one xmm
* inputs: i0-i3
* outputs: i0, o1-o3
* clobbers: t0
*/
#define Matrix_Transpose_A(i0, i1, i2, i3, o1, o2, o3, t0){\
asm ("movaps xmm"tostr(t0)", [TRANSP_MASK]");\
\
asm ("pshufb xmm"tostr(i0)", xmm"tostr(t0)"");\
asm ("pshufb xmm"tostr(i1)", xmm"tostr(t0)"");\
asm ("pshufb xmm"tostr(i2)", xmm"tostr(t0)"");\
asm ("pshufb xmm"tostr(i3)", xmm"tostr(t0)"");\
\
asm ("movdqa xmm"tostr(o1)", xmm"tostr(i0)"");\
asm ("movdqa xmm"tostr(t0)", xmm"tostr(i2)"");\
\
asm ("punpcklwd xmm"tostr(i0)", xmm"tostr(i1)"");\
asm ("punpckhwd xmm"tostr(o1)", xmm"tostr(i1)"");\
asm ("punpcklwd xmm"tostr(i2)", xmm"tostr(i3)"");\
asm ("punpckhwd xmm"tostr(t0)", xmm"tostr(i3)"");\
\
asm ("pshufd xmm"tostr(i0)", xmm"tostr(i0)", 216");\
asm ("pshufd xmm"tostr(o1)", xmm"tostr(o1)", 216");\
asm ("pshufd xmm"tostr(i2)", xmm"tostr(i2)", 216");\
asm ("pshufd xmm"tostr(t0)", xmm"tostr(t0)", 216");\
\
asm ("movdqa xmm"tostr(o2)", xmm"tostr(i0)"");\
asm ("movdqa xmm"tostr(o3)", xmm"tostr(o1)"");\
\
asm ("punpckldq xmm"tostr(i0)", xmm"tostr(i2)"");\
asm ("punpckldq xmm"tostr(o1)", xmm"tostr(t0)"");\
asm ("punpckhdq xmm"tostr(o2)", xmm"tostr(i2)"");\
asm ("punpckhdq xmm"tostr(o3)", xmm"tostr(t0)"");\
}/**/
/* Matrix Transpose Step 2
* input are two 512-bit states with two rows in one xmm
* output are two 512-bit states with one row of each state in one xmm
* inputs: i0-i3 = P, i4-i7 = Q
* outputs: (i0, o1-o7) = (P|Q)
* possible reassignments: (output reg = input reg)
* * i1 -> o3-7
* * i2 -> o5-7
* * i3 -> o7
* * i4 -> o3-7
* * i5 -> o6-7
*/
#define Matrix_Transpose_B(i0, i1, i2, i3, i4, i5, i6, i7, o1, o2, o3, o4, o5, o6, o7){\
asm ("movdqa xmm"tostr(o1)", xmm"tostr(i0)"");\
asm ("movdqa xmm"tostr(o2)", xmm"tostr(i1)"");\
asm ("punpcklqdq xmm"tostr(i0)", xmm"tostr(i4)"");\
asm ("punpckhqdq xmm"tostr(o1)", xmm"tostr(i4)"");\
asm ("movdqa xmm"tostr(o3)", xmm"tostr(i1)"");\
asm ("movdqa xmm"tostr(o4)", xmm"tostr(i2)"");\
asm ("punpcklqdq xmm"tostr(o2)", xmm"tostr(i5)"");\
asm ("punpckhqdq xmm"tostr(o3)", xmm"tostr(i5)"");\
asm ("movdqa xmm"tostr(o5)", xmm"tostr(i2)"");\
asm ("movdqa xmm"tostr(o6)", xmm"tostr(i3)"");\
asm ("punpcklqdq xmm"tostr(o4)", xmm"tostr(i6)"");\
asm ("punpckhqdq xmm"tostr(o5)", xmm"tostr(i6)"");\
asm ("movdqa xmm"tostr(o7)", xmm"tostr(i3)"");\
asm ("punpcklqdq xmm"tostr(o6)", xmm"tostr(i7)"");\
asm ("punpckhqdq xmm"tostr(o7)", xmm"tostr(i7)"");\
}/**/
/* Matrix Transpose Inverse Step 2
* input are two 512-bit states with one row of each state in one xmm
* output are two 512-bit states with two rows in one xmm
* inputs: i0-i7 = (P|Q)
* outputs: (i0, i2, i4, i6) = P, (o0-o3) = Q
*/
#define Matrix_Transpose_B_INV(i0, i1, i2, i3, i4, i5, i6, i7, o0, o1, o2, o3){\
asm ("movdqa xmm"tostr(o0)", xmm"tostr(i0)"");\
asm ("punpcklqdq xmm"tostr(i0)", xmm"tostr(i1)"");\
asm ("punpckhqdq xmm"tostr(o0)", xmm"tostr(i1)"");\
asm ("movdqa xmm"tostr(o1)", xmm"tostr(i2)"");\
asm ("punpcklqdq xmm"tostr(i2)", xmm"tostr(i3)"");\
asm ("punpckhqdq xmm"tostr(o1)", xmm"tostr(i3)"");\
asm ("movdqa xmm"tostr(o2)", xmm"tostr(i4)"");\
asm ("punpcklqdq xmm"tostr(i4)", xmm"tostr(i5)"");\
asm ("punpckhqdq xmm"tostr(o2)", xmm"tostr(i5)"");\
asm ("movdqa xmm"tostr(o3)", xmm"tostr(i6)"");\
asm ("punpcklqdq xmm"tostr(i6)", xmm"tostr(i7)"");\
asm ("punpckhqdq xmm"tostr(o3)", xmm"tostr(i7)"");\
}/**/
/* Matrix Transpose Output Step 2
* input is one 512-bit state with two rows in one xmm
* output is one 512-bit state with one row in the low 64-bits of one xmm
* inputs: i0,i2,i4,i6 = S
* outputs: (i0-7) = (0|S)
*/
#define Matrix_Transpose_O_B(i0, i1, i2, i3, i4, i5, i6, i7, t0){\
asm ("pxor xmm"tostr(t0)", xmm"tostr(t0)"");\
asm ("movdqa xmm"tostr(i1)", xmm"tostr(i0)"");\
asm ("movdqa xmm"tostr(i3)", xmm"tostr(i2)"");\
asm ("movdqa xmm"tostr(i5)", xmm"tostr(i4)"");\
asm ("movdqa xmm"tostr(i7)", xmm"tostr(i6)"");\
asm ("punpcklqdq xmm"tostr(i0)", xmm"tostr(t0)"");\
asm ("punpckhqdq xmm"tostr(i1)", xmm"tostr(t0)"");\
asm ("punpcklqdq xmm"tostr(i2)", xmm"tostr(t0)"");\
asm ("punpckhqdq xmm"tostr(i3)", xmm"tostr(t0)"");\
asm ("punpcklqdq xmm"tostr(i4)", xmm"tostr(t0)"");\
asm ("punpckhqdq xmm"tostr(i5)", xmm"tostr(t0)"");\
asm ("punpcklqdq xmm"tostr(i6)", xmm"tostr(t0)"");\
asm ("punpckhqdq xmm"tostr(i7)", xmm"tostr(t0)"");\
}/**/
/* Matrix Transpose Output Inverse Step 2
* input is one 512-bit state with one row in the low 64-bits of one xmm
* output is one 512-bit state with two rows in one xmm
* inputs: i0-i7 = (0|S)
* outputs: (i0, i2, i4, i6) = S
*/
#define Matrix_Transpose_O_B_INV(i0, i1, i2, i3, i4, i5, i6, i7){\
asm ("punpcklqdq xmm"tostr(i0)", xmm"tostr(i1)"");\
asm ("punpcklqdq xmm"tostr(i2)", xmm"tostr(i3)"");\
asm ("punpcklqdq xmm"tostr(i4)", xmm"tostr(i5)"");\
asm ("punpcklqdq xmm"tostr(i6)", xmm"tostr(i7)"");\
}/**/
void INIT256(u64* h)
{
/* __cdecl calling convention: */
/* chaining value CV in rdi */
asm (".intel_syntax noprefix");
asm volatile ("emms");
/* load IV into registers xmm12 - xmm15 */
asm ("movaps xmm12, [rdi+0*16]");
asm ("movaps xmm13, [rdi+1*16]");
asm ("movaps xmm14, [rdi+2*16]");
asm ("movaps xmm15, [rdi+3*16]");
/* transform chaining value from column ordering into row ordering */
/* we put two rows (64 bit) of the IV into one 128-bit XMM register */
Matrix_Transpose_A(12, 13, 14, 15, 2, 6, 7, 0);
/* store transposed IV */
asm ("movaps [rdi+0*16], xmm12");
asm ("movaps [rdi+1*16], xmm2");
asm ("movaps [rdi+2*16], xmm6");
asm ("movaps [rdi+3*16], xmm7");
asm volatile ("emms");
asm (".att_syntax noprefix");
}
void TF512(u64* h, u64* m)
{
/* __cdecl calling convention: */
/* chaining value CV in rdi */
/* message M in rsi */
#ifdef IACA_TRACE
IACA_START;
#endif
asm (".intel_syntax noprefix");
Push_All_Regs();
/* load message into registers xmm12 - xmm15 (Q = message) */
asm ("movaps xmm12, [rsi+0*16]");
asm ("movaps xmm13, [rsi+1*16]");
asm ("movaps xmm14, [rsi+2*16]");
asm ("movaps xmm15, [rsi+3*16]");
/* transform message M from column ordering into row ordering */
/* we first put two rows (2x64 bit) of the message into one 128-bit xmm register */
Matrix_Transpose_A(12, 13, 14, 15, 2, 6, 7, 0);
/* load previous chaining value */
/* we first put two rows (64 bit) of the CV into one 128-bit xmm register */
asm ("movaps xmm8, [rdi+0*16]");
asm ("movaps xmm0, [rdi+1*16]");
asm ("movaps xmm4, [rdi+2*16]");
asm ("movaps xmm5, [rdi+3*16]");
/* xor message to CV get input of P */
/* result: CV+M in xmm8, xmm0, xmm4, xmm5 */
asm ("pxor xmm8, xmm12");
asm ("pxor xmm0, xmm2");
asm ("pxor xmm4, xmm6");
asm ("pxor xmm5, xmm7");
/* there are now 2 rows of the Groestl state (P and Q) in each xmm register */
/* unpack to get 1 row of P (64 bit) and Q (64 bit) into one xmm register */
/* result: the 8 rows of P and Q in xmm8 - xmm12 */
Matrix_Transpose_B(8, 0, 4, 5, 12, 2, 6, 7, 9, 10, 11, 12, 13, 14, 15);
/* compute the two permutations P and Q in parallel */
ROUNDS_P_Q();
/* unpack again to get two rows of P or two rows of Q in one xmm register */
Matrix_Transpose_B_INV(8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3);
/* xor output of P and Q */
/* result: P(CV+M)+Q(M) in xmm0...xmm3 */
asm ("pxor xmm0, xmm8");
asm ("pxor xmm1, xmm10");
asm ("pxor xmm2, xmm12");
asm ("pxor xmm3, xmm14");
/* xor CV (feed-forward) */
/* result: P(CV+M)+Q(M)+CV in xmm0...xmm3 */
asm ("pxor xmm0, [rdi+0*16]");
asm ("pxor xmm1, [rdi+1*16]");
asm ("pxor xmm2, [rdi+2*16]");
asm ("pxor xmm3, [rdi+3*16]");
/* store CV */
asm ("movaps [rdi+0*16], xmm0");
asm ("movaps [rdi+1*16], xmm1");
asm ("movaps [rdi+2*16], xmm2");
asm ("movaps [rdi+3*16], xmm3");
Pop_All_Regs();
asm (".att_syntax noprefix");
#ifdef IACA_TRACE
IACA_END;
#endif
return;
}
void OF512(u64* h)
{
/* __cdecl calling convention: */
/* chaining value CV in rdi */
asm (".intel_syntax noprefix");
Push_All_Regs();
/* load CV into registers xmm8, xmm10, xmm12, xmm14 */
asm ("movaps xmm8, [rdi+0*16]");
asm ("movaps xmm10, [rdi+1*16]");
asm ("movaps xmm12, [rdi+2*16]");
asm ("movaps xmm14, [rdi+3*16]");
/* there are now 2 rows of the CV in one xmm register */
/* unpack to get 1 row of P (64 bit) into one half of an xmm register */
/* result: the 8 input rows of P in xmm8 - xmm15 */
Matrix_Transpose_O_B(8, 9, 10, 11, 12, 13, 14, 15, 0);
/* compute the permutation P */
/* result: the output of P(CV) in xmm8 - xmm15 */
ROUNDS_P_Q();
/* unpack again to get two rows of P in one xmm register */
/* result: P(CV) in xmm8, xmm10, xmm12, xmm14 */
Matrix_Transpose_O_B_INV(8, 9, 10, 11, 12, 13, 14, 15);
/* xor CV to P output (feed-forward) */
/* result: P(CV)+CV in xmm8, xmm10, xmm12, xmm14 */
asm ("pxor xmm8, [rdi+0*16]");
asm ("pxor xmm10, [rdi+1*16]");
asm ("pxor xmm12, [rdi+2*16]");
asm ("pxor xmm14, [rdi+3*16]");
/* transform state back from row ordering into column ordering */
/* result: final hash value in xmm9, xmm11 */
Matrix_Transpose_A(8, 10, 12, 14, 4, 9, 11, 0);
/* we only need to return the truncated half of the state */
asm ("movaps [rdi+2*16], xmm9");
asm ("movaps [rdi+3*16], xmm11");
Pop_All_Regs();
asm (".att_syntax noprefix");
return;
}

View File

@@ -1,519 +0,0 @@
/* groestl-asm-avx.h Aug 2011
*
* Groestl implementation with inline assembly using ssse3, sse4.1, aes and avx
* instructions.
* Author: Günther A. Roland, Martin Schläffer, Krystian Matusiewicz
*
* This code is placed in the public domain
*/
#include "hash-groestl256.h"
/* global variables */
__attribute__ ((aligned (32))) unsigned char ROUND_CONST_Lx[16];
__attribute__ ((aligned (32))) unsigned char ROUND_CONST_L0[ROUNDS512*16];
__attribute__ ((aligned (32))) unsigned char ROUND_CONST_L7[ROUNDS512*16];
__attribute__ ((aligned (32))) unsigned char ROUND_CONST_P[ROUNDS1024*16];
__attribute__ ((aligned (32))) unsigned char ROUND_CONST_Q[ROUNDS1024*16];
__attribute__ ((aligned (32))) unsigned char TRANSP_MASK[16];
__attribute__ ((aligned (32))) unsigned char SUBSH_MASK[8*16];
__attribute__ ((aligned (32))) unsigned char ALL_1B[32];
__attribute__ ((aligned (32))) unsigned char ALL_FF[32];
/* temporary variables */
__attribute__ ((aligned (32))) unsigned char TEMP[6*32];
#define tos(a) #a
#define tostr(a) tos(a)
#define SET_CONSTANTS(){\
((u64*)TRANSP_MASK)[0] = 0x0d0509010c040800ULL;\
((u64*)TRANSP_MASK)[1] = 0x0f070b030e060a02ULL;\
((u64*)ALL_1B)[0] = 0x1b1b1b1b1b1b1b1bULL;\
((u64*)ALL_1B)[1] = 0x1b1b1b1b1b1b1b1bULL;\
((u64*)SUBSH_MASK)[ 0] = 0x0c0f0104070b0e00ULL;\
((u64*)SUBSH_MASK)[ 1] = 0x03060a0d08020509ULL;\
((u64*)SUBSH_MASK)[ 2] = 0x0e090205000d0801ULL;\
((u64*)SUBSH_MASK)[ 3] = 0x04070c0f0a03060bULL;\
((u64*)SUBSH_MASK)[ 4] = 0x080b0306010f0a02ULL;\
((u64*)SUBSH_MASK)[ 5] = 0x05000e090c04070dULL;\
((u64*)SUBSH_MASK)[ 6] = 0x0a0d040702090c03ULL;\
((u64*)SUBSH_MASK)[ 7] = 0x0601080b0e05000fULL;\
((u64*)SUBSH_MASK)[ 8] = 0x0b0e0500030a0d04ULL;\
((u64*)SUBSH_MASK)[ 9] = 0x0702090c0f060108ULL;\
((u64*)SUBSH_MASK)[10] = 0x0d080601040c0f05ULL;\
((u64*)SUBSH_MASK)[11] = 0x00030b0e0907020aULL;\
((u64*)SUBSH_MASK)[12] = 0x0f0a0702050e0906ULL;\
((u64*)SUBSH_MASK)[13] = 0x01040d080b00030cULL;\
((u64*)SUBSH_MASK)[14] = 0x090c000306080b07ULL;\
((u64*)SUBSH_MASK)[15] = 0x02050f0a0d01040eULL;\
for(i = 0; i < ROUNDS512; i++)\
{\
((u64*)ROUND_CONST_L0)[i*2+1] = 0xffffffffffffffffULL;\
((u64*)ROUND_CONST_L0)[i*2+0] = (i * 0x0101010101010101ULL) ^ 0x7060504030201000ULL;\
((u64*)ROUND_CONST_L7)[i*2+1] = (i * 0x0101010101010101ULL) ^ 0x8f9fafbfcfdfefffULL;\
((u64*)ROUND_CONST_L7)[i*2+0] = 0x0000000000000000ULL;\
}\
((u64*)ROUND_CONST_Lx)[1] = 0xffffffffffffffffULL;\
((u64*)ROUND_CONST_Lx)[0] = 0x0000000000000000ULL;\
}while(0);
#define Push_All_Regs() do{\
/* not using any...
asm("push rax");\
asm("push rbx");\
asm("push rcx");*/\
}while(0);
#define Pop_All_Regs() do{\
/* not using any...
asm("pop rcx");\
asm("pop rbx");\
asm("pop rax");*/\
}while(0);
/* xmm[i] will be multiplied by 2
* xmm[j] will be lost
* xmm[k] has to be all 0x1b
* xmm[z] has to be zero */
#define VMUL2(i, j, k, z){\
asm("vpcmpgtb xmm"tostr(j)", xmm"tostr(z)", xmm"tostr(i)"");\
asm("vpaddb xmm"tostr(i)", xmm"tostr(i)", xmm"tostr(i)"");\
asm("vpand xmm"tostr(j)", xmm"tostr(j)", xmm"tostr(k)"");\
asm("vpxor xmm"tostr(i)", xmm"tostr(i)", xmm"tostr(j)"");\
}/**/
/* xmm[i] will be multiplied by 2
* xmm[j] will be lost
* xmm[k] has to be all 0x1b
* xmm[z] has to be zero */
#define VMUL2v2(i, j, k, z){\
asm("vpblendvb xmm"tostr(j)", xmm"tostr(z)", xmm"tostr(k)", xmm"tostr(i)"");\
asm("vpaddb xmm"tostr(i)", xmm"tostr(i)", xmm"tostr(i)"");\
asm("vpxor xmm"tostr(i)", xmm"tostr(i)", xmm"tostr(j)"");\
}/**/
/* Yet another implementation of MixBytes.
This time we use the formulae (3) from the paper "Byte Slicing Groestl".
Input: a0, ..., a7
Output: b0, ..., b7 = MixBytes(a0,...,a7).
but we use the relations:
t_i = a_i + a_{i+3}
x_i = t_i + t_{i+3}
y_i = t_i + t+{i+2} + a_{i+6}
z_i = 2*x_i
w_i = z_i + y_{i+4}
v_i = 2*w_i
b_i = v_{i+3} + y_{i+4}
We keep building b_i in registers xmm8..xmm15 by first building y_{i+4} there
and then adding v_i computed in the meantime in registers xmm0..xmm7.
We almost fit into 16 registers, need only 3 spills to memory.
This implementation costs 7.7 c/b giving total speed on SNB: 10.7c/b.
K. Matusiewicz, 2011/05/29 */
#define MixBytes(a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\
/* xmm"tostr(8..xmm"tostr(15 = a2 a3... a0 a1 */\
asm("vmovdqa xmm"tostr(b0)", xmm"tostr(a2)"");\
asm("vmovdqa xmm"tostr(b1)", xmm"tostr(a3)"");\
asm("vmovdqa xmm"tostr(b2)", xmm"tostr(a4)"");\
asm("vmovdqa xmm"tostr(b3)", xmm"tostr(a5)"");\
asm("vmovdqa xmm"tostr(b4)", xmm"tostr(a6)"");\
asm("vmovdqa xmm"tostr(b5)", xmm"tostr(a7)"");\
asm("vmovdqa xmm"tostr(b6)", xmm"tostr(a0)"");\
asm("vmovdqa xmm"tostr(b7)", xmm"tostr(a1)"");\
\
/* t_i = a_i + a_{i+1} */\
asm("vpxor xmm"tostr(a0)", xmm"tostr(a0)", xmm"tostr(a1)"");\
asm("vpxor xmm"tostr(a1)", xmm"tostr(a1)", xmm"tostr(a2)"");\
asm("vpxor xmm"tostr(a2)", xmm"tostr(a2)", xmm"tostr(a3)"");\
asm("vpxor xmm"tostr(a3)", xmm"tostr(a3)", xmm"tostr(a4)"");\
asm("vpxor xmm"tostr(a4)", xmm"tostr(a4)", xmm"tostr(a5)"");\
asm("vpxor xmm"tostr(a5)", xmm"tostr(a5)", xmm"tostr(a6)"");\
asm("vpxor xmm"tostr(a6)", xmm"tostr(a6)", xmm"tostr(a7)"");\
asm("vpxor xmm"tostr(a7)", xmm"tostr(a7)", xmm"tostr(b6)"");\
\
/* build y4 y5 y6 ... in regs xmm8, xmm9, xmm10 by adding t_i*/\
asm("vpxor xmm"tostr(b0)", xmm"tostr(b0)", xmm"tostr(a4)"");\
asm("vpxor xmm"tostr(b1)", xmm"tostr(b1)", xmm"tostr(a5)"");\
asm("vpxor xmm"tostr(b2)", xmm"tostr(b2)", xmm"tostr(a6)"");\
asm("vpxor xmm"tostr(b3)", xmm"tostr(b3)", xmm"tostr(a7)"");\
asm("vpxor xmm"tostr(b4)", xmm"tostr(b4)", xmm"tostr(a0)"");\
asm("vpxor xmm"tostr(b5)", xmm"tostr(b5)", xmm"tostr(a1)"");\
asm("vpxor xmm"tostr(b6)", xmm"tostr(b6)", xmm"tostr(a2)"");\
asm("vpxor xmm"tostr(b7)", xmm"tostr(b7)", xmm"tostr(a3)"");\
\
asm("vpxor xmm"tostr(b0)", xmm"tostr(b0)", xmm"tostr(a6)"");\
asm("vpxor xmm"tostr(b1)", xmm"tostr(b1)", xmm"tostr(a7)"");\
asm("vpxor xmm"tostr(b2)", xmm"tostr(b2)", xmm"tostr(a0)"");\
asm("vpxor xmm"tostr(b3)", xmm"tostr(b3)", xmm"tostr(a1)"");\
asm("vpxor xmm"tostr(b4)", xmm"tostr(b4)", xmm"tostr(a2)"");\
asm("vpxor xmm"tostr(b5)", xmm"tostr(b5)", xmm"tostr(a3)"");\
asm("vpxor xmm"tostr(b6)", xmm"tostr(b6)", xmm"tostr(a4)"");\
asm("vpxor xmm"tostr(b7)", xmm"tostr(b7)", xmm"tostr(a5)"");\
\
/* spill values y_4, y_5 to memory */\
asm("vmovaps [TEMP+0*16], xmm"tostr(b0)"");\
asm("vmovaps [TEMP+1*16], xmm"tostr(b1)"");\
asm("vmovaps [TEMP+2*16], xmm"tostr(b2)"");\
\
/* save values t0, t1, t2 to xmm8, xmm9 and memory */\
asm("vmovdqa xmm"tostr(b0)", xmm"tostr(a0)"");\
asm("vmovdqa xmm"tostr(b1)", xmm"tostr(a1)"");\
asm("vmovaps [TEMP+3*16], xmm"tostr(a2)"");\
\
/* compute x_i = t_i + t_{i+3} */\
asm("vpxor xmm"tostr(a0)", xmm"tostr(a0)", xmm"tostr(a3)"");\
asm("vpxor xmm"tostr(a1)", xmm"tostr(a1)", xmm"tostr(a4)"");\
asm("vpxor xmm"tostr(a2)", xmm"tostr(a2)", xmm"tostr(a5)"");\
asm("vpxor xmm"tostr(a3)", xmm"tostr(a3)", xmm"tostr(a6)"");\
asm("vpxor xmm"tostr(a4)", xmm"tostr(a4)", xmm"tostr(a7)"");\
asm("vpxor xmm"tostr(a5)", xmm"tostr(a5)", xmm"tostr(b0)"");\
asm("vpxor xmm"tostr(a6)", xmm"tostr(a6)", xmm"tostr(b1)"");\
asm("vpxor xmm"tostr(a7)", xmm"tostr(a7)", [TEMP+3*16]");\
\
/*compute z_i : double x_i using temp xmm8 and 1B xmm9 */\
asm("vmovaps xmm"tostr(b1)", [ALL_1B]");\
asm("vpxor xmm"tostr(b2)", xmm"tostr(b2)", xmm"tostr(b2)"");\
VMUL2(a7, b0, b1, b2);\
VMUL2(a6, b0, b1, b2);\
VMUL2(a5, b0, b1, b2);\
VMUL2(a4, b0, b1, b2);\
VMUL2(a3, b0, b1, b2);\
VMUL2(a2, b0, b1, b2);\
VMUL2(a1, b0, b1, b2);\
VMUL2(a0, b0, b1, b2);\
\
/* compute w_i : add y_{i+4} */\
asm("vpxor xmm"tostr(a0)", xmm"tostr(a0)", [TEMP+0*16]");\
asm("vpxor xmm"tostr(a1)", xmm"tostr(a1)", [TEMP+1*16]");\
asm("vpxor xmm"tostr(a2)", xmm"tostr(a2)", [TEMP+2*16]");\
asm("vpxor xmm"tostr(a3)", xmm"tostr(a3)", xmm"tostr(b3)"");\
asm("vpxor xmm"tostr(a4)", xmm"tostr(a4)", xmm"tostr(b4)"");\
asm("vpxor xmm"tostr(a5)", xmm"tostr(a5)", xmm"tostr(b5)"");\
asm("vpxor xmm"tostr(a6)", xmm"tostr(a6)", xmm"tostr(b6)"");\
asm("vpxor xmm"tostr(a7)", xmm"tostr(a7)", xmm"tostr(b7)"");\
\
/*compute v_i: double w_i */\
VMUL2(a0, b0, b1, b2);\
VMUL2(a1, b0, b1, b2);\
VMUL2(a2, b0, b1, b2);\
VMUL2(a3, b0, b1, b2);\
VMUL2(a4, b0, b1, b2);\
VMUL2(a5, b0, b1, b2);\
VMUL2(a6, b0, b1, b2);\
VMUL2(a7, b0, b1, b2);\
\
/* add to y_4 y_5 .. v3, v4, ... */\
asm("vpxor xmm"tostr(b0)", xmm"tostr(a3)", [TEMP+0*16]");\
asm("vpxor xmm"tostr(b1)", xmm"tostr(a4)", [TEMP+1*16]");\
asm("vpxor xmm"tostr(b2)", xmm"tostr(a5)", [TEMP+2*16]");\
asm("vpxor xmm"tostr(b3)", xmm"tostr(b3)", xmm"tostr(a6)"");\
asm("vpxor xmm"tostr(b4)", xmm"tostr(b4)", xmm"tostr(a7)"");\
asm("vpxor xmm"tostr(b5)", xmm"tostr(b5)", xmm"tostr(a0)"");\
asm("vpxor xmm"tostr(b6)", xmm"tostr(b6)", xmm"tostr(a1)"");\
asm("vpxor xmm"tostr(b7)", xmm"tostr(b7)", xmm"tostr(a2)"");\
}/*MixBytes*/
/* one round
* i = round number
* a0-a7 = input rows
* b0-b7 = output rows
*/
#define ROUND(i, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\
/* AddRoundConstant */\
asm ("vmovaps xmm"tostr(b1)", [ROUND_CONST_Lx]");\
asm ("vpxor xmm"tostr(a0)", xmm"tostr(a0)", [ROUND_CONST_L0+"tostr(i)"*16]");\
asm ("vpxor xmm"tostr(a1)", xmm"tostr(a1)", xmm"tostr(b1)"");\
asm ("vpxor xmm"tostr(a2)", xmm"tostr(a2)", xmm"tostr(b1)"");\
asm ("vpxor xmm"tostr(a3)", xmm"tostr(a3)", xmm"tostr(b1)"");\
asm ("vpxor xmm"tostr(a4)", xmm"tostr(a4)", xmm"tostr(b1)"");\
asm ("vpxor xmm"tostr(a5)", xmm"tostr(a5)", xmm"tostr(b1)"");\
asm ("vpxor xmm"tostr(a6)", xmm"tostr(a6)", xmm"tostr(b1)"");\
asm ("vpxor xmm"tostr(a7)", xmm"tostr(a7)", [ROUND_CONST_L7+"tostr(i)"*16]");\
/* ShiftBytes + SubBytes (interleaved) */\
asm ("vpxor xmm"tostr(b0)", xmm"tostr(b0)", xmm"tostr(b0)"");\
asm ("vpshufb xmm"tostr(a0)", xmm"tostr(a0)", [SUBSH_MASK+0*16]");\
asm ("vaesenclast xmm"tostr(a0)", xmm"tostr(a0)", xmm"tostr(b0)"");\
asm ("vpshufb xmm"tostr(a1)", xmm"tostr(a1)", [SUBSH_MASK+1*16]");\
asm ("vaesenclast xmm"tostr(a1)", xmm"tostr(a1)", xmm"tostr(b0)"");\
asm ("vpshufb xmm"tostr(a2)", xmm"tostr(a2)", [SUBSH_MASK+2*16]");\
asm ("vaesenclast xmm"tostr(a2)", xmm"tostr(a2)", xmm"tostr(b0)"");\
asm ("vpshufb xmm"tostr(a3)", xmm"tostr(a3)", [SUBSH_MASK+3*16]");\
asm ("vaesenclast xmm"tostr(a3)", xmm"tostr(a3)", xmm"tostr(b0)"");\
asm ("vpshufb xmm"tostr(a4)", xmm"tostr(a4)", [SUBSH_MASK+4*16]");\
asm ("vaesenclast xmm"tostr(a4)", xmm"tostr(a4)", xmm"tostr(b0)"");\
asm ("vpshufb xmm"tostr(a5)", xmm"tostr(a5)", [SUBSH_MASK+5*16]");\
asm ("vaesenclast xmm"tostr(a5)", xmm"tostr(a5)", xmm"tostr(b0)"");\
asm ("vpshufb xmm"tostr(a6)", xmm"tostr(a6)", [SUBSH_MASK+6*16]");\
asm ("vaesenclast xmm"tostr(a6)", xmm"tostr(a6)", xmm"tostr(b0)"");\
asm ("vpshufb xmm"tostr(a7)", xmm"tostr(a7)", [SUBSH_MASK+7*16]");\
asm ("vaesenclast xmm"tostr(a7)", xmm"tostr(a7)", xmm"tostr(b0)"");\
/* MixBytes */\
MixBytes(a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7);\
}
/* 10 rounds, P and Q in parallel */
#define ROUNDS_P_Q(){\
ROUND(0, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
ROUND(2, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(3, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
ROUND(4, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(5, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
ROUND(6, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
ROUND(8, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
}
/* Matrix Transpose Step 1
* input is a 512-bit state with two columns in one xmm
* output is a 512-bit state with two rows in one xmm
* inputs: i0-i3
* outputs: i0, o1-o3
* clobbers: t0
*/
#define Matrix_Transpose_A(i0, i1, i2, i3, o1, o2, o3, t0){\
asm ("vmovaps xmm"tostr(t0)", [TRANSP_MASK]");\
\
asm ("vpshufb xmm"tostr(i0)", xmm"tostr(i0)", xmm"tostr(t0)"");\
asm ("vpshufb xmm"tostr(i1)", xmm"tostr(i1)", xmm"tostr(t0)"");\
asm ("vpshufb xmm"tostr(i2)", xmm"tostr(i2)", xmm"tostr(t0)"");\
asm ("vpshufb xmm"tostr(i3)", xmm"tostr(i3)", xmm"tostr(t0)"");\
\
asm ("vpunpckhwd xmm"tostr(o1)", xmm"tostr(i0)", xmm"tostr(i1)"");\
asm ("vpunpcklwd xmm"tostr(i0)", xmm"tostr(i0)", xmm"tostr(i1)"");\
asm ("vpunpckhwd xmm"tostr(t0)", xmm"tostr(i2)", xmm"tostr(i3)"");\
asm ("vpunpcklwd xmm"tostr(i2)", xmm"tostr(i2)", xmm"tostr(i3)"");\
\
asm ("vpshufd xmm"tostr(i0)", xmm"tostr(i0)", 216");\
asm ("vpshufd xmm"tostr(o1)", xmm"tostr(o1)", 216");\
asm ("vpshufd xmm"tostr(i2)", xmm"tostr(i2)", 216");\
asm ("vpshufd xmm"tostr(t0)", xmm"tostr(t0)", 216");\
\
asm ("vpunpckhdq xmm"tostr(o2)", xmm"tostr(i0)", xmm"tostr(i2)"");\
asm ("vpunpckhdq xmm"tostr(o3)", xmm"tostr(o1)", xmm"tostr(t0)"");\
asm ("vpunpckldq xmm"tostr(i0)", xmm"tostr(i0)", xmm"tostr(i2)"");\
asm ("vpunpckldq xmm"tostr(o1)", xmm"tostr(o1)", xmm"tostr(t0)"");\
}/**/
/* Matrix Transpose Step 2
* input are two 512-bit states with two rows in one xmm
* output are two 512-bit states with one row of each state in one xmm
* inputs: i0-i3 = P, i4-i7 = Q
* outputs: (i0, o1-o7) = (P|Q)
* possible reassignments: (output reg = input reg)
* * i1 -> o3-7
* * i2 -> o5-7
* * i3 -> o7
* * i4 -> o3-7
* * i5 -> o6-7
*/
#define Matrix_Transpose_B(i0, i1, i2, i3, i4, i5, i6, i7, o1, o2, o3, o4, o5, o6, o7){\
asm ("vpunpckhqdq xmm"tostr(o1)", xmm"tostr(i0)", xmm"tostr(i4)"");\
asm ("vpunpcklqdq xmm"tostr(i0)", xmm"tostr(i0)", xmm"tostr(i4)"");\
asm ("vpunpcklqdq xmm"tostr(o2)", xmm"tostr(i1)", xmm"tostr(i5)"");\
asm ("vpunpckhqdq xmm"tostr(o3)", xmm"tostr(i1)", xmm"tostr(i5)"");\
asm ("vpunpcklqdq xmm"tostr(o4)", xmm"tostr(i2)", xmm"tostr(i6)"");\
asm ("vpunpckhqdq xmm"tostr(o5)", xmm"tostr(i2)", xmm"tostr(i6)"");\
asm ("vpunpcklqdq xmm"tostr(o6)", xmm"tostr(i3)", xmm"tostr(i7)"");\
asm ("vpunpckhqdq xmm"tostr(o7)", xmm"tostr(i3)", xmm"tostr(i7)"");\
}/**/
/* Matrix Transpose Inverse Step 2
* input are two 512-bit states with one row of each state in one xmm
* output are two 512-bit states with two rows in one xmm
* inputs: i0-i7 = (P|Q)
* outputs: (i0, i2, i4, i6) = P, (o0-o3) = Q
*/
#define Matrix_Transpose_B_INV(i0, i1, i2, i3, i4, i5, i6, i7, o0, o1, o2, o3){\
asm ("vpunpckhqdq xmm"tostr(o0)", xmm"tostr(i0)", xmm"tostr(i1)"");\
asm ("vpunpcklqdq xmm"tostr(i0)", xmm"tostr(i0)", xmm"tostr(i1)"");\
asm ("vpunpckhqdq xmm"tostr(o1)", xmm"tostr(i2)", xmm"tostr(i3)"");\
asm ("vpunpcklqdq xmm"tostr(i2)", xmm"tostr(i2)", xmm"tostr(i3)"");\
asm ("vpunpckhqdq xmm"tostr(o2)", xmm"tostr(i4)", xmm"tostr(i5)"");\
asm ("vpunpcklqdq xmm"tostr(i4)", xmm"tostr(i4)", xmm"tostr(i5)"");\
asm ("vpunpckhqdq xmm"tostr(o3)", xmm"tostr(i6)", xmm"tostr(i7)"");\
asm ("vpunpcklqdq xmm"tostr(i6)", xmm"tostr(i6)", xmm"tostr(i7)"");\
}/**/
/* Matrix Transpose Output Step 2
* input is one 512-bit state with two rows in one xmm
* output is one 512-bit state with one row in the low 64-bits of one xmm
* inputs: i0,i2,i4,i6 = S
* outputs: (i0-7) = (0|S)
*/
#define Matrix_Transpose_O_B(i0, i1, i2, i3, i4, i5, i6, i7, t0){\
asm ("vpxor xmm"tostr(t0)", xmm"tostr(t0)", xmm"tostr(t0)"");\
asm ("vpunpckhqdq xmm"tostr(i1)", xmm"tostr(i0)", xmm"tostr(t0)"");\
asm ("vpunpcklqdq xmm"tostr(i0)", xmm"tostr(i0)", xmm"tostr(t0)"");\
asm ("vpunpckhqdq xmm"tostr(i3)", xmm"tostr(i2)", xmm"tostr(t0)"");\
asm ("vpunpcklqdq xmm"tostr(i2)", xmm"tostr(i2)", xmm"tostr(t0)"");\
asm ("vpunpckhqdq xmm"tostr(i5)", xmm"tostr(i4)", xmm"tostr(t0)"");\
asm ("vpunpcklqdq xmm"tostr(i4)", xmm"tostr(i4)", xmm"tostr(t0)"");\
asm ("vpunpckhqdq xmm"tostr(i7)", xmm"tostr(i6)", xmm"tostr(t0)"");\
asm ("vpunpcklqdq xmm"tostr(i6)", xmm"tostr(i6)", xmm"tostr(t0)"");\
}/**/
/* Matrix Transpose Output Inverse Step 2
* input is one 512-bit state with one row in the low 64-bits of one xmm
* output is one 512-bit state with two rows in one xmm
* inputs: i0-i7 = (0|S)
* outputs: (i0, i2, i4, i6) = S
*/
#define Matrix_Transpose_O_B_INV(i0, i1, i2, i3, i4, i5, i6, i7){\
asm ("vpunpcklqdq xmm"tostr(i0)", xmm"tostr(i0)", xmm"tostr(i1)"");\
asm ("vpunpcklqdq xmm"tostr(i2)", xmm"tostr(i2)", xmm"tostr(i3)"");\
asm ("vpunpcklqdq xmm"tostr(i4)", xmm"tostr(i4)", xmm"tostr(i5)"");\
asm ("vpunpcklqdq xmm"tostr(i6)", xmm"tostr(i6)", xmm"tostr(i7)"");\
}/**/
void INIT256(u64* h)
{
/* __cdecl calling convention: */
/* chaining value CV in rdi */
asm (".intel_syntax noprefix");
asm volatile ("emms");
/* load IV into registers xmm12 - xmm15 */
asm ("vmovaps xmm12, [rdi+0*16]");
asm ("vmovaps xmm13, [rdi+1*16]");
asm ("vmovaps xmm14, [rdi+2*16]");
asm ("vmovaps xmm15, [rdi+3*16]");
/* transform chaining value from column ordering into row ordering */
/* we put two rows (64 bit) of the IV into one 128-bit XMM register */
Matrix_Transpose_A(12, 13, 14, 15, 2, 6, 7, 0);
/* store transposed IV */
asm ("vmovaps [rdi+0*16], xmm12");
asm ("vmovaps [rdi+1*16], xmm2");
asm ("vmovaps [rdi+2*16], xmm6");
asm ("vmovaps [rdi+3*16], xmm7");
asm volatile ("emms");
asm (".att_syntax noprefix");
}
void TF512(u64* h, u64* m)
{
/* __cdecl calling convention: */
/* chaining value CV in rdi */
/* message M in rsi */
#ifdef IACA_TRACE
IACA_START;
#endif
asm (".intel_syntax noprefix");
Push_All_Regs();
/* load message into registers xmm12 - xmm15 (Q = message) */
asm ("vmovaps xmm12, [rsi+0*16]");
asm ("vmovaps xmm13, [rsi+1*16]");
asm ("vmovaps xmm14, [rsi+2*16]");
asm ("vmovaps xmm15, [rsi+3*16]");
/* transform message M from column ordering into row ordering */
/* we first put two rows (64 bit) of the message into one 128-bit xmm register */
Matrix_Transpose_A(12, 13, 14, 15, 2, 6, 7, 0);
/* load previous chaining value and xor message to CV to get input of P */
/* we first put two rows (2x64 bit) of the CV into one 128-bit xmm register */
/* result: CV+M in xmm8, xmm0, xmm4, xmm5 */
asm ("vpxor xmm8, xmm12, [rdi+0*16]");
asm ("vpxor xmm0, xmm2, [rdi+1*16]");
asm ("vpxor xmm4, xmm6, [rdi+2*16]");
asm ("vpxor xmm5, xmm7, [rdi+3*16]");
/* there are now 2 rows of the Groestl state (P and Q) in each xmm register */
/* unpack to get 1 row of P (64 bit) and Q (64 bit) into one xmm register */
/* result: the 8 rows of P and Q in xmm8 - xmm12 */
Matrix_Transpose_B(8, 0, 4, 5, 12, 2, 6, 7, 9, 10, 11, 12, 13, 14, 15);
/* compute the two permutations P and Q in parallel */
ROUNDS_P_Q();
/* unpack again to get two rows of P or two rows of Q in one xmm register */
Matrix_Transpose_B_INV(8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3);
/* xor output of P and Q */
/* result: P(CV+M)+Q(M) in xmm0...xmm3 */
asm ("vpxor xmm0, xmm0, xmm8");
asm ("vpxor xmm1, xmm1, xmm10");
asm ("vpxor xmm2, xmm2, xmm12");
asm ("vpxor xmm3, xmm3, xmm14");
/* xor CV (feed-forward) */
/* result: P(CV+M)+Q(M)+CV in xmm0...xmm3 */
asm ("vpxor xmm0, xmm0, [rdi+0*16]");
asm ("vpxor xmm1, xmm1, [rdi+1*16]");
asm ("vpxor xmm2, xmm2, [rdi+2*16]");
asm ("vpxor xmm3, xmm3, [rdi+3*16]");
/* store CV */
asm ("vmovaps [rdi+0*16], xmm0");
asm ("vmovaps [rdi+1*16], xmm1");
asm ("vmovaps [rdi+2*16], xmm2");
asm ("vmovaps [rdi+3*16], xmm3");
Pop_All_Regs();
asm (".att_syntax noprefix");
#ifdef IACA_TRACE
IACA_END;
#endif
return;
}
void OF512(u64* h)
{
/* __cdecl calling convention: */
/* chaining value CV in rdi */
asm (".intel_syntax noprefix");
Push_All_Regs();
/* load CV into registers xmm8, xmm10, xmm12, xmm14 */
asm ("vmovaps xmm8, [rdi+0*16]");
asm ("vmovaps xmm10, [rdi+1*16]");
asm ("vmovaps xmm12, [rdi+2*16]");
asm ("vmovaps xmm14, [rdi+3*16]");
/* there are now 2 rows of the CV in one xmm register */
/* unpack to get 1 row of P (64 bit) into one half of an xmm register */
/* result: the 8 input rows of P in xmm8 - xmm15 */
Matrix_Transpose_O_B(8, 9, 10, 11, 12, 13, 14, 15, 0);
/* compute the permutation P */
/* result: the output of P(CV) in xmm8 - xmm15 */
ROUNDS_P_Q();
/* unpack again to get two rows of P in one xmm register */
/* result: P(CV) in xmm8, xmm10, xmm12, xmm14 */
Matrix_Transpose_O_B_INV(8, 9, 10, 11, 12, 13, 14, 15);
/* xor CV to P output (feed-forward) */
/* result: P(CV)+CV in xmm8, xmm10, xmm12, xmm14 */
asm ("vpxor xmm8, xmm8, [rdi+0*16]");
asm ("vpxor xmm10, xmm10, [rdi+1*16]");
asm ("vpxor xmm12, xmm12, [rdi+2*16]");
asm ("vpxor xmm14, xmm14, [rdi+3*16]");
/* transform state back from row ordering into column ordering */
/* result: final hash value in xmm9, xmm11 */
Matrix_Transpose_A(8, 10, 12, 14, 4, 9, 11, 0);
/* we only need to return the truncated half of the state */
asm ("vmovaps [rdi+2*16], xmm9");
asm ("vmovaps [rdi+3*16], xmm11");
Pop_All_Regs();
asm (".att_syntax noprefix");
return;
}

View File

@@ -1,856 +0,0 @@
/* groestl-asm-vperm.h Aug 2011
*
* Groestl implementation with inline assembly using ssse3 instructions.
* Author: Günther A. Roland, Martin Schläffer, Krystian Matusiewicz
*
* Based on the vperm and aes_ni implementations of the hash function Groestl
* by Cagdas Calik <ccalik@metu.edu.tr> http://www.metu.edu.tr/~ccalik/
* Institute of Applied Mathematics, Middle East Technical University, Turkey
*
* This code is placed in the public domain
*/
#include "hash-groestl256.h"
/* global constants */
__attribute__ ((aligned (16))) unsigned char ROUND_CONST_Lx[16];
__attribute__ ((aligned (16))) unsigned char ROUND_CONST_L0[ROUNDS512*16];
__attribute__ ((aligned (16))) unsigned char ROUND_CONST_L7[ROUNDS512*16];
__attribute__ ((aligned (16))) unsigned char ROUND_CONST_P[ROUNDS1024*16];
__attribute__ ((aligned (16))) unsigned char ROUND_CONST_Q[ROUNDS1024*16];
__attribute__ ((aligned (16))) unsigned char TRANSP_MASK[16];
__attribute__ ((aligned (16))) unsigned char SUBSH_MASK[8*16];
__attribute__ ((aligned (16))) unsigned char ALL_0F[16];
__attribute__ ((aligned (16))) unsigned char ALL_15[16];
__attribute__ ((aligned (16))) unsigned char ALL_1B[16];
__attribute__ ((aligned (16))) unsigned char ALL_63[16];
__attribute__ ((aligned (16))) unsigned char ALL_FF[16];
__attribute__ ((aligned (16))) unsigned char VPERM_IPT[2*16];
__attribute__ ((aligned (16))) unsigned char VPERM_OPT[2*16];
__attribute__ ((aligned (16))) unsigned char VPERM_INV[2*16];
__attribute__ ((aligned (16))) unsigned char VPERM_SB1[2*16];
__attribute__ ((aligned (16))) unsigned char VPERM_SB2[2*16];
__attribute__ ((aligned (16))) unsigned char VPERM_SB4[2*16];
__attribute__ ((aligned (16))) unsigned char VPERM_SBO[2*16];
/* temporary variables */
__attribute__ ((aligned (16))) unsigned char TEMP_MUL1[8*16];
__attribute__ ((aligned (16))) unsigned char TEMP_MUL2[8*16];
__attribute__ ((aligned (16))) unsigned char TEMP_MUL4[1*16];
__attribute__ ((aligned (16))) unsigned char QTEMP[8*16];
__attribute__ ((aligned (16))) unsigned char TEMP[8*16];
#define tos(a) #a
#define tostr(a) tos(a)
#define SET_SHARED_CONSTANTS(){\
((u64*)TRANSP_MASK)[0] = 0x0d0509010c040800ULL;\
((u64*)TRANSP_MASK)[1] = 0x0f070b030e060a02ULL;\
((u64*)ALL_1B)[0] = 0x1b1b1b1b1b1b1b1bULL;\
((u64*)ALL_1B)[1] = 0x1b1b1b1b1b1b1b1bULL;\
((u64*)ALL_63)[ 0] = 0x6363636363636363ULL;\
((u64*)ALL_63)[ 1] = 0x6363636363636363ULL;\
((u64*)ALL_0F)[ 0] = 0x0F0F0F0F0F0F0F0FULL;\
((u64*)ALL_0F)[ 1] = 0x0F0F0F0F0F0F0F0FULL;\
((u64*)VPERM_IPT)[ 0] = 0x4C01307D317C4D00ULL;\
((u64*)VPERM_IPT)[ 1] = 0xCD80B1FCB0FDCC81ULL;\
((u64*)VPERM_IPT)[ 2] = 0xC2B2E8985A2A7000ULL;\
((u64*)VPERM_IPT)[ 3] = 0xCABAE09052227808ULL;\
((u64*)VPERM_OPT)[ 0] = 0x01EDBD5150BCEC00ULL;\
((u64*)VPERM_OPT)[ 1] = 0xE10D5DB1B05C0CE0ULL;\
((u64*)VPERM_OPT)[ 2] = 0xFF9F4929D6B66000ULL;\
((u64*)VPERM_OPT)[ 3] = 0xF7974121DEBE6808ULL;\
((u64*)VPERM_INV)[ 0] = 0x01040A060F0B0780ULL;\
((u64*)VPERM_INV)[ 1] = 0x030D0E0C02050809ULL;\
((u64*)VPERM_INV)[ 2] = 0x0E05060F0D080180ULL;\
((u64*)VPERM_INV)[ 3] = 0x040703090A0B0C02ULL;\
((u64*)VPERM_SB1)[ 0] = 0x3618D415FAE22300ULL;\
((u64*)VPERM_SB1)[ 1] = 0x3BF7CCC10D2ED9EFULL;\
((u64*)VPERM_SB1)[ 2] = 0xB19BE18FCB503E00ULL;\
((u64*)VPERM_SB1)[ 3] = 0xA5DF7A6E142AF544ULL;\
((u64*)VPERM_SB2)[ 0] = 0x69EB88400AE12900ULL;\
((u64*)VPERM_SB2)[ 1] = 0xC2A163C8AB82234AULL;\
((u64*)VPERM_SB2)[ 2] = 0xE27A93C60B712400ULL;\
((u64*)VPERM_SB2)[ 3] = 0x5EB7E955BC982FCDULL;\
((u64*)VPERM_SB4)[ 0] = 0x3D50AED7C393EA00ULL;\
((u64*)VPERM_SB4)[ 1] = 0xBA44FE79876D2914ULL;\
((u64*)VPERM_SB4)[ 2] = 0xE1E937A03FD64100ULL;\
((u64*)VPERM_SB4)[ 3] = 0xA876DE9749087E9FULL;\
/*((u64*)VPERM_SBO)[ 0] = 0xCFE474A55FBB6A00ULL;\
((u64*)VPERM_SBO)[ 1] = 0x8E1E90D1412B35FAULL;\
((u64*)VPERM_SBO)[ 2] = 0xD0D26D176FBDC700ULL;\
((u64*)VPERM_SBO)[ 3] = 0x15AABF7AC502A878ULL;*/\
((u64*)ALL_15)[ 0] = 0x1515151515151515ULL;\
((u64*)ALL_15)[ 1] = 0x1515151515151515ULL;\
}/**/
/* VPERM
* Transform w/o settings c*
* transforms 2 rows to/from "vperm mode"
* this function is derived from:
* vperm and aes_ni implementations of hash function Grostl
* by Cagdas CALIK
* inputs:
* a0, a1 = 2 rows
* table = transformation table to use
* t*, c* = clobbers
* outputs:
* a0, a1 = 2 rows transformed with table
* */
#define VPERM_Transform_No_Const(a0, a1, t0, t1, t2, t3, c0, c1, c2){\
asm ("movdqa xmm"tostr(t0)", xmm"tostr(c0)"");\
asm ("movdqa xmm"tostr(t1)", xmm"tostr(c0)"");\
asm ("pandn xmm"tostr(t0)", xmm"tostr(a0)"");\
asm ("pandn xmm"tostr(t1)", xmm"tostr(a1)"");\
asm ("psrld xmm"tostr(t0)", 4");\
asm ("psrld xmm"tostr(t1)", 4");\
asm ("pand xmm"tostr(a0)", xmm"tostr(c0)"");\
asm ("pand xmm"tostr(a1)", xmm"tostr(c0)"");\
asm ("movdqa xmm"tostr(t2)", xmm"tostr(c2)"");\
asm ("movdqa xmm"tostr(t3)", xmm"tostr(c2)"");\
asm ("pshufb xmm"tostr(t2)", xmm"tostr(a0)"");\
asm ("pshufb xmm"tostr(t3)", xmm"tostr(a1)"");\
asm ("movdqa xmm"tostr(a0)", xmm"tostr(c1)"");\
asm ("movdqa xmm"tostr(a1)", xmm"tostr(c1)"");\
asm ("pshufb xmm"tostr(a0)", xmm"tostr(t0)"");\
asm ("pshufb xmm"tostr(a1)", xmm"tostr(t1)"");\
asm ("pxor xmm"tostr(a0)", xmm"tostr(t2)"");\
asm ("pxor xmm"tostr(a1)", xmm"tostr(t3)"");\
}/**/
#define VPERM_Transform_Set_Const(table, c0, c1, c2){\
asm ("movaps xmm"tostr(c0)", [ALL_0F]");\
asm ("movaps xmm"tostr(c1)", ["tostr(table)"+0*16]");\
asm ("movaps xmm"tostr(c2)", ["tostr(table)"+1*16]");\
}/**/
/* VPERM
* Transform
* transforms 2 rows to/from "vperm mode"
* this function is derived from:
* vperm and aes_ni implementations of hash function Grostl
* by Cagdas CALIK
* inputs:
* a0, a1 = 2 rows
* table = transformation table to use
* t*, c* = clobbers
* outputs:
* a0, a1 = 2 rows transformed with table
* */
#define VPERM_Transform(a0, a1, table, t0, t1, t2, t3, c0, c1, c2){\
VPERM_Transform_Set_Const(table, c0, c1, c2);\
VPERM_Transform_No_Const(a0, a1, t0, t1, t2, t3, c0, c1, c2);\
}/**/
/* VPERM
* Transform State
* inputs:
* a0-a3 = state
* table = transformation table to use
* t* = clobbers
* outputs:
* a0-a3 = transformed state
* */
#define VPERM_Transform_State(a0, a1, a2, a3, table, t0, t1, t2, t3, c0, c1, c2){\
VPERM_Transform_Set_Const(table, c0, c1, c2);\
VPERM_Transform_No_Const(a0, a1, t0, t1, t2, t3, c0, c1, c2);\
VPERM_Transform_No_Const(a2, a3, t0, t1, t2, t3, c0, c1, c2);\
}/**/
/* VPERM
* Add Constant to State
* inputs:
* a0-a7 = state
* constant = constant to add
* t0 = clobber
* outputs:
* a0-a7 = state + constant
* */
#define VPERM_Add_Constant(a0, a1, a2, a3, a4, a5, a6, a7, constant, t0){\
asm ("movaps xmm"tostr(t0)", ["tostr(constant)"]");\
asm ("pxor xmm"tostr(a0)", xmm"tostr(t0)"");\
asm ("pxor xmm"tostr(a1)", xmm"tostr(t0)"");\
asm ("pxor xmm"tostr(a2)", xmm"tostr(t0)"");\
asm ("pxor xmm"tostr(a3)", xmm"tostr(t0)"");\
asm ("pxor xmm"tostr(a4)", xmm"tostr(t0)"");\
asm ("pxor xmm"tostr(a5)", xmm"tostr(t0)"");\
asm ("pxor xmm"tostr(a6)", xmm"tostr(t0)"");\
asm ("pxor xmm"tostr(a7)", xmm"tostr(t0)"");\
}/**/
/* VPERM
* Set Substitute Core Constants
* */
#define VPERM_Substitute_Core_Set_Const(c0, c1, c2){\
VPERM_Transform_Set_Const(VPERM_INV, c0, c1, c2);\
}/**/
/* VPERM
* Substitute Core
* first part of sbox inverse computation
* this function is derived from:
* vperm and aes_ni implementations of hash function Grostl
* by Cagdas CALIK
* inputs:
* a0 = 1 row
* t*, c* = clobbers
* outputs:
* b0a, b0b = inputs for lookup step
* */
#define VPERM_Substitute_Core(a0, b0a, b0b, t0, t1, c0, c1, c2){\
asm ("movdqa xmm"tostr(t0)", xmm"tostr(c0)"");\
asm ("pandn xmm"tostr(t0)", xmm"tostr(a0)"");\
asm ("psrld xmm"tostr(t0)", 4");\
asm ("pand xmm"tostr(a0)", xmm"tostr(c0)"");\
asm ("movdqa xmm"tostr(b0a)", "tostr(c1)"");\
asm ("pshufb xmm"tostr(b0a)", xmm"tostr(a0)"");\
asm ("pxor xmm"tostr(a0)", xmm"tostr(t0)"");\
asm ("movdqa xmm"tostr(b0b)", xmm"tostr(c2)"");\
asm ("pshufb xmm"tostr(b0b)", xmm"tostr(t0)"");\
asm ("pxor xmm"tostr(b0b)", xmm"tostr(b0a)"");\
asm ("movdqa xmm"tostr(t1)", xmm"tostr(c2)"");\
asm ("pshufb xmm"tostr(t1)", xmm"tostr(a0)"");\
asm ("pxor xmm"tostr(t1)", xmm"tostr(b0a)"");\
asm ("movdqa xmm"tostr(b0a)", xmm"tostr(c2)"");\
asm ("pshufb xmm"tostr(b0a)", xmm"tostr(b0b)"");\
asm ("pxor xmm"tostr(b0a)", xmm"tostr(a0)"");\
asm ("movdqa xmm"tostr(b0b)", xmm"tostr(c2)"");\
asm ("pshufb xmm"tostr(b0b)", xmm"tostr(t1)"");\
asm ("pxor xmm"tostr(b0b)", xmm"tostr(t0)"");\
}/**/
/* VPERM
* Lookup
* second part of sbox inverse computation
* this function is derived from:
* vperm and aes_ni implementations of hash function Grostl
* by Cagdas CALIK
* inputs:
* a0a, a0b = output of Substitution Core
* table = lookup table to use (*1 / *2 / *4)
* t0 = clobber
* outputs:
* b0 = output of sbox + multiplication
* */
#define VPERM_Lookup(a0a, a0b, table, b0, t0){\
asm ("movaps xmm"tostr(b0)", ["tostr(table)"+0*16]");\
asm ("movaps xmm"tostr(t0)", ["tostr(table)"+1*16]");\
asm ("pshufb xmm"tostr(b0)", xmm"tostr(a0b)"");\
asm ("pshufb xmm"tostr(t0)", xmm"tostr(a0a)"");\
asm ("pxor xmm"tostr(b0)", xmm"tostr(t0)"");\
}/**/
/* VPERM
* SubBytes and *2 / *4
* this function is derived from:
* Constant-time SSSE3 AES core implementation
* by Mike Hamburg
* and
* vperm and aes_ni implementations of hash function Grostl
* by Cagdas CALIK
* inputs:
* a0-a7 = state
* t*, c* = clobbers
* outputs:
* a0-a7 = state * 4
* c2 = row0 * 2 -> b0
* c1 = row7 * 2 -> b3
* c0 = row7 * 1 -> b4
* t2 = row4 * 1 -> b7
* TEMP_MUL1 = row(i) * 1
* TEMP_MUL2 = row(i) * 2
*
* call:VPERM_SUB_MULTIPLY(a0, a1, a2, a3, a4, a5, a6, a7, b1, b2, b5, b6, b0, b3, b4, b7) */
#define VPERM_SUB_MULTIPLY(a0, a1, a2, a3, a4, a5, a6, a7, t0, t1, t3, t4, c2, c1, c0, t2){\
/* set Constants */\
VPERM_Substitute_Core_Set_Const(c0, c1, c2);\
/* row 1 */\
VPERM_Substitute_Core(a1, t0, t1, t3, t4, c0, xmm##c1, c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, t2, t4);\
asm ("movaps [TEMP_MUL1+1*16], xmm"tostr(t2)"");\
VPERM_Lookup(t0, t1, VPERM_SB2, t3, t4);\
asm ("movaps [TEMP_MUL2+1*16], xmm"tostr(t3)"");\
VPERM_Lookup(t0, t1, VPERM_SB4, a1, t4);\
/* --- */\
/* row 2 */\
VPERM_Substitute_Core(a2, t0, t1, t3, t4, c0, xmm##c1, c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, t2, t4);\
asm ("movaps [TEMP_MUL1+2*16], xmm"tostr(t2)"");\
VPERM_Lookup(t0, t1, VPERM_SB2, t3, t4);\
asm ("movaps [TEMP_MUL2+2*16], xmm"tostr(t3)"");\
VPERM_Lookup(t0, t1, VPERM_SB4, a2, t4);\
/* --- */\
/* row 3 */\
VPERM_Substitute_Core(a3, t0, t1, t3, t4, c0, xmm##c1, c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, t2, t4);\
asm ("movaps [TEMP_MUL1+3*16], xmm"tostr(t2)"");\
VPERM_Lookup(t0, t1, VPERM_SB2, t3, t4);\
asm ("movaps [TEMP_MUL2+3*16], xmm"tostr(t3)"");\
VPERM_Lookup(t0, t1, VPERM_SB4, a3, t4);\
/* --- */\
/* row 5 */\
VPERM_Substitute_Core(a5, t0, t1, t3, t4, c0, xmm##c1, c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, t2, t4);\
asm ("movaps [TEMP_MUL1+5*16], xmm"tostr(t2)"");\
VPERM_Lookup(t0, t1, VPERM_SB2, t3, t4);\
asm ("movaps [TEMP_MUL2+5*16], xmm"tostr(t3)"");\
VPERM_Lookup(t0, t1, VPERM_SB4, a5, t4);\
/* --- */\
/* row 6 */\
VPERM_Substitute_Core(a6, t0, t1, t3, t4, c0, xmm##c1, c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, t2, t4);\
asm ("movaps [TEMP_MUL1+6*16], xmm"tostr(t2)"");\
VPERM_Lookup(t0, t1, VPERM_SB2, t3, t4);\
asm ("movaps [TEMP_MUL2+6*16], xmm"tostr(t3)"");\
VPERM_Lookup(t0, t1, VPERM_SB4, a6, t4);\
/* --- */\
/* row 7 */\
VPERM_Substitute_Core(a7, t0, t1, t3, t4, c0, xmm##c1, c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, t2, t4);\
asm ("movaps [TEMP_MUL1+7*16], xmm"tostr(t2)"");\
VPERM_Lookup(t0, t1, VPERM_SB2, c1, t4); /*c1 -> b3*/\
VPERM_Lookup(t0, t1, VPERM_SB4, a7, t4);\
/* --- */\
/* row 4 */\
VPERM_Substitute_Core(a4, t0, t1, t3, t4, c0, [VPERM_INV+0*16], c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, t2, t4); /*t2 -> b7*/\
VPERM_Lookup(t0, t1, VPERM_SB2, t3, t4);\
asm ("movaps [TEMP_MUL2+4*16], xmm"tostr(t3)"");\
VPERM_Lookup(t0, t1, VPERM_SB4, a4, t4);\
/* --- */\
/* row 0 */\
VPERM_Substitute_Core(a0, t0, t1, t3, t4, c0, [VPERM_INV+0*16], c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, c0, t4); /*c0 -> b4*/\
VPERM_Lookup(t0, t1, VPERM_SB2, c2, t4); /*c2 -> b0*/\
asm ("movaps [TEMP_MUL2+0*16], xmm"tostr(c2)"");\
VPERM_Lookup(t0, t1, VPERM_SB4, a0, t4);\
/* --- */\
}/**/
/* Optimized MixBytes
* inputs:
* a0-a7 = (row0-row7) * 4
* b0 = row0 * 2
* b3 = row7 * 2
* b4 = row7 * 1
* b7 = row4 * 1
* all *1 and *2 values must also be in TEMP_MUL1, TEMP_MUL2
* output: b0-b7
* */
#define MixBytes(a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\
/* save one value */\
asm ("movaps [TEMP_MUL4], xmm"tostr(a3)"");\
/* 1 */\
asm ("movdqa xmm"tostr(b1)", xmm"tostr(a0)"");\
asm ("pxor xmm"tostr(b1)", xmm"tostr(a5)"");\
asm ("pxor xmm"tostr(b1)", xmm"tostr(b4)""); /* -> helper! */\
asm ("pxor xmm"tostr(b1)", [TEMP_MUL2+3*16]");\
asm ("movdqa xmm"tostr(b2)", xmm"tostr(b1)"");\
\
/* 2 */\
asm ("movdqa xmm"tostr(b5)", xmm"tostr(a1)"");\
asm ("pxor xmm"tostr(b5)", xmm"tostr(a4)"");\
asm ("pxor xmm"tostr(b5)", xmm"tostr(b7)""); /* -> helper! */\
asm ("pxor xmm"tostr(b5)", xmm"tostr(b3)""); /* -> helper! */\
asm ("movdqa xmm"tostr(b6)", xmm"tostr(b5)"");\
\
/* 4 */\
asm ("pxor xmm"tostr(b7)", xmm"tostr(a6)"");\
/*asm ("pxor xmm"tostr(b7)", [TEMP_MUL1+4*16]"); -> helper! */\
asm ("pxor xmm"tostr(b7)", [TEMP_MUL1+6*16]");\
asm ("pxor xmm"tostr(b7)", [TEMP_MUL2+1*16]");\
asm ("pxor xmm"tostr(b7)", xmm"tostr(b3)""); /* -> helper! */\
asm ("pxor xmm"tostr(b2)", xmm"tostr(b7)"");\
\
/* 3 */\
asm ("pxor xmm"tostr(b0)", xmm"tostr(a7)"");\
asm ("pxor xmm"tostr(b0)", [TEMP_MUL1+5*16]");\
asm ("pxor xmm"tostr(b0)", [TEMP_MUL1+7*16]");\
/*asm ("pxor xmm"tostr(b0)", [TEMP_MUL2+0*16]"); -> helper! */\
asm ("pxor xmm"tostr(b0)", [TEMP_MUL2+2*16]");\
asm ("movdqa xmm"tostr(b3)", xmm"tostr(b0)"");\
asm ("pxor xmm"tostr(b1)", xmm"tostr(b0)"");\
asm ("pxor xmm"tostr(b0)", xmm"tostr(b7)""); /* moved from 4 */\
\
/* 5 */\
asm ("pxor xmm"tostr(b4)", xmm"tostr(a2)"");\
/*asm ("pxor xmm"tostr(b4)", [TEMP_MUL1+0*16]"); -> helper! */\
asm ("pxor xmm"tostr(b4)", [TEMP_MUL1+2*16]");\
asm ("pxor xmm"tostr(b4)", [TEMP_MUL2+3*16]");\
asm ("pxor xmm"tostr(b4)", [TEMP_MUL2+5*16]");\
asm ("pxor xmm"tostr(b3)", xmm"tostr(b4)"");\
asm ("pxor xmm"tostr(b6)", xmm"tostr(b4)"");\
\
/* 6 */\
asm ("pxor xmm"tostr(a3)", [TEMP_MUL1+1*16]");\
asm ("pxor xmm"tostr(a3)", [TEMP_MUL1+3*16]");\
asm ("pxor xmm"tostr(a3)", [TEMP_MUL2+4*16]");\
asm ("pxor xmm"tostr(a3)", [TEMP_MUL2+6*16]");\
asm ("pxor xmm"tostr(b4)", xmm"tostr(a3)"");\
asm ("pxor xmm"tostr(b5)", xmm"tostr(a3)"");\
asm ("pxor xmm"tostr(b7)", xmm"tostr(a3)"");\
\
/* 7 */\
asm ("pxor xmm"tostr(a1)", [TEMP_MUL1+1*16]");\
asm ("pxor xmm"tostr(a1)", [TEMP_MUL2+4*16]");\
asm ("pxor xmm"tostr(b2)", xmm"tostr(a1)"");\
asm ("pxor xmm"tostr(b3)", xmm"tostr(a1)"");\
\
/* 8 */\
asm ("pxor xmm"tostr(a5)", [TEMP_MUL1+5*16]");\
asm ("pxor xmm"tostr(a5)", [TEMP_MUL2+0*16]");\
asm ("pxor xmm"tostr(b6)", xmm"tostr(a5)"");\
asm ("pxor xmm"tostr(b7)", xmm"tostr(a5)"");\
\
/* 9 */\
asm ("movaps xmm"tostr(a3)", [TEMP_MUL1+2*16]");\
asm ("pxor xmm"tostr(a3)", [TEMP_MUL2+5*16]");\
asm ("pxor xmm"tostr(b0)", xmm"tostr(a3)"");\
asm ("pxor xmm"tostr(b5)", xmm"tostr(a3)"");\
\
/* 10 */\
asm ("movaps xmm"tostr(a1)", [TEMP_MUL1+6*16]");\
asm ("pxor xmm"tostr(a1)", [TEMP_MUL2+1*16]");\
asm ("pxor xmm"tostr(b1)", xmm"tostr(a1)"");\
asm ("pxor xmm"tostr(b4)", xmm"tostr(a1)"");\
\
/* 11 */\
asm ("movaps xmm"tostr(a5)", [TEMP_MUL1+3*16]");\
asm ("pxor xmm"tostr(a5)", [TEMP_MUL2+6*16]");\
asm ("pxor xmm"tostr(b1)", xmm"tostr(a5)"");\
asm ("pxor xmm"tostr(b6)", xmm"tostr(a5)"");\
\
/* 12 */\
asm ("movaps xmm"tostr(a3)", [TEMP_MUL1+7*16]");\
asm ("pxor xmm"tostr(a3)", [TEMP_MUL2+2*16]");\
asm ("pxor xmm"tostr(b2)", xmm"tostr(a3)"");\
asm ("pxor xmm"tostr(b5)", xmm"tostr(a3)"");\
\
/* 13 */\
asm ("pxor xmm"tostr(b0)", [TEMP_MUL4]");\
asm ("pxor xmm"tostr(b0)", xmm"tostr(a4)"");\
asm ("pxor xmm"tostr(b1)", xmm"tostr(a4)"");\
asm ("pxor xmm"tostr(b3)", xmm"tostr(a6)"");\
asm ("pxor xmm"tostr(b4)", xmm"tostr(a0)"");\
asm ("pxor xmm"tostr(b4)", xmm"tostr(a7)"");\
asm ("pxor xmm"tostr(b5)", xmm"tostr(a0)"");\
asm ("pxor xmm"tostr(b7)", xmm"tostr(a2)"");\
}/**/
//#if (LENGTH <= 256)
#define SET_CONSTANTS(){\
SET_SHARED_CONSTANTS();\
((u64*)SUBSH_MASK)[ 0] = 0x0706050403020100ULL;\
((u64*)SUBSH_MASK)[ 1] = 0x080f0e0d0c0b0a09ULL;\
((u64*)SUBSH_MASK)[ 2] = 0x0007060504030201ULL;\
((u64*)SUBSH_MASK)[ 3] = 0x0a09080f0e0d0c0bULL;\
((u64*)SUBSH_MASK)[ 4] = 0x0100070605040302ULL;\
((u64*)SUBSH_MASK)[ 5] = 0x0c0b0a09080f0e0dULL;\
((u64*)SUBSH_MASK)[ 6] = 0x0201000706050403ULL;\
((u64*)SUBSH_MASK)[ 7] = 0x0e0d0c0b0a09080fULL;\
((u64*)SUBSH_MASK)[ 8] = 0x0302010007060504ULL;\
((u64*)SUBSH_MASK)[ 9] = 0x0f0e0d0c0b0a0908ULL;\
((u64*)SUBSH_MASK)[10] = 0x0403020100070605ULL;\
((u64*)SUBSH_MASK)[11] = 0x09080f0e0d0c0b0aULL;\
((u64*)SUBSH_MASK)[12] = 0x0504030201000706ULL;\
((u64*)SUBSH_MASK)[13] = 0x0b0a09080f0e0d0cULL;\
((u64*)SUBSH_MASK)[14] = 0x0605040302010007ULL;\
((u64*)SUBSH_MASK)[15] = 0x0d0c0b0a09080f0eULL;\
for(i = 0; i < ROUNDS512; i++)\
{\
((u64*)ROUND_CONST_L0)[i*2+1] = 0xffffffffffffffffULL;\
((u64*)ROUND_CONST_L0)[i*2+0] = (i * 0x0101010101010101ULL) ^ 0x7060504030201000ULL;\
((u64*)ROUND_CONST_L7)[i*2+1] = (i * 0x0101010101010101ULL) ^ 0x8f9fafbfcfdfefffULL;\
((u64*)ROUND_CONST_L7)[i*2+0] = 0x0000000000000000ULL;\
}\
((u64*)ROUND_CONST_Lx)[1] = 0xffffffffffffffffULL;\
((u64*)ROUND_CONST_Lx)[0] = 0x0000000000000000ULL;\
}/**/
#define Push_All_Regs(){\
/* not using any...
asm("push rax");\
asm("push rbx");\
asm("push rcx");*/\
}/**/
#define Pop_All_Regs(){\
/* not using any...
asm("pop rcx");\
asm("pop rbx");\
asm("pop rax");*/\
}/**/
/* vperm:
* transformation before rounds with ipt
* first round add transformed constant
* middle rounds: add constant XOR 0x15...15
* last round: additionally add 0x15...15 after MB
* transformation after rounds with opt
*/
/* one round
* i = round number
* a0-a7 = input rows
* b0-b7 = output rows
*/
#define ROUND(i, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\
/* AddRoundConstant + ShiftBytes (interleaved) */\
asm ("movaps xmm"tostr(b1)", [ROUND_CONST_Lx]");\
asm ("pxor xmm"tostr(a0)", [ROUND_CONST_L0+"tostr(i)"*16]");\
asm ("pxor xmm"tostr(a1)", xmm"tostr(b1)"");\
asm ("pxor xmm"tostr(a2)", xmm"tostr(b1)"");\
asm ("pxor xmm"tostr(a3)", xmm"tostr(b1)"");\
asm ("pshufb xmm"tostr(a0)", [SUBSH_MASK+0*16]");\
asm ("pshufb xmm"tostr(a1)", [SUBSH_MASK+1*16]");\
asm ("pxor xmm"tostr(a4)", xmm"tostr(b1)"");\
asm ("pshufb xmm"tostr(a2)", [SUBSH_MASK+2*16]");\
asm ("pshufb xmm"tostr(a3)", [SUBSH_MASK+3*16]");\
asm ("pxor xmm"tostr(a5)", xmm"tostr(b1)"");\
asm ("pxor xmm"tostr(a6)", xmm"tostr(b1)"");\
asm ("pshufb xmm"tostr(a4)", [SUBSH_MASK+4*16]");\
asm ("pshufb xmm"tostr(a5)", [SUBSH_MASK+5*16]");\
asm ("pxor xmm"tostr(a7)", [ROUND_CONST_L7+"tostr(i)"*16]");\
asm ("pshufb xmm"tostr(a6)", [SUBSH_MASK+6*16]");\
asm ("pshufb xmm"tostr(a7)", [SUBSH_MASK+7*16]");\
/* SubBytes + Multiplication by 2 and 4 */\
VPERM_SUB_MULTIPLY(a0, a1, a2, a3, a4, a5, a6, a7, b1, b2, b5, b6, b0, b3, b4, b7);\
/* MixBytes */\
MixBytes(a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7);\
}/**/
/* 10 rounds, P and Q in parallel */
#define ROUNDS_P_Q(){\
VPERM_Add_Constant(8, 9, 10, 11, 12, 13, 14, 15, ALL_15, 0);\
ROUND(0, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
ROUND(2, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(3, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
ROUND(4, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(5, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
ROUND(6, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
ROUND(8, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);\
ROUND(9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);\
VPERM_Add_Constant(8, 9, 10, 11, 12, 13, 14, 15, ALL_15, 0);\
}
/* Matrix Transpose Step 1
* input is a 512-bit state with two columns in one xmm
* output is a 512-bit state with two rows in one xmm
* inputs: i0-i3
* outputs: i0, o1-o3
* clobbers: t0
*/
#define Matrix_Transpose_A(i0, i1, i2, i3, o1, o2, o3, t0){\
asm ("movaps xmm"tostr(t0)", [TRANSP_MASK]");\
\
asm ("pshufb xmm"tostr(i0)", xmm"tostr(t0)"");\
asm ("pshufb xmm"tostr(i1)", xmm"tostr(t0)"");\
asm ("pshufb xmm"tostr(i2)", xmm"tostr(t0)"");\
asm ("pshufb xmm"tostr(i3)", xmm"tostr(t0)"");\
\
asm ("movdqa xmm"tostr(o1)", xmm"tostr(i0)"");\
asm ("movdqa xmm"tostr(t0)", xmm"tostr(i2)"");\
\
asm ("punpcklwd xmm"tostr(i0)", xmm"tostr(i1)"");\
asm ("punpckhwd xmm"tostr(o1)", xmm"tostr(i1)"");\
asm ("punpcklwd xmm"tostr(i2)", xmm"tostr(i3)"");\
asm ("punpckhwd xmm"tostr(t0)", xmm"tostr(i3)"");\
\
asm ("pshufd xmm"tostr(i0)", xmm"tostr(i0)", 216");\
asm ("pshufd xmm"tostr(o1)", xmm"tostr(o1)", 216");\
asm ("pshufd xmm"tostr(i2)", xmm"tostr(i2)", 216");\
asm ("pshufd xmm"tostr(t0)", xmm"tostr(t0)", 216");\
\
asm ("movdqa xmm"tostr(o2)", xmm"tostr(i0)"");\
asm ("movdqa xmm"tostr(o3)", xmm"tostr(o1)"");\
\
asm ("punpckldq xmm"tostr(i0)", xmm"tostr(i2)"");\
asm ("punpckldq xmm"tostr(o1)", xmm"tostr(t0)"");\
asm ("punpckhdq xmm"tostr(o2)", xmm"tostr(i2)"");\
asm ("punpckhdq xmm"tostr(o3)", xmm"tostr(t0)"");\
}/**/
/* Matrix Transpose Step 2
* input are two 512-bit states with two rows in one xmm
* output are two 512-bit states with one row of each state in one xmm
* inputs: i0-i3 = P, i4-i7 = Q
* outputs: (i0, o1-o7) = (P|Q)
* possible reassignments: (output reg = input reg)
* * i1 -> o3-7
* * i2 -> o5-7
* * i3 -> o7
* * i4 -> o3-7
* * i5 -> o6-7
*/
#define Matrix_Transpose_B(i0, i1, i2, i3, i4, i5, i6, i7, o1, o2, o3, o4, o5, o6, o7){\
asm ("movdqa xmm"tostr(o1)", xmm"tostr(i0)"");\
asm ("movdqa xmm"tostr(o2)", xmm"tostr(i1)"");\
asm ("punpcklqdq xmm"tostr(i0)", xmm"tostr(i4)"");\
asm ("punpckhqdq xmm"tostr(o1)", xmm"tostr(i4)"");\
asm ("movdqa xmm"tostr(o3)", xmm"tostr(i1)"");\
asm ("movdqa xmm"tostr(o4)", xmm"tostr(i2)"");\
asm ("punpcklqdq xmm"tostr(o2)", xmm"tostr(i5)"");\
asm ("punpckhqdq xmm"tostr(o3)", xmm"tostr(i5)"");\
asm ("movdqa xmm"tostr(o5)", xmm"tostr(i2)"");\
asm ("movdqa xmm"tostr(o6)", xmm"tostr(i3)"");\
asm ("punpcklqdq xmm"tostr(o4)", xmm"tostr(i6)"");\
asm ("punpckhqdq xmm"tostr(o5)", xmm"tostr(i6)"");\
asm ("movdqa xmm"tostr(o7)", xmm"tostr(i3)"");\
asm ("punpcklqdq xmm"tostr(o6)", xmm"tostr(i7)"");\
asm ("punpckhqdq xmm"tostr(o7)", xmm"tostr(i7)"");\
}/**/
/* Matrix Transpose Inverse Step 2
* input are two 512-bit states with one row of each state in one xmm
* output are two 512-bit states with two rows in one xmm
* inputs: i0-i7 = (P|Q)
* outputs: (i0, i2, i4, i6) = P, (o0-o3) = Q
*/
#define Matrix_Transpose_B_INV(i0, i1, i2, i3, i4, i5, i6, i7, o0, o1, o2, o3){\
asm ("movdqa xmm"tostr(o0)", xmm"tostr(i0)"");\
asm ("punpcklqdq xmm"tostr(i0)", xmm"tostr(i1)"");\
asm ("punpckhqdq xmm"tostr(o0)", xmm"tostr(i1)"");\
asm ("movdqa xmm"tostr(o1)", xmm"tostr(i2)"");\
asm ("punpcklqdq xmm"tostr(i2)", xmm"tostr(i3)"");\
asm ("punpckhqdq xmm"tostr(o1)", xmm"tostr(i3)"");\
asm ("movdqa xmm"tostr(o2)", xmm"tostr(i4)"");\
asm ("punpcklqdq xmm"tostr(i4)", xmm"tostr(i5)"");\
asm ("punpckhqdq xmm"tostr(o2)", xmm"tostr(i5)"");\
asm ("movdqa xmm"tostr(o3)", xmm"tostr(i6)"");\
asm ("punpcklqdq xmm"tostr(i6)", xmm"tostr(i7)"");\
asm ("punpckhqdq xmm"tostr(o3)", xmm"tostr(i7)"");\
}/**/
/* Matrix Transpose Output Step 2
* input is one 512-bit state with two rows in one xmm
* output is one 512-bit state with one row in the low 64-bits of one xmm
* inputs: i0,i2,i4,i6 = S
* outputs: (i0-7) = (0|S)
*/
#define Matrix_Transpose_O_B(i0, i1, i2, i3, i4, i5, i6, i7, t0){\
asm ("pxor xmm"tostr(t0)", xmm"tostr(t0)"");\
asm ("movdqa xmm"tostr(i1)", xmm"tostr(i0)"");\
asm ("movdqa xmm"tostr(i3)", xmm"tostr(i2)"");\
asm ("movdqa xmm"tostr(i5)", xmm"tostr(i4)"");\
asm ("movdqa xmm"tostr(i7)", xmm"tostr(i6)"");\
asm ("punpcklqdq xmm"tostr(i0)", xmm"tostr(t0)"");\
asm ("punpckhqdq xmm"tostr(i1)", xmm"tostr(t0)"");\
asm ("punpcklqdq xmm"tostr(i2)", xmm"tostr(t0)"");\
asm ("punpckhqdq xmm"tostr(i3)", xmm"tostr(t0)"");\
asm ("punpcklqdq xmm"tostr(i4)", xmm"tostr(t0)"");\
asm ("punpckhqdq xmm"tostr(i5)", xmm"tostr(t0)"");\
asm ("punpcklqdq xmm"tostr(i6)", xmm"tostr(t0)"");\
asm ("punpckhqdq xmm"tostr(i7)", xmm"tostr(t0)"");\
}/**/
/* Matrix Transpose Output Inverse Step 2
* input is one 512-bit state with one row in the low 64-bits of one xmm
* output is one 512-bit state with two rows in one xmm
* inputs: i0-i7 = (0|S)
* outputs: (i0, i2, i4, i6) = S
*/
#define Matrix_Transpose_O_B_INV(i0, i1, i2, i3, i4, i5, i6, i7){\
asm ("punpcklqdq xmm"tostr(i0)", xmm"tostr(i1)"");\
asm ("punpcklqdq xmm"tostr(i2)", xmm"tostr(i3)"");\
asm ("punpcklqdq xmm"tostr(i4)", xmm"tostr(i5)"");\
asm ("punpcklqdq xmm"tostr(i6)", xmm"tostr(i7)"");\
}/**/
/* transform round constants into VPERM mode */
#define VPERM_Transform_RoundConst_CNT2(i, j){\
asm ("movaps xmm0, [ROUND_CONST_L0+"tostr(i)"*16]");\
asm ("movaps xmm1, [ROUND_CONST_L7+"tostr(i)"*16]");\
asm ("movaps xmm2, [ROUND_CONST_L0+"tostr(j)"*16]");\
asm ("movaps xmm3, [ROUND_CONST_L7+"tostr(j)"*16]");\
VPERM_Transform_State(0, 1, 2, 3, VPERM_IPT, 4, 5, 6, 7, 8, 9, 10);\
asm ("pxor xmm0, [ALL_15]");\
asm ("pxor xmm1, [ALL_15]");\
asm ("pxor xmm2, [ALL_15]");\
asm ("pxor xmm3, [ALL_15]");\
asm ("movaps [ROUND_CONST_L0+"tostr(i)"*16], xmm0");\
asm ("movaps [ROUND_CONST_L7+"tostr(i)"*16], xmm1");\
asm ("movaps [ROUND_CONST_L0+"tostr(j)"*16], xmm2");\
asm ("movaps [ROUND_CONST_L7+"tostr(j)"*16], xmm3");\
}/**/
/* transform round constants into VPERM mode */
#define VPERM_Transform_RoundConst(){\
asm ("movaps xmm0, [ROUND_CONST_Lx]");\
VPERM_Transform(0, 1, VPERM_IPT, 4, 5, 6, 7, 8, 9, 10);\
asm ("pxor xmm0, [ALL_15]");\
asm ("movaps [ROUND_CONST_Lx], xmm0");\
VPERM_Transform_RoundConst_CNT2(0, 1);\
VPERM_Transform_RoundConst_CNT2(2, 3);\
VPERM_Transform_RoundConst_CNT2(4, 5);\
VPERM_Transform_RoundConst_CNT2(6, 7);\
VPERM_Transform_RoundConst_CNT2(8, 9);\
}/**/
void INIT256(u64* h)
{
/* __cdecl calling convention: */
/* chaining value CV in rdi */
asm (".intel_syntax noprefix");
asm volatile ("emms");
/* transform round constants into VPERM mode */
VPERM_Transform_RoundConst();
/* load IV into registers xmm12 - xmm15 */
asm ("movaps xmm12, [rdi+0*16]");
asm ("movaps xmm13, [rdi+1*16]");
asm ("movaps xmm14, [rdi+2*16]");
asm ("movaps xmm15, [rdi+3*16]");
/* transform chaining value from column ordering into row ordering */
/* we put two rows (64 bit) of the IV into one 128-bit XMM register */
VPERM_Transform_State(12, 13, 14, 15, VPERM_IPT, 1, 2, 3, 4, 5, 6, 7);
Matrix_Transpose_A(12, 13, 14, 15, 2, 6, 7, 0);
/* store transposed IV */
asm ("movaps [rdi+0*16], xmm12");
asm ("movaps [rdi+1*16], xmm2");
asm ("movaps [rdi+2*16], xmm6");
asm ("movaps [rdi+3*16], xmm7");
asm volatile ("emms");
asm (".att_syntax noprefix");
}
void TF512(u64* h, u64* m)
{
/* __cdecl calling convention: */
/* chaining value CV in rdi */
/* message M in rsi */
#ifdef IACA_TRACE
IACA_START;
#endif
asm (".intel_syntax noprefix");
Push_All_Regs();
/* load message into registers xmm12 - xmm15 (Q = message) */
asm ("movaps xmm12, [rsi+0*16]");
asm ("movaps xmm13, [rsi+1*16]");
asm ("movaps xmm14, [rsi+2*16]");
asm ("movaps xmm15, [rsi+3*16]");
/* transform message M from column ordering into row ordering */
/* we first put two rows (64 bit) of the message into one 128-bit xmm register */
VPERM_Transform_State(12, 13, 14, 15, VPERM_IPT, 1, 2, 3, 4, 5, 6, 7);
Matrix_Transpose_A(12, 13, 14, 15, 2, 6, 7, 0);
/* load previous chaining value */
/* we first put two rows (64 bit) of the CV into one 128-bit xmm register */
asm ("movaps xmm8, [rdi+0*16]");
asm ("movaps xmm0, [rdi+1*16]");
asm ("movaps xmm4, [rdi+2*16]");
asm ("movaps xmm5, [rdi+3*16]");
/* xor message to CV get input of P */
/* result: CV+M in xmm8, xmm0, xmm4, xmm5 */
asm ("pxor xmm8, xmm12");
asm ("pxor xmm0, xmm2");
asm ("pxor xmm4, xmm6");
asm ("pxor xmm5, xmm7");
/* there are now 2 rows of the Groestl state (P and Q) in each xmm register */
/* unpack to get 1 row of P (64 bit) and Q (64 bit) into one xmm register */
/* result: the 8 rows of P and Q in xmm8 - xmm12 */
Matrix_Transpose_B(8, 0, 4, 5, 12, 2, 6, 7, 9, 10, 11, 12, 13, 14, 15);
/* compute the two permutations P and Q in parallel */
ROUNDS_P_Q();
/* unpack again to get two rows of P or two rows of Q in one xmm register */
Matrix_Transpose_B_INV(8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3);
/* xor output of P and Q */
/* result: P(CV+M)+Q(M) in xmm0...xmm3 */
asm ("pxor xmm0, xmm8");
asm ("pxor xmm1, xmm10");
asm ("pxor xmm2, xmm12");
asm ("pxor xmm3, xmm14");
/* xor CV (feed-forward) */
/* result: P(CV+M)+Q(M)+CV in xmm0...xmm3 */
asm ("pxor xmm0, [rdi+0*16]");
asm ("pxor xmm1, [rdi+1*16]");
asm ("pxor xmm2, [rdi+2*16]");
asm ("pxor xmm3, [rdi+3*16]");
/* store CV */
asm ("movaps [rdi+0*16], xmm0");
asm ("movaps [rdi+1*16], xmm1");
asm ("movaps [rdi+2*16], xmm2");
asm ("movaps [rdi+3*16], xmm3");
Pop_All_Regs();
asm (".att_syntax noprefix");
#ifdef IACA_TRACE
IACA_END;
#endif
return;
}
void OF512(u64* h)
{
/* __cdecl calling convention: */
/* chaining value CV in rdi */
asm (".intel_syntax noprefix");
Push_All_Regs();
/* load CV into registers xmm8, xmm10, xmm12, xmm14 */
asm ("movaps xmm8, [rdi+0*16]");
asm ("movaps xmm10, [rdi+1*16]");
asm ("movaps xmm12, [rdi+2*16]");
asm ("movaps xmm14, [rdi+3*16]");
/* there are now 2 rows of the CV in one xmm register */
/* unpack to get 1 row of P (64 bit) into one half of an xmm register */
/* result: the 8 input rows of P in xmm8 - xmm15 */
Matrix_Transpose_O_B(8, 9, 10, 11, 12, 13, 14, 15, 0);
/* compute the permutation P */
/* result: the output of P(CV) in xmm8 - xmm15 */
ROUNDS_P_Q();
/* unpack again to get two rows of P in one xmm register */
/* result: P(CV) in xmm8, xmm10, xmm12, xmm14 */
Matrix_Transpose_O_B_INV(8, 9, 10, 11, 12, 13, 14, 15);
/* xor CV to P output (feed-forward) */
/* result: P(CV)+CV in xmm8, xmm10, xmm12, xmm14 */
asm ("pxor xmm8, [rdi+0*16]");
asm ("pxor xmm10, [rdi+1*16]");
asm ("pxor xmm12, [rdi+2*16]");
asm ("pxor xmm14, [rdi+3*16]");
/* transform state back from row ordering into column ordering */
/* result: final hash value in xmm9, xmm11 */
Matrix_Transpose_A(8, 10, 12, 14, 4, 9, 11, 0);
VPERM_Transform(9, 11, VPERM_OPT, 0, 1, 2, 3, 5, 6, 7);
/* we only need to return the truncated half of the state */
asm ("movaps [rdi+2*16], xmm9");
asm ("movaps [rdi+3*16], xmm11");
Pop_All_Regs();
asm (".att_syntax noprefix");
return;
}

View File

@@ -11,17 +11,44 @@
#include <wmmintrin.h> #include <wmmintrin.h>
#include "hash-groestl256.h" #include "hash-groestl256.h"
/* global constants */ static const __m128i round_const_l0[] __attribute__ ((aligned (64))) =
__m128i ROUND_CONST_Lx; {
__m128i ROUND_CONST_L0[ROUNDS512]; { 0x7060504030201000, 0xffffffffffffffff },
__m128i ROUND_CONST_L7[ROUNDS512]; { 0x7161514131211101, 0xffffffffffffffff },
//__m128i ROUND_CONST_P[ROUNDS1024]; { 0x7262524232221202, 0xffffffffffffffff },
//__m128i ROUND_CONST_Q[ROUNDS1024]; { 0x7363534333231303, 0xffffffffffffffff },
__m128i TRANSP_MASK; { 0x7464544434241404, 0xffffffffffffffff },
__m128i SUBSH_MASK[8]; { 0x7565554535251505, 0xffffffffffffffff },
__m128i ALL_1B; { 0x7666564636261606, 0xffffffffffffffff },
__m128i ALL_FF; { 0x7767574737271707, 0xffffffffffffffff },
{ 0x7868584838281808, 0xffffffffffffffff },
{ 0x7969594939291909, 0xffffffffffffffff }
};
static const __m128i round_const_l7[] __attribute__ ((aligned (64))) =
{
{ 0x0000000000000000, 0x8f9fafbfcfdfefff },
{ 0x0000000000000000, 0x8e9eaebecedeeefe },
{ 0x0000000000000000, 0x8d9dadbdcdddedfd },
{ 0x0000000000000000, 0x8c9cacbcccdcecfc },
{ 0x0000000000000000, 0x8b9babbbcbdbebfb },
{ 0x0000000000000000, 0x8a9aaabacadaeafa },
{ 0x0000000000000000, 0x8999a9b9c9d9e9f9 },
{ 0x0000000000000000, 0x8898a8b8c8d8e8f8 },
{ 0x0000000000000000, 0x8797a7b7c7d7e7f7 },
{ 0x0000000000000000, 0x8696a6b6c6d6e6f6 }
};
static const __m128i TRANSP_MASK = { 0x0d0509010c040800, 0x0f070b030e060a02 };
static const __m128i SUBSH_MASK0 = { 0x0c0f0104070b0e00, 0x03060a0d08020509 };
static const __m128i SUBSH_MASK1 = { 0x0e090205000d0801, 0x04070c0f0a03060b };
static const __m128i SUBSH_MASK2 = { 0x080b0306010f0a02, 0x05000e090c04070d };
static const __m128i SUBSH_MASK3 = { 0x0a0d040702090c03, 0x0601080b0e05000f };
static const __m128i SUBSH_MASK4 = { 0x0b0e0500030a0d04, 0x0702090c0f060108 };
static const __m128i SUBSH_MASK5 = { 0x0d080601040c0f05, 0x00030b0e0907020a };
static const __m128i SUBSH_MASK6 = { 0x0f0a0702050e0906, 0x01040d080b00030c };
static const __m128i SUBSH_MASK7 = { 0x090c000306080b07, 0x02050f0a0d01040e };
#define tos(a) #a #define tos(a) #a
#define tostr(a) tos(a) #define tostr(a) tos(a)
@@ -38,8 +65,6 @@ __m128i ALL_FF;
i = _mm_xor_si128(i, j);\ i = _mm_xor_si128(i, j);\
} }
/**/
/* Yet another implementation of MixBytes. /* Yet another implementation of MixBytes.
This time we use the formulae (3) from the paper "Byte Slicing Groestl". This time we use the formulae (3) from the paper "Byte Slicing Groestl".
Input: a0, ..., a7 Input: a0, ..., a7
@@ -113,7 +138,7 @@ __m128i ALL_FF;
\ \
/* compute z_i : double x_i using temp xmm8 and 1B xmm9 */\ /* compute z_i : double x_i using temp xmm8 and 1B xmm9 */\
/* compute w_i : add y_{i+4} */\ /* compute w_i : add y_{i+4} */\
b1 = ALL_1B;\ b1 = m128_const1_64( 0x1b1b1b1b1b1b1b1b );\
MUL2(a0, b0, b1);\ MUL2(a0, b0, b1);\
a0 = _mm_xor_si128(a0, TEMP0);\ a0 = _mm_xor_si128(a0, TEMP0);\
MUL2(a1, b0, b1);\ MUL2(a1, b0, b1);\
@@ -153,25 +178,6 @@ __m128i ALL_FF;
b1 = _mm_xor_si128(b1, a4);\ b1 = _mm_xor_si128(b1, a4);\
}/*MixBytes*/ }/*MixBytes*/
#define SET_CONSTANTS(){\
ALL_1B = _mm_set_epi32(0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b);\
TRANSP_MASK = _mm_set_epi32(0x0f070b03, 0x0e060a02, 0x0d050901, 0x0c040800);\
SUBSH_MASK[0] = _mm_set_epi32(0x03060a0d, 0x08020509, 0x0c0f0104, 0x070b0e00);\
SUBSH_MASK[1] = _mm_set_epi32(0x04070c0f, 0x0a03060b, 0x0e090205, 0x000d0801);\
SUBSH_MASK[2] = _mm_set_epi32(0x05000e09, 0x0c04070d, 0x080b0306, 0x010f0a02);\
SUBSH_MASK[3] = _mm_set_epi32(0x0601080b, 0x0e05000f, 0x0a0d0407, 0x02090c03);\
SUBSH_MASK[4] = _mm_set_epi32(0x0702090c, 0x0f060108, 0x0b0e0500, 0x030a0d04);\
SUBSH_MASK[5] = _mm_set_epi32(0x00030b0e, 0x0907020a, 0x0d080601, 0x040c0f05);\
SUBSH_MASK[6] = _mm_set_epi32(0x01040d08, 0x0b00030c, 0x0f0a0702, 0x050e0906);\
SUBSH_MASK[7] = _mm_set_epi32(0x02050f0a, 0x0d01040e, 0x090c0003, 0x06080b07);\
for(i = 0; i < ROUNDS512; i++)\
{\
ROUND_CONST_L0[i] = _mm_set_epi32(0xffffffff, 0xffffffff, 0x70605040 ^ (i * 0x01010101), 0x30201000 ^ (i * 0x01010101));\
ROUND_CONST_L7[i] = _mm_set_epi32(0x8f9fafbf ^ (i * 0x01010101), 0xcfdfefff ^ (i * 0x01010101), 0x00000000, 0x00000000);\
}\
ROUND_CONST_Lx = _mm_set_epi32(0xffffffff, 0xffffffff, 0x00000000, 0x00000000);\
}while(0); \
/* one round /* one round
* i = round number * i = round number
* a0-a7 = input rows * a0-a7 = input rows
@@ -179,34 +185,34 @@ __m128i ALL_FF;
*/ */
#define ROUND(i, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\ #define ROUND(i, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\
/* AddRoundConstant */\ /* AddRoundConstant */\
b1 = ROUND_CONST_Lx;\ b1 = m128_const_64( 0xffffffffffffffff, 0 ); \
a0 = _mm_xor_si128(a0, (ROUND_CONST_L0[i]));\ a0 = _mm_xor_si128( a0, casti_m128i( round_const_l0, i ) ); \
a1 = _mm_xor_si128(a1, b1);\ a1 = _mm_xor_si128( a1, b1 ); \
a2 = _mm_xor_si128(a2, b1);\ a2 = _mm_xor_si128( a2, b1 ); \
a3 = _mm_xor_si128(a3, b1);\ a3 = _mm_xor_si128( a3, b1 ); \
a4 = _mm_xor_si128(a4, b1);\ a4 = _mm_xor_si128( a4, b1 ); \
a5 = _mm_xor_si128(a5, b1);\ a5 = _mm_xor_si128( a5, b1 ); \
a6 = _mm_xor_si128(a6, b1);\ a6 = _mm_xor_si128( a6, b1 ); \
a7 = _mm_xor_si128(a7, (ROUND_CONST_L7[i]));\ a7 = _mm_xor_si128( a7, casti_m128i( round_const_l7, i ) ); \
\ \
/* ShiftBytes + SubBytes (interleaved) */\ /* ShiftBytes + SubBytes (interleaved) */\
b0 = _mm_xor_si128(b0, b0);\ b0 = _mm_xor_si128(b0, b0);\
a0 = _mm_shuffle_epi8(a0, (SUBSH_MASK[0]));\ a0 = _mm_shuffle_epi8( a0, SUBSH_MASK0 ); \
a0 = _mm_aesenclast_si128(a0, b0);\ a0 = _mm_aesenclast_si128( a0, b0 );\
a1 = _mm_shuffle_epi8(a1, (SUBSH_MASK[1]));\ a1 = _mm_shuffle_epi8( a1, SUBSH_MASK1 ); \
a1 = _mm_aesenclast_si128(a1, b0);\ a1 = _mm_aesenclast_si128( a1, b0 );\
a2 = _mm_shuffle_epi8(a2, (SUBSH_MASK[2]));\ a2 = _mm_shuffle_epi8( a2, SUBSH_MASK2 ); \
a2 = _mm_aesenclast_si128(a2, b0);\ a2 = _mm_aesenclast_si128( a2, b0 );\
a3 = _mm_shuffle_epi8(a3, (SUBSH_MASK[3]));\ a3 = _mm_shuffle_epi8( a3, SUBSH_MASK3 ); \
a3 = _mm_aesenclast_si128(a3, b0);\ a3 = _mm_aesenclast_si128( a3, b0 );\
a4 = _mm_shuffle_epi8(a4, (SUBSH_MASK[4]));\ a4 = _mm_shuffle_epi8( a4, SUBSH_MASK4 ); \
a4 = _mm_aesenclast_si128(a4, b0);\ a4 = _mm_aesenclast_si128( a4, b0 );\
a5 = _mm_shuffle_epi8(a5, (SUBSH_MASK[5]));\ a5 = _mm_shuffle_epi8( a5, SUBSH_MASK5 ); \
a5 = _mm_aesenclast_si128(a5, b0);\ a5 = _mm_aesenclast_si128( a5, b0 );\
a6 = _mm_shuffle_epi8(a6, (SUBSH_MASK[6]));\ a6 = _mm_shuffle_epi8( a6, SUBSH_MASK6 ); \
a6 = _mm_aesenclast_si128(a6, b0);\ a6 = _mm_aesenclast_si128( a6, b0 );\
a7 = _mm_shuffle_epi8(a7, (SUBSH_MASK[7]));\ a7 = _mm_shuffle_epi8( a7, SUBSH_MASK7 ); \
a7 = _mm_aesenclast_si128(a7, b0);\ a7 = _mm_aesenclast_si128( a7, b0 );\
\ \
/* MixBytes */\ /* MixBytes */\
MixBytes(a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7);\ MixBytes(a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7);\
@@ -234,8 +240,9 @@ __m128i ALL_FF;
* outputs: i0, o1-o3 * outputs: i0, o1-o3
* clobbers: t0 * clobbers: t0
*/ */
#define Matrix_Transpose_A(i0, i1, i2, i3, o1, o2, o3, t0){\ #define Matrix_Transpose_A(i0, i1, i2, i3, o1, o2, o3, t0){\
t0 = TRANSP_MASK;\ t0 = TRANSP_MASK; \
\ \
i0 = _mm_shuffle_epi8(i0, t0);\ i0 = _mm_shuffle_epi8(i0, t0);\
i1 = _mm_shuffle_epi8(i1, t0);\ i1 = _mm_shuffle_epi8(i1, t0);\

View File

@@ -1,482 +0,0 @@
/* groestl-intr-avx.h Aug 2011
*
* Groestl implementation with intrinsics using ssse3, sse4.1, aes and avx
* instructions.
* Author: Günther A. Roland, Martin Schläffer, Krystian Matusiewicz
*
* This code is placed in the public domain
*/
#include <smmintrin.h>
#include <wmmintrin.h>
#include <immintrin.h>
#include "hash-groestl256.h"
/* global constants */
__m128i ROUND_CONST_Lx;
__m128i ROUND_CONST_L0[ROUNDS512];
__m128i ROUND_CONST_L7[ROUNDS512];
__m128i ROUND_CONST_P[ROUNDS1024];
__m128i ROUND_CONST_Q[ROUNDS1024];
__m128i TRANSP_MASK;
__m128i SUBSH_MASK[8];
__m128i ALL_FF;
//#if LENGTH <= 256
__m128i ALL_1B;
//#else
//__m256d ALL_1B;
//#endif
#define tos(a) #a
#define tostr(a) tos(a)
#define insert_m128i_in_m256d(ymm, xmm, pos) (_mm256_castsi256_pd(_mm256_insertf128_si256(_mm256_castpd_si256(ymm), xmm, pos)))
#define extract_m128i_from_m256d(ymm, pos) (_mm256_extractf128_si256(_mm256_castpd_si256(ymm), pos))
#define SET_CONSTANTS(){\
ALL_1B = _mm_set_epi32(0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b);\
ALL_FF = _mm_set_epi32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);\
TRANSP_MASK = _mm_set_epi32(0x0f070b03, 0x0e060a02, 0x0d050901, 0x0c040800);\
SUBSH_MASK[0] = _mm_set_epi32(0x03060a0d, 0x08020509, 0x0c0f0104, 0x070b0e00);\
SUBSH_MASK[1] = _mm_set_epi32(0x04070c0f, 0x0a03060b, 0x0e090205, 0x000d0801);\
SUBSH_MASK[2] = _mm_set_epi32(0x05000e09, 0x0c04070d, 0x080b0306, 0x010f0a02);\
SUBSH_MASK[3] = _mm_set_epi32(0x0601080b, 0x0e05000f, 0x0a0d0407, 0x02090c03);\
SUBSH_MASK[4] = _mm_set_epi32(0x0702090c, 0x0f060108, 0x0b0e0500, 0x030a0d04);\
SUBSH_MASK[5] = _mm_set_epi32(0x00030b0e, 0x0907020a, 0x0d080601, 0x040c0f05);\
SUBSH_MASK[6] = _mm_set_epi32(0x01040d08, 0x0b00030c, 0x0f0a0702, 0x050e0906);\
SUBSH_MASK[7] = _mm_set_epi32(0x02050f0a, 0x0d01040e, 0x090c0003, 0x06080b07);\
for(i = 0; i < ROUNDS512; i++)\
{\
ROUND_CONST_L0[i] = _mm_set_epi32(0xffffffff, 0xffffffff, 0x70605040 ^ (i * 0x01010101), 0x30201000 ^ (i * 0x01010101));\
ROUND_CONST_L7[i] = _mm_set_epi32(0x8f9fafbf ^ (i * 0x01010101), 0xcfdfefff ^ (i * 0x01010101), 0x00000000, 0x00000000);\
}\
ROUND_CONST_Lx = _mm_set_epi32(0xffffffff, 0xffffffff, 0x00000000, 0x00000000);\
}while(0);
/* xmm[i] will be multiplied by 2
* xmm[j] will be lost
* xmm[k] has to be all 0x1b
* xmm[z] has to be zero */
#define VMUL2(i, j, k, z){\
j = _mm_cmpgt_epi8(z, i);\
i = _mm_add_epi8(i, i);\
j = _mm_and_si128(j, k);\
i = _mm_xor_si128(i, j);\
}/**/
/* Yet another implementation of MixBytes.
This time we use the formulae (3) from the paper "Byte Slicing Groestl".
Input: a0, ..., a7
Output: b0, ..., b7 = MixBytes(a0,...,a7).
but we use the relations:
t_i = a_i + a_{i+3}
x_i = t_i + t_{i+3}
y_i = t_i + t+{i+2} + a_{i+6}
z_i = 2*x_i
w_i = z_i + y_{i+4}
v_i = 2*w_i
b_i = v_{i+3} + y_{i+4}
We keep building b_i in registers xmm8..xmm15 by first building y_{i+4} there
and then adding v_i computed in the meantime in registers xmm0..xmm7.
We almost fit into 16 registers, need only 3 spills to memory.
This implementation costs 7.7 c/b giving total speed on SNB: 10.7c/b.
K. Matusiewicz, 2011/05/29 */
#define MixBytes(a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\
/* xmm"tostr(8..xmm"tostr(15 = a2 a3... a0 a1 */\
b0 = a2;\
b1 = a3;\
b2 = a4;\
b3 = a5;\
b4 = a6;\
b5 = a7;\
b6 = a0;\
b7 = a1;\
\
/* t_i = a_i + a_{i+1} */\
a0 = _mm_xor_si128(a0, a1);\
a1 = _mm_xor_si128(a1, a2);\
a2 = _mm_xor_si128(a2, a3);\
a3 = _mm_xor_si128(a3, a4);\
a4 = _mm_xor_si128(a4, a5);\
a5 = _mm_xor_si128(a5, a6);\
a6 = _mm_xor_si128(a6, a7);\
a7 = _mm_xor_si128(a7, b6);\
\
/* build y4 y5 y6 ... in regs xmm8, xmm9, xmm10 by adding t_i*/\
b0 = _mm_xor_si128(b0, a4);\
b1 = _mm_xor_si128(b1, a5);\
b2 = _mm_xor_si128(b2, a6);\
b3 = _mm_xor_si128(b3, a7);\
b4 = _mm_xor_si128(b4, a0);\
b5 = _mm_xor_si128(b5, a1);\
b6 = _mm_xor_si128(b6, a2);\
b7 = _mm_xor_si128(b7, a3);\
\
b0 = _mm_xor_si128(b0, a6);\
b1 = _mm_xor_si128(b1, a7);\
b2 = _mm_xor_si128(b2, a0);\
b3 = _mm_xor_si128(b3, a1);\
b4 = _mm_xor_si128(b4, a2);\
b5 = _mm_xor_si128(b5, a3);\
b6 = _mm_xor_si128(b6, a4);\
b7 = _mm_xor_si128(b7, a5);\
\
/* spill values y_4, y_5 to memory */\
TEMP0 = b0;\
TEMP1 = b1;\
TEMP2 = b2;\
\
/* save values t0, t1, t2 to xmm8, xmm9 and memory */\
b0 = a0;\
b1 = a1;\
TEMP3 = a2;\
\
/* compute x_i = t_i + t_{i+3} */\
a0 = _mm_xor_si128(a0, a3);\
a1 = _mm_xor_si128(a1, a4);\
a2 = _mm_xor_si128(a2, a5);\
a3 = _mm_xor_si128(a3, a6);\
a4 = _mm_xor_si128(a4, a7);\
a5 = _mm_xor_si128(a5, b0);\
a6 = _mm_xor_si128(a6, b1);\
a7 = _mm_xor_si128(a7, TEMP3);\
\
/*compute z_i : double x_i using temp xmm8 and 1B xmm9 */\
b1 = ALL_1B;\
b2 = _mm_xor_si128(b2, b2);\
VMUL2(a7, b0, b1, b2);\
VMUL2(a6, b0, b1, b2);\
VMUL2(a5, b0, b1, b2);\
VMUL2(a4, b0, b1, b2);\
VMUL2(a3, b0, b1, b2);\
VMUL2(a2, b0, b1, b2);\
VMUL2(a1, b0, b1, b2);\
VMUL2(a0, b0, b1, b2);\
\
/* compute w_i : add y_{i+4} */\
a0 = _mm_xor_si128(a0, TEMP0);\
a1 = _mm_xor_si128(a1, TEMP1);\
a2 = _mm_xor_si128(a2, TEMP2);\
a3 = _mm_xor_si128(a3, b3);\
a4 = _mm_xor_si128(a4, b4);\
a5 = _mm_xor_si128(a5, b5);\
a6 = _mm_xor_si128(a6, b6);\
a7 = _mm_xor_si128(a7, b7);\
\
/*compute v_i: double w_i */\
VMUL2(a0, b0, b1, b2);\
VMUL2(a1, b0, b1, b2);\
VMUL2(a2, b0, b1, b2);\
VMUL2(a3, b0, b1, b2);\
VMUL2(a4, b0, b1, b2);\
VMUL2(a5, b0, b1, b2);\
VMUL2(a6, b0, b1, b2);\
VMUL2(a7, b0, b1, b2);\
\
/* add to y_4 y_5 .. v3, v4, ... */\
b0 = _mm_xor_si128(a3, TEMP0);\
b1 = _mm_xor_si128(a4, TEMP1);\
b2 = _mm_xor_si128(a5, TEMP2);\
b3 = _mm_xor_si128(b3, a6);\
b4 = _mm_xor_si128(b4, a7);\
b5 = _mm_xor_si128(b5, a0);\
b6 = _mm_xor_si128(b6, a1);\
b7 = _mm_xor_si128(b7, a2);\
}/*MixBytes*/
/* one round
* i = round number
* a0-a7 = input rows
* b0-b7 = output rows
*/
#define ROUND(i, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\
/* Add Round Constant */\
b1 = ROUND_CONST_Lx;\
a0 = _mm_xor_si128(a0, (ROUND_CONST_L0[i]));\
a1 = _mm_xor_si128(a1, b1);\
a2 = _mm_xor_si128(a2, b1);\
a3 = _mm_xor_si128(a3, b1);\
a4 = _mm_xor_si128(a4, b1);\
a5 = _mm_xor_si128(a5, b1);\
a6 = _mm_xor_si128(a6, b1);\
a7 = _mm_xor_si128(a7, (ROUND_CONST_L7[i]));\
\
/* ShiftBytes + SubBytes (interleaved) */\
b0 = _mm_xor_si128(b0, b0);\
a0 = _mm_shuffle_epi8(a0, (SUBSH_MASK[0]));\
a0 = _mm_aesenclast_si128(a0, b0);\
a1 = _mm_shuffle_epi8(a1, (SUBSH_MASK[1]));\
a1 = _mm_aesenclast_si128(a1, b0);\
a2 = _mm_shuffle_epi8(a2, (SUBSH_MASK[2]));\
a2 = _mm_aesenclast_si128(a2, b0);\
a3 = _mm_shuffle_epi8(a3, (SUBSH_MASK[3]));\
a3 = _mm_aesenclast_si128(a3, b0);\
a4 = _mm_shuffle_epi8(a4, (SUBSH_MASK[4]));\
a4 = _mm_aesenclast_si128(a4, b0);\
a5 = _mm_shuffle_epi8(a5, (SUBSH_MASK[5]));\
a5 = _mm_aesenclast_si128(a5, b0);\
a6 = _mm_shuffle_epi8(a6, (SUBSH_MASK[6]));\
a6 = _mm_aesenclast_si128(a6, b0);\
a7 = _mm_shuffle_epi8(a7, (SUBSH_MASK[7]));\
a7 = _mm_aesenclast_si128(a7, b0);\
\
/* MixBytes */\
MixBytes(a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7);\
}
/* 10 rounds, P and Q in parallel */
#define ROUNDS_P_Q(){\
ROUND(0, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\
ROUND(1, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\
ROUND(2, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\
ROUND(3, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\
ROUND(4, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\
ROUND(5, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\
ROUND(6, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\
ROUND(7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\
ROUND(8, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\
ROUND(9, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\
}
/* Matrix Transpose Step 1
* input is a 512-bit state with two columns in one xmm
* output is a 512-bit state with two rows in one xmm
* inputs: i0-i3
* outputs: i0, o1-o3
* clobbers: t0
*/
#define Matrix_Transpose_A(i0, i1, i2, i3, o1, o2, o3, t0){\
t0 = TRANSP_MASK;\
\
i0 = _mm_shuffle_epi8(i0, t0);\
i1 = _mm_shuffle_epi8(i1, t0);\
i2 = _mm_shuffle_epi8(i2, t0);\
i3 = _mm_shuffle_epi8(i3, t0);\
\
o1 = _mm_unpackhi_epi16(i0, i1);\
i0 = _mm_unpacklo_epi16(i0, i1);\
t0 = _mm_unpackhi_epi16(i2, i3);\
i2 = _mm_unpacklo_epi16(i2, i3);\
\
i0 = _mm_shuffle_epi32(i0, 216);\
o1 = _mm_shuffle_epi32(o1, 216);\
i2 = _mm_shuffle_epi32(i2, 216);\
t0 = _mm_shuffle_epi32(t0, 216);\
\
o2 = _mm_unpackhi_epi32(i0, i2);\
o3 = _mm_unpackhi_epi32(o1, t0);\
i0 = _mm_unpacklo_epi32(i0, i2);\
o1 = _mm_unpacklo_epi32(o1, t0);\
}/**/
/* Matrix Transpose Step 2
* input are two 512-bit states with two rows in one xmm
* output are two 512-bit states with one row of each state in one xmm
* inputs: i0-i3 = P, i4-i7 = Q
* outputs: (i0, o1-o7) = (P|Q)
* possible reassignments: (output reg = input reg)
* * i1 -> o3-7
* * i2 -> o5-7
* * i3 -> o7
* * i4 -> o3-7
* * i5 -> o6-7
*/
#define Matrix_Transpose_B(i0, i1, i2, i3, i4, i5, i6, i7, o1, o2, o3, o4, o5, o6, o7){\
o1 = _mm_unpackhi_epi64(i0, i4);\
i0 = _mm_unpacklo_epi64(i0, i4);\
o2 = _mm_unpacklo_epi64(i1, i5);\
o3 = _mm_unpackhi_epi64(i1, i5);\
o4 = _mm_unpacklo_epi64(i2, i6);\
o5 = _mm_unpackhi_epi64(i2, i6);\
o6 = _mm_unpacklo_epi64(i3, i7);\
o7 = _mm_unpackhi_epi64(i3, i7);\
}/**/
/* Matrix Transpose Inverse Step 2
* input are two 512-bit states with one row of each state in one xmm
* output are two 512-bit states with two rows in one xmm
* inputs: i0-i7 = (P|Q)
* outputs: (i0, i2, i4, i6) = P, (o0-o3) = Q
*/
#define Matrix_Transpose_B_INV(i0, i1, i2, i3, i4, i5, i6, i7, o0, o1, o2, o3){\
o0 = _mm_unpackhi_epi64(i0, i1);\
i0 = _mm_unpacklo_epi64(i0, i1);\
o1 = _mm_unpackhi_epi64(i2, i3);\
i2 = _mm_unpacklo_epi64(i2, i3);\
o2 = _mm_unpackhi_epi64(i4, i5);\
i4 = _mm_unpacklo_epi64(i4, i5);\
o3 = _mm_unpackhi_epi64(i6, i7);\
i6 = _mm_unpacklo_epi64(i6, i7);\
}/**/
/* Matrix Transpose Output Step 2
* input is one 512-bit state with two rows in one xmm
* output is one 512-bit state with one row in the low 64-bits of one xmm
* inputs: i0,i2,i4,i6 = S
* outputs: (i0-7) = (0|S)
*/
#define Matrix_Transpose_O_B(i0, i1, i2, i3, i4, i5, i6, i7, t0){\
t0 = _mm_xor_si128(t0, t0);\
i1 = _mm_unpackhi_epi64(i0, t0);\
i0 = _mm_unpacklo_epi64(i0, t0);\
i3 = _mm_unpackhi_epi64(i2, t0);\
i2 = _mm_unpacklo_epi64(i2, t0);\
i5 = _mm_unpackhi_epi64(i4, t0);\
i4 = _mm_unpacklo_epi64(i4, t0);\
i7 = _mm_unpackhi_epi64(i6, t0);\
i6 = _mm_unpacklo_epi64(i6, t0);\
}/**/
/* Matrix Transpose Output Inverse Step 2
* input is one 512-bit state with one row in the low 64-bits of one xmm
* output is one 512-bit state with two rows in one xmm
* inputs: i0-i7 = (0|S)
* outputs: (i0, i2, i4, i6) = S
*/
#define Matrix_Transpose_O_B_INV(i0, i1, i2, i3, i4, i5, i6, i7){\
i0 = _mm_unpacklo_epi64(i0, i1);\
i2 = _mm_unpacklo_epi64(i2, i3);\
i4 = _mm_unpacklo_epi64(i4, i5);\
i6 = _mm_unpacklo_epi64(i6, i7);\
}/**/
void INIT256(u64* h)
{
__m128i* const chaining = (__m128i*) h;
static __m128i xmm0, /*xmm1,*/ xmm2, /*xmm3, xmm4, xmm5,*/ xmm6, xmm7;
static __m128i /*xmm8, xmm9, xmm10, xmm11,*/ xmm12, xmm13, xmm14, xmm15;
/* load IV into registers xmm12 - xmm15 */
xmm12 = chaining[0];
xmm13 = chaining[1];
xmm14 = chaining[2];
xmm15 = chaining[3];
/* transform chaining value from column ordering into row ordering */
/* we put two rows (64 bit) of the IV into one 128-bit XMM register */
Matrix_Transpose_A(xmm12, xmm13, xmm14, xmm15, xmm2, xmm6, xmm7, xmm0);
/* store transposed IV */
chaining[0] = xmm12;
chaining[1] = xmm2;
chaining[2] = xmm6;
chaining[3] = xmm7;
}
void TF512(u64* h, u64* m)
{
__m128i* const chaining = (__m128i*) h;
__m128i* const message = (__m128i*) m;
static __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
static __m128i xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
static __m128i TEMP0;
static __m128i TEMP1;
static __m128i TEMP2;
static __m128i TEMP3;
#ifdef IACA_TRACE
IACA_START;
#endif
/* load message into registers xmm12 - xmm15 */
xmm12 = message[0];
xmm13 = message[1];
xmm14 = message[2];
xmm15 = message[3];
/* transform message M from column ordering into row ordering */
/* we first put two rows (64 bit) of the message into one 128-bit xmm register */
Matrix_Transpose_A(xmm12, xmm13, xmm14, xmm15, xmm2, xmm6, xmm7, xmm0);
/* load previous chaining value and xor message to CV to get input of P */
/* we first put two rows (2x64 bit) of the CV into one 128-bit xmm register */
/* result: CV+M in xmm8, xmm0, xmm4, xmm5 */
xmm8 = _mm_xor_si128(xmm12, chaining[0]);
xmm0 = _mm_xor_si128(xmm2, chaining[1]);
xmm4 = _mm_xor_si128(xmm6, chaining[2]);
xmm5 = _mm_xor_si128(xmm7, chaining[3]);
/* there are now 2 rows of the Groestl state (P and Q) in each xmm register */
/* unpack to get 1 row of P (64 bit) and Q (64 bit) into one xmm register */
/* result: the 8 rows of P and Q in xmm8 - xmm12 */
Matrix_Transpose_B(xmm8, xmm0, xmm4, xmm5, xmm12, xmm2, xmm6, xmm7, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);
/* compute the two permutations P and Q in parallel */
ROUNDS_P_Q();
/* unpack again to get two rows of P or two rows of Q in one xmm register */
Matrix_Transpose_B_INV(xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3);
/* xor output of P and Q */
/* result: P(CV+M)+Q(M) in xmm0...xmm3 */
xmm0 = _mm_xor_si128(xmm0, xmm8);
xmm1 = _mm_xor_si128(xmm1, xmm10);
xmm2 = _mm_xor_si128(xmm2, xmm12);
xmm3 = _mm_xor_si128(xmm3, xmm14);
/* xor CV (feed-forward) */
/* result: P(CV+M)+Q(M)+CV in xmm0...xmm3 */
xmm0 = _mm_xor_si128(xmm0, chaining[0]);
xmm1 = _mm_xor_si128(xmm1, chaining[1]);
xmm2 = _mm_xor_si128(xmm2, chaining[2]);
xmm3 = _mm_xor_si128(xmm3, chaining[3]);
/* store CV */
chaining[0] = xmm0;
chaining[1] = xmm1;
chaining[2] = xmm2;
chaining[3] = xmm3;
#ifdef IACA_TRACE
IACA_END;
#endif
return;
}
void OF512(u64* h)
{
__m128i* const chaining = (__m128i*) h;
static __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
static __m128i xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
static __m128i TEMP0;
static __m128i TEMP1;
static __m128i TEMP2;
static __m128i TEMP3;
/* load CV into registers xmm8, xmm10, xmm12, xmm14 */
xmm8 = chaining[0];
xmm10 = chaining[1];
xmm12 = chaining[2];
xmm14 = chaining[3];
/* there are now 2 rows of the CV in one xmm register */
/* unpack to get 1 row of P (64 bit) into one half of an xmm register */
/* result: the 8 input rows of P in xmm8 - xmm15 */
Matrix_Transpose_O_B(xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0);
/* compute the permutation P */
/* result: the output of P(CV) in xmm8 - xmm15 */
ROUNDS_P_Q();
/* unpack again to get two rows of P in one xmm register */
/* result: P(CV) in xmm8, xmm10, xmm12, xmm14 */
Matrix_Transpose_O_B_INV(xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);
/* xor CV to P output (feed-forward) */
/* result: P(CV)+CV in xmm8, xmm10, xmm12, xmm14 */
xmm8 = _mm_xor_si128(xmm8, (chaining[0]));
xmm10 = _mm_xor_si128(xmm10, (chaining[1]));
xmm12 = _mm_xor_si128(xmm12, (chaining[2]));
xmm14 = _mm_xor_si128(xmm14, (chaining[3]));
/* transform state back from row ordering into column ordering */
/* result: final hash value in xmm9, xmm11 */
Matrix_Transpose_A(xmm8, xmm10, xmm12, xmm14, xmm4, xmm9, xmm11, xmm0);
/* we only need to return the truncated half of the state */
chaining[2] = xmm9;
chaining[3] = xmm11;
}

View File

@@ -1,793 +0,0 @@
/* groestl-intr-vperm.h Aug 2011
*
* Groestl implementation with intrinsics using ssse3 instructions.
* Author: Günther A. Roland, Martin Schläffer
*
* Based on the vperm and aes_ni implementations of the hash function Groestl
* by Cagdas Calik <ccalik@metu.edu.tr> http://www.metu.edu.tr/~ccalik/
* Institute of Applied Mathematics, Middle East Technical University, Turkey
*
* This code is placed in the public domain
*/
#include <tmmintrin.h>
#include "hash-groestl256.h"
/* global constants */
__m128i ROUND_CONST_Lx;
__m128i ROUND_CONST_L0[ROUNDS512];
__m128i ROUND_CONST_L7[ROUNDS512];
__m128i ROUND_CONST_P[ROUNDS1024];
__m128i ROUND_CONST_Q[ROUNDS1024];
__m128i TRANSP_MASK;
__m128i SUBSH_MASK[8];
__m128i ALL_0F;
__m128i ALL_15;
__m128i ALL_1B;
__m128i ALL_63;
__m128i ALL_FF;
__m128i VPERM_IPT[2];
__m128i VPERM_OPT[2];
__m128i VPERM_INV[2];
__m128i VPERM_SB1[2];
__m128i VPERM_SB2[2];
__m128i VPERM_SB4[2];
__m128i VPERM_SBO[2];
#define tos(a) #a
#define tostr(a) tos(a)
#define SET_SHARED_CONSTANTS(){\
TRANSP_MASK = _mm_set_epi32(0x0f070b03, 0x0e060a02, 0x0d050901, 0x0c040800);\
ALL_1B = _mm_set_epi32(0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b);\
ALL_63 = _mm_set_epi32(0x63636363, 0x63636363, 0x63636363, 0x63636363);\
ALL_0F = _mm_set_epi32(0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f);\
ALL_15 = _mm_set_epi32(0x15151515, 0x15151515, 0x15151515, 0x15151515);\
VPERM_IPT[0] = _mm_set_epi32(0xCD80B1FC, 0xB0FDCC81, 0x4C01307D, 0x317C4D00);\
VPERM_IPT[1] = _mm_set_epi32(0xCABAE090, 0x52227808, 0xC2B2E898, 0x5A2A7000);\
VPERM_OPT[0] = _mm_set_epi32(0xE10D5DB1, 0xB05C0CE0, 0x01EDBD51, 0x50BCEC00);\
VPERM_OPT[1] = _mm_set_epi32(0xF7974121, 0xDEBE6808, 0xFF9F4929, 0xD6B66000);\
VPERM_INV[0] = _mm_set_epi32(0x030D0E0C, 0x02050809, 0x01040A06, 0x0F0B0780);\
VPERM_INV[1] = _mm_set_epi32(0x04070309, 0x0A0B0C02, 0x0E05060F, 0x0D080180);\
VPERM_SB1[0] = _mm_set_epi32(0x3BF7CCC1, 0x0D2ED9EF, 0x3618D415, 0xFAE22300);\
VPERM_SB1[1] = _mm_set_epi32(0xA5DF7A6E, 0x142AF544, 0xB19BE18F, 0xCB503E00);\
VPERM_SB2[0] = _mm_set_epi32(0xC2A163C8, 0xAB82234A, 0x69EB8840, 0x0AE12900);\
VPERM_SB2[1] = _mm_set_epi32(0x5EB7E955, 0xBC982FCD, 0xE27A93C6, 0x0B712400);\
VPERM_SB4[0] = _mm_set_epi32(0xBA44FE79, 0x876D2914, 0x3D50AED7, 0xC393EA00);\
VPERM_SB4[1] = _mm_set_epi32(0xA876DE97, 0x49087E9F, 0xE1E937A0, 0x3FD64100);\
}/**/
/* VPERM
* Transform w/o settings c*
* transforms 2 rows to/from "vperm mode"
* this function is derived from:
* vperm and aes_ni implementations of hash function Grostl
* by Cagdas CALIK
* inputs:
* a0, a1 = 2 rows
* table = transformation table to use
* t*, c* = clobbers
* outputs:
* a0, a1 = 2 rows transformed with table
* */
#define VPERM_Transform_No_Const(a0, a1, t0, t1, t2, t3, c0, c1, c2){\
t0 = c0;\
t1 = c0;\
t0 = _mm_andnot_si128(t0, a0);\
t1 = _mm_andnot_si128(t1, a1);\
t0 = _mm_srli_epi32(t0, 4);\
t1 = _mm_srli_epi32(t1, 4);\
a0 = _mm_and_si128(a0, c0);\
a1 = _mm_and_si128(a1, c0);\
t2 = c2;\
t3 = c2;\
t2 = _mm_shuffle_epi8(t2, a0);\
t3 = _mm_shuffle_epi8(t3, a1);\
a0 = c1;\
a1 = c1;\
a0 = _mm_shuffle_epi8(a0, t0);\
a1 = _mm_shuffle_epi8(a1, t1);\
a0 = _mm_xor_si128(a0, t2);\
a1 = _mm_xor_si128(a1, t3);\
}/**/
#define VPERM_Transform_Set_Const(table, c0, c1, c2){\
c0 = ALL_0F;\
c1 = ((__m128i*) table )[0];\
c2 = ((__m128i*) table )[1];\
}/**/
/* VPERM
* Transform
* transforms 2 rows to/from "vperm mode"
* this function is derived from:
* vperm and aes_ni implementations of hash function Grostl
* by Cagdas CALIK
* inputs:
* a0, a1 = 2 rows
* table = transformation table to use
* t*, c* = clobbers
* outputs:
* a0, a1 = 2 rows transformed with table
* */
#define VPERM_Transform(a0, a1, table, t0, t1, t2, t3, c0, c1, c2){\
VPERM_Transform_Set_Const(table, c0, c1, c2);\
VPERM_Transform_No_Const(a0, a1, t0, t1, t2, t3, c0, c1, c2);\
}/**/
/* VPERM
* Transform State
* inputs:
* a0-a3 = state
* table = transformation table to use
* t* = clobbers
* outputs:
* a0-a3 = transformed state
* */
#define VPERM_Transform_State(a0, a1, a2, a3, table, t0, t1, t2, t3, c0, c1, c2){\
VPERM_Transform_Set_Const(table, c0, c1, c2);\
VPERM_Transform_No_Const(a0, a1, t0, t1, t2, t3, c0, c1, c2);\
VPERM_Transform_No_Const(a2, a3, t0, t1, t2, t3, c0, c1, c2);\
}/**/
/* VPERM
* Add Constant to State
* inputs:
* a0-a7 = state
* constant = constant to add
* t0 = clobber
* outputs:
* a0-a7 = state + constant
* */
#define VPERM_Add_Constant(a0, a1, a2, a3, a4, a5, a6, a7, constant, t0){\
t0 = constant;\
a0 = _mm_xor_si128(a0, t0);\
a1 = _mm_xor_si128(a1, t0);\
a2 = _mm_xor_si128(a2, t0);\
a3 = _mm_xor_si128(a3, t0);\
a4 = _mm_xor_si128(a4, t0);\
a5 = _mm_xor_si128(a5, t0);\
a6 = _mm_xor_si128(a6, t0);\
a7 = _mm_xor_si128(a7, t0);\
}/**/
/* VPERM
* Set Substitute Core Constants
* */
#define VPERM_Substitute_Core_Set_Const(c0, c1, c2){\
VPERM_Transform_Set_Const(VPERM_INV, c0, c1, c2);\
}/**/
/* VPERM
* Substitute Core
* first part of sbox inverse computation
* this function is derived from:
* vperm and aes_ni implementations of hash function Grostl
* by Cagdas CALIK
* inputs:
* a0 = 1 row
* t*, c* = clobbers
* outputs:
* b0a, b0b = inputs for lookup step
* */
#define VPERM_Substitute_Core(a0, b0a, b0b, t0, t1, c0, c1, c2){\
t0 = c0;\
t0 = _mm_andnot_si128(t0, a0);\
t0 = _mm_srli_epi32(t0, 4);\
a0 = _mm_and_si128(a0, c0);\
b0a = c1;\
b0a = _mm_shuffle_epi8(b0a, a0);\
a0 = _mm_xor_si128(a0, t0);\
b0b = c2;\
b0b = _mm_shuffle_epi8(b0b, t0);\
b0b = _mm_xor_si128(b0b, b0a);\
t1 = c2;\
t1 = _mm_shuffle_epi8(t1, a0);\
t1 = _mm_xor_si128(t1, b0a);\
b0a = c2;\
b0a = _mm_shuffle_epi8(b0a, b0b);\
b0a = _mm_xor_si128(b0a, a0);\
b0b = c2;\
b0b = _mm_shuffle_epi8(b0b, t1);\
b0b = _mm_xor_si128(b0b, t0);\
}/**/
/* VPERM
* Lookup
* second part of sbox inverse computation
* this function is derived from:
* vperm and aes_ni implementations of hash function Grostl
* by Cagdas CALIK
* inputs:
* a0a, a0b = output of Substitution Core
* table = lookup table to use (*1 / *2 / *4)
* t0 = clobber
* outputs:
* b0 = output of sbox + multiplication
* */
#define VPERM_Lookup(a0a, a0b, table, b0, t0){\
b0 = ((__m128i*) table )[0];\
t0 = ((__m128i*) table )[1];\
b0 = _mm_shuffle_epi8(b0, a0b);\
t0 = _mm_shuffle_epi8(t0, a0a);\
b0 = _mm_xor_si128(b0, t0);\
}/**/
/* VPERM
* SubBytes and *2 / *4
* this function is derived from:
* Constant-time SSSE3 AES core implementation
* by Mike Hamburg
* and
* vperm and aes_ni implementations of hash function Grostl
* by Cagdas CALIK
* inputs:
* a0-a7 = state
* t*, c* = clobbers
* outputs:
* a0-a7 = state * 4
* c2 = row0 * 2 -> b0
* c1 = row7 * 2 -> b3
* c0 = row7 * 1 -> b4
* t2 = row4 * 1 -> b7
* TEMP_MUL1 = row(i) * 1
* TEMP_MUL2 = row(i) * 2
*
* call:VPERM_SUB_MULTIPLY(a0, a1, a2, a3, a4, a5, a6, a7, b1, b2, b5, b6, b0, b3, b4, b7) */
#define VPERM_SUB_MULTIPLY(a0, a1, a2, a3, a4, a5, a6, a7, t0, t1, t3, t4, c2, c1, c0, t2){\
/* set Constants */\
VPERM_Substitute_Core_Set_Const(c0, c1, c2);\
/* row 1 */\
VPERM_Substitute_Core(a1, t0, t1, t3, t4, c0, c1, c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, t2, t4);\
TEMP_MUL1[1] = t2;\
VPERM_Lookup(t0, t1, VPERM_SB2, t3, t4);\
TEMP_MUL2[1] = t3;\
VPERM_Lookup(t0, t1, VPERM_SB4, a1, t4);\
/* --- */\
/* row 2 */\
VPERM_Substitute_Core(a2, t0, t1, t3, t4, c0, c1, c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, t2, t4);\
TEMP_MUL1[2] = t2;\
VPERM_Lookup(t0, t1, VPERM_SB2, t3, t4);\
TEMP_MUL2[2] = t3;\
VPERM_Lookup(t0, t1, VPERM_SB4, a2, t4);\
/* --- */\
/* row 3 */\
VPERM_Substitute_Core(a3, t0, t1, t3, t4, c0, c1, c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, t2, t4);\
TEMP_MUL1[3] = t2;\
VPERM_Lookup(t0, t1, VPERM_SB2, t3, t4);\
TEMP_MUL2[3] = t3;\
VPERM_Lookup(t0, t1, VPERM_SB4, a3, t4);\
/* --- */\
/* row 5 */\
VPERM_Substitute_Core(a5, t0, t1, t3, t4, c0, c1, c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, t2, t4);\
TEMP_MUL1[5] = t2;\
VPERM_Lookup(t0, t1, VPERM_SB2, t3, t4);\
TEMP_MUL2[5] = t3;\
VPERM_Lookup(t0, t1, VPERM_SB4, a5, t4);\
/* --- */\
/* row 6 */\
VPERM_Substitute_Core(a6, t0, t1, t3, t4, c0, c1, c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, t2, t4);\
TEMP_MUL1[6] = t2;\
VPERM_Lookup(t0, t1, VPERM_SB2, t3, t4);\
TEMP_MUL2[6] = t3;\
VPERM_Lookup(t0, t1, VPERM_SB4, a6, t4);\
/* --- */\
/* row 7 */\
VPERM_Substitute_Core(a7, t0, t1, t3, t4, c0, c1, c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, t2, t4);\
TEMP_MUL1[7] = t2;\
VPERM_Lookup(t0, t1, VPERM_SB2, c1, t4); /*c1 -> b3*/\
VPERM_Lookup(t0, t1, VPERM_SB4, a7, t4);\
/* --- */\
/* row 4 */\
VPERM_Substitute_Core(a4, t0, t1, t3, t4, c0, (VPERM_INV[0]), c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, t2, t4); /*t2 -> b7*/\
VPERM_Lookup(t0, t1, VPERM_SB2, t3, t4);\
TEMP_MUL2[4] = t3;\
VPERM_Lookup(t0, t1, VPERM_SB4, a4, t4);\
/* --- */\
/* row 0 */\
VPERM_Substitute_Core(a0, t0, t1, t3, t4, c0, (VPERM_INV[0]), c2);\
VPERM_Lookup(t0, t1, VPERM_SB1, c0, t4); /*c0 -> b4*/\
VPERM_Lookup(t0, t1, VPERM_SB2, c2, t4); /*c2 -> b0*/\
TEMP_MUL2[0] = c2;\
VPERM_Lookup(t0, t1, VPERM_SB4, a0, t4);\
/* --- */\
}/**/
/* Optimized MixBytes
* inputs:
* a0-a7 = (row0-row7) * 4
* b0 = row0 * 2
* b3 = row7 * 2
* b4 = row7 * 1
* b7 = row4 * 1
* all *1 and *2 values must also be in TEMP_MUL1, TEMP_MUL2
* output: b0-b7
* */
#define MixBytes(a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\
/* save one value */\
TEMP_MUL4 = a3;\
/* 1 */\
b1 = a0;\
b1 = _mm_xor_si128(b1, a5);\
b1 = _mm_xor_si128(b1, b4); /* -> helper! */\
b1 = _mm_xor_si128(b1, (TEMP_MUL2[3]));\
b2 = b1;\
\
/* 2 */\
b5 = a1;\
b5 = _mm_xor_si128(b5, a4);\
b5 = _mm_xor_si128(b5, b7); /* -> helper! */\
b5 = _mm_xor_si128(b5, b3); /* -> helper! */\
b6 = b5;\
\
/* 4 */\
b7 = _mm_xor_si128(b7, a6);\
/*b7 = _mm_xor_si128(b7, (TEMP_MUL1[4])); -> helper! */\
b7 = _mm_xor_si128(b7, (TEMP_MUL1[6]));\
b7 = _mm_xor_si128(b7, (TEMP_MUL2[1]));\
b7 = _mm_xor_si128(b7, b3); /* -> helper! */\
b2 = _mm_xor_si128(b2, b7);\
\
/* 3 */\
b0 = _mm_xor_si128(b0, a7);\
b0 = _mm_xor_si128(b0, (TEMP_MUL1[5]));\
b0 = _mm_xor_si128(b0, (TEMP_MUL1[7]));\
/*b0 = _mm_xor_si128(b0, (TEMP_MUL2[0])); -> helper! */\
b0 = _mm_xor_si128(b0, (TEMP_MUL2[2]));\
b3 = b0;\
b1 = _mm_xor_si128(b1, b0);\
b0 = _mm_xor_si128(b0, b7); /* moved from 4 */\
\
/* 5 */\
b4 = _mm_xor_si128(b4, a2);\
/*b4 = _mm_xor_si128(b4, (TEMP_MUL1[0])); -> helper! */\
b4 = _mm_xor_si128(b4, (TEMP_MUL1[2]));\
b4 = _mm_xor_si128(b4, (TEMP_MUL2[3]));\
b4 = _mm_xor_si128(b4, (TEMP_MUL2[5]));\
b3 = _mm_xor_si128(b3, b4);\
b6 = _mm_xor_si128(b6, b4);\
\
/* 6 */\
a3 = _mm_xor_si128(a3, (TEMP_MUL1[1]));\
a3 = _mm_xor_si128(a3, (TEMP_MUL1[3]));\
a3 = _mm_xor_si128(a3, (TEMP_MUL2[4]));\
a3 = _mm_xor_si128(a3, (TEMP_MUL2[6]));\
b4 = _mm_xor_si128(b4, a3);\
b5 = _mm_xor_si128(b5, a3);\
b7 = _mm_xor_si128(b7, a3);\
\
/* 7 */\
a1 = _mm_xor_si128(a1, (TEMP_MUL1[1]));\
a1 = _mm_xor_si128(a1, (TEMP_MUL2[4]));\
b2 = _mm_xor_si128(b2, a1);\
b3 = _mm_xor_si128(b3, a1);\
\
/* 8 */\
a5 = _mm_xor_si128(a5, (TEMP_MUL1[5]));\
a5 = _mm_xor_si128(a5, (TEMP_MUL2[0]));\
b6 = _mm_xor_si128(b6, a5);\
b7 = _mm_xor_si128(b7, a5);\
\
/* 9 */\
a3 = TEMP_MUL1[2];\
a3 = _mm_xor_si128(a3, (TEMP_MUL2[5]));\
b0 = _mm_xor_si128(b0, a3);\
b5 = _mm_xor_si128(b5, a3);\
\
/* 10 */\
a1 = TEMP_MUL1[6];\
a1 = _mm_xor_si128(a1, (TEMP_MUL2[1]));\
b1 = _mm_xor_si128(b1, a1);\
b4 = _mm_xor_si128(b4, a1);\
\
/* 11 */\
a5 = TEMP_MUL1[3];\
a5 = _mm_xor_si128(a5, (TEMP_MUL2[6]));\
b1 = _mm_xor_si128(b1, a5);\
b6 = _mm_xor_si128(b6, a5);\
\
/* 12 */\
a3 = TEMP_MUL1[7];\
a3 = _mm_xor_si128(a3, (TEMP_MUL2[2]));\
b2 = _mm_xor_si128(b2, a3);\
b5 = _mm_xor_si128(b5, a3);\
\
/* 13 */\
b0 = _mm_xor_si128(b0, (TEMP_MUL4));\
b0 = _mm_xor_si128(b0, a4);\
b1 = _mm_xor_si128(b1, a4);\
b3 = _mm_xor_si128(b3, a6);\
b4 = _mm_xor_si128(b4, a0);\
b4 = _mm_xor_si128(b4, a7);\
b5 = _mm_xor_si128(b5, a0);\
b7 = _mm_xor_si128(b7, a2);\
}/**/
#define SET_CONSTANTS(){\
SET_SHARED_CONSTANTS();\
SUBSH_MASK[0] = _mm_set_epi32(0x080f0e0d, 0x0c0b0a09, 0x07060504, 0x03020100);\
SUBSH_MASK[1] = _mm_set_epi32(0x0a09080f, 0x0e0d0c0b, 0x00070605, 0x04030201);\
SUBSH_MASK[2] = _mm_set_epi32(0x0c0b0a09, 0x080f0e0d, 0x01000706, 0x05040302);\
SUBSH_MASK[3] = _mm_set_epi32(0x0e0d0c0b, 0x0a09080f, 0x02010007, 0x06050403);\
SUBSH_MASK[4] = _mm_set_epi32(0x0f0e0d0c, 0x0b0a0908, 0x03020100, 0x07060504);\
SUBSH_MASK[5] = _mm_set_epi32(0x09080f0e, 0x0d0c0b0a, 0x04030201, 0x00070605);\
SUBSH_MASK[6] = _mm_set_epi32(0x0b0a0908, 0x0f0e0d0c, 0x05040302, 0x01000706);\
SUBSH_MASK[7] = _mm_set_epi32(0x0d0c0b0a, 0x09080f0e, 0x06050403, 0x02010007);\
for(i = 0; i < ROUNDS512; i++)\
{\
ROUND_CONST_L0[i] = _mm_set_epi32(0xffffffff, 0xffffffff, 0x70605040 ^ (i * 0x01010101), 0x30201000 ^ (i * 0x01010101));\
ROUND_CONST_L7[i] = _mm_set_epi32(0x8f9fafbf ^ (i * 0x01010101), 0xcfdfefff ^ (i * 0x01010101), 0x00000000, 0x00000000);\
}\
ROUND_CONST_Lx = _mm_set_epi32(0xffffffff, 0xffffffff, 0x00000000, 0x00000000);\
}/**/
/* vperm:
* transformation before rounds with ipt
* first round add transformed constant
* middle rounds: add constant XOR 0x15...15
* last round: additionally add 0x15...15 after MB
* transformation after rounds with opt
*/
/* one round
* i = round number
* a0-a7 = input rows
* b0-b7 = output rows
*/
#define ROUND(i, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\
/* AddRoundConstant + ShiftBytes (interleaved) */\
b1 = ROUND_CONST_Lx;\
a0 = _mm_xor_si128(a0, (ROUND_CONST_L0[i]));\
a1 = _mm_xor_si128(a1, b1);\
a2 = _mm_xor_si128(a2, b1);\
a3 = _mm_xor_si128(a3, b1);\
a0 = _mm_shuffle_epi8(a0, (SUBSH_MASK[0]));\
a1 = _mm_shuffle_epi8(a1, (SUBSH_MASK[1]));\
a4 = _mm_xor_si128(a4, b1);\
a2 = _mm_shuffle_epi8(a2, (SUBSH_MASK[2]));\
a3 = _mm_shuffle_epi8(a3, (SUBSH_MASK[3]));\
a5 = _mm_xor_si128(a5, b1);\
a6 = _mm_xor_si128(a6, b1);\
a4 = _mm_shuffle_epi8(a4, (SUBSH_MASK[4]));\
a5 = _mm_shuffle_epi8(a5, (SUBSH_MASK[5]));\
a7 = _mm_xor_si128(a7, (ROUND_CONST_L7[i]));\
a6 = _mm_shuffle_epi8(a6, (SUBSH_MASK[6]));\
a7 = _mm_shuffle_epi8(a7, (SUBSH_MASK[7]));\
/* SubBytes + Multiplication by 2 and 4 */\
VPERM_SUB_MULTIPLY(a0, a1, a2, a3, a4, a5, a6, a7, b1, b2, b5, b6, b0, b3, b4, b7);\
/* MixBytes */\
MixBytes(a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7);\
}/**/
/* 10 rounds, P and Q in parallel */
#define ROUNDS_P_Q(){\
VPERM_Add_Constant(xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, ALL_15, xmm0);\
ROUND(0, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\
ROUND(1, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\
ROUND(2, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\
ROUND(3, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\
ROUND(4, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\
ROUND(5, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\
ROUND(6, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\
ROUND(7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\
ROUND(8, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\
ROUND(9, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\
VPERM_Add_Constant(xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, ALL_15, xmm0);\
}
/* Matrix Transpose Step 1
* input is a 512-bit state with two columns in one xmm
* output is a 512-bit state with two rows in one xmm
* inputs: i0-i3
* outputs: i0, o1-o3
* clobbers: t0
*/
#define Matrix_Transpose_A(i0, i1, i2, i3, o1, o2, o3, t0){\
t0 = TRANSP_MASK;\
\
i0 = _mm_shuffle_epi8(i0, t0);\
i1 = _mm_shuffle_epi8(i1, t0);\
i2 = _mm_shuffle_epi8(i2, t0);\
i3 = _mm_shuffle_epi8(i3, t0);\
\
o1 = i0;\
t0 = i2;\
\
i0 = _mm_unpacklo_epi16(i0, i1);\
o1 = _mm_unpackhi_epi16(o1, i1);\
i2 = _mm_unpacklo_epi16(i2, i3);\
t0 = _mm_unpackhi_epi16(t0, i3);\
\
i0 = _mm_shuffle_epi32(i0, 216);\
o1 = _mm_shuffle_epi32(o1, 216);\
i2 = _mm_shuffle_epi32(i2, 216);\
t0 = _mm_shuffle_epi32(t0, 216);\
\
o2 = i0;\
o3 = o1;\
\
i0 = _mm_unpacklo_epi32(i0, i2);\
o1 = _mm_unpacklo_epi32(o1, t0);\
o2 = _mm_unpackhi_epi32(o2, i2);\
o3 = _mm_unpackhi_epi32(o3, t0);\
}/**/
/* Matrix Transpose Step 2
* input are two 512-bit states with two rows in one xmm
* output are two 512-bit states with one row of each state in one xmm
* inputs: i0-i3 = P, i4-i7 = Q
* outputs: (i0, o1-o7) = (P|Q)
* possible reassignments: (output reg = input reg)
* * i1 -> o3-7
* * i2 -> o5-7
* * i3 -> o7
* * i4 -> o3-7
* * i5 -> o6-7
*/
#define Matrix_Transpose_B(i0, i1, i2, i3, i4, i5, i6, i7, o1, o2, o3, o4, o5, o6, o7){\
o1 = i0;\
o2 = i1;\
i0 = _mm_unpacklo_epi64(i0, i4);\
o1 = _mm_unpackhi_epi64(o1, i4);\
o3 = i1;\
o4 = i2;\
o2 = _mm_unpacklo_epi64(o2, i5);\
o3 = _mm_unpackhi_epi64(o3, i5);\
o5 = i2;\
o6 = i3;\
o4 = _mm_unpacklo_epi64(o4, i6);\
o5 = _mm_unpackhi_epi64(o5, i6);\
o7 = i3;\
o6 = _mm_unpacklo_epi64(o6, i7);\
o7 = _mm_unpackhi_epi64(o7, i7);\
}/**/
/* Matrix Transpose Inverse Step 2
* input are two 512-bit states with one row of each state in one xmm
* output are two 512-bit states with two rows in one xmm
* inputs: i0-i7 = (P|Q)
* outputs: (i0, i2, i4, i6) = P, (o0-o3) = Q
*/
#define Matrix_Transpose_B_INV(i0, i1, i2, i3, i4, i5, i6, i7, o0, o1, o2, o3){\
o0 = i0;\
i0 = _mm_unpacklo_epi64(i0, i1);\
o0 = _mm_unpackhi_epi64(o0, i1);\
o1 = i2;\
i2 = _mm_unpacklo_epi64(i2, i3);\
o1 = _mm_unpackhi_epi64(o1, i3);\
o2 = i4;\
i4 = _mm_unpacklo_epi64(i4, i5);\
o2 = _mm_unpackhi_epi64(o2, i5);\
o3 = i6;\
i6 = _mm_unpacklo_epi64(i6, i7);\
o3 = _mm_unpackhi_epi64(o3, i7);\
}/**/
/* Matrix Transpose Output Step 2
* input is one 512-bit state with two rows in one xmm
* output is one 512-bit state with one row in the low 64-bits of one xmm
* inputs: i0,i2,i4,i6 = S
* outputs: (i0-7) = (0|S)
*/
#define Matrix_Transpose_O_B(i0, i1, i2, i3, i4, i5, i6, i7, t0){\
t0 = _mm_xor_si128(t0, t0);\
i1 = i0;\
i3 = i2;\
i5 = i4;\
i7 = i6;\
i0 = _mm_unpacklo_epi64(i0, t0);\
i1 = _mm_unpackhi_epi64(i1, t0);\
i2 = _mm_unpacklo_epi64(i2, t0);\
i3 = _mm_unpackhi_epi64(i3, t0);\
i4 = _mm_unpacklo_epi64(i4, t0);\
i5 = _mm_unpackhi_epi64(i5, t0);\
i6 = _mm_unpacklo_epi64(i6, t0);\
i7 = _mm_unpackhi_epi64(i7, t0);\
}/**/
/* Matrix Transpose Output Inverse Step 2
* input is one 512-bit state with one row in the low 64-bits of one xmm
* output is one 512-bit state with two rows in one xmm
* inputs: i0-i7 = (0|S)
* outputs: (i0, i2, i4, i6) = S
*/
#define Matrix_Transpose_O_B_INV(i0, i1, i2, i3, i4, i5, i6, i7){\
i0 = _mm_unpacklo_epi64(i0, i1);\
i2 = _mm_unpacklo_epi64(i2, i3);\
i4 = _mm_unpacklo_epi64(i4, i5);\
i6 = _mm_unpacklo_epi64(i6, i7);\
}/**/
/* transform round constants into VPERM mode */
#define VPERM_Transform_RoundConst_CNT2(i, j){\
xmm0 = ROUND_CONST_L0[i];\
xmm1 = ROUND_CONST_L7[i];\
xmm2 = ROUND_CONST_L0[j];\
xmm3 = ROUND_CONST_L7[j];\
VPERM_Transform_State(xmm0, xmm1, xmm2, xmm3, VPERM_IPT, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10);\
xmm0 = _mm_xor_si128(xmm0, (ALL_15));\
xmm1 = _mm_xor_si128(xmm1, (ALL_15));\
xmm2 = _mm_xor_si128(xmm2, (ALL_15));\
xmm3 = _mm_xor_si128(xmm3, (ALL_15));\
ROUND_CONST_L0[i] = xmm0;\
ROUND_CONST_L7[i] = xmm1;\
ROUND_CONST_L0[j] = xmm2;\
ROUND_CONST_L7[j] = xmm3;\
}/**/
/* transform round constants into VPERM mode */
#define VPERM_Transform_RoundConst(){\
xmm0 = ROUND_CONST_Lx;\
VPERM_Transform(xmm0, xmm1, VPERM_IPT, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10);\
xmm0 = _mm_xor_si128(xmm0, (ALL_15));\
ROUND_CONST_Lx = xmm0;\
VPERM_Transform_RoundConst_CNT2(0, 1);\
VPERM_Transform_RoundConst_CNT2(2, 3);\
VPERM_Transform_RoundConst_CNT2(4, 5);\
VPERM_Transform_RoundConst_CNT2(6, 7);\
VPERM_Transform_RoundConst_CNT2(8, 9);\
}/**/
void INIT256(u64* h)
{
__m128i* const chaining = (__m128i*) h;
static __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
static __m128i xmm8, xmm9, xmm10, /*xmm11,*/ xmm12, xmm13, xmm14, xmm15;
/* transform round constants into VPERM mode */
VPERM_Transform_RoundConst();
/* load IV into registers xmm12 - xmm15 */
xmm12 = chaining[0];
xmm13 = chaining[1];
xmm14 = chaining[2];
xmm15 = chaining[3];
/* transform chaining value from column ordering into row ordering */
/* we put two rows (64 bit) of the IV into one 128-bit XMM register */
VPERM_Transform_State(xmm12, xmm13, xmm14, xmm15, VPERM_IPT, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);
Matrix_Transpose_A(xmm12, xmm13, xmm14, xmm15, xmm2, xmm6, xmm7, xmm0);
/* store transposed IV */
chaining[0] = xmm12;
chaining[1] = xmm2;
chaining[2] = xmm6;
chaining[3] = xmm7;
}
void TF512(u64* h, u64* m)
{
__m128i* const chaining = (__m128i*) h;
__m128i* const message = (__m128i*) m;
static __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
static __m128i xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
static __m128i TEMP_MUL1[8];
static __m128i TEMP_MUL2[8];
static __m128i TEMP_MUL4;
#ifdef IACA_TRACE
IACA_START;
#endif
/* load message into registers xmm12 - xmm15 */
xmm12 = message[0];
xmm13 = message[1];
xmm14 = message[2];
xmm15 = message[3];
/* transform message M from column ordering into row ordering */
/* we first put two rows (64 bit) of the message into one 128-bit xmm register */
VPERM_Transform_State(xmm12, xmm13, xmm14, xmm15, VPERM_IPT, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);
Matrix_Transpose_A(xmm12, xmm13, xmm14, xmm15, xmm2, xmm6, xmm7, xmm0);
/* load previous chaining value */
/* we first put two rows (64 bit) of the CV into one 128-bit xmm register */
xmm8 = chaining[0];
xmm0 = chaining[1];
xmm4 = chaining[2];
xmm5 = chaining[3];
/* xor message to CV get input of P */
/* result: CV+M in xmm8, xmm0, xmm4, xmm5 */
xmm8 = _mm_xor_si128(xmm8, xmm12);
xmm0 = _mm_xor_si128(xmm0, xmm2);
xmm4 = _mm_xor_si128(xmm4, xmm6);
xmm5 = _mm_xor_si128(xmm5, xmm7);
/* there are now 2 rows of the Groestl state (P and Q) in each xmm register */
/* unpack to get 1 row of P (64 bit) and Q (64 bit) into one xmm register */
/* result: the 8 rows of P and Q in xmm8 - xmm12 */
Matrix_Transpose_B(xmm8, xmm0, xmm4, xmm5, xmm12, xmm2, xmm6, xmm7, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);
/* compute the two permutations P and Q in parallel */
ROUNDS_P_Q();
/* unpack again to get two rows of P or two rows of Q in one xmm register */
Matrix_Transpose_B_INV(xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3);
/* xor output of P and Q */
/* result: P(CV+M)+Q(M) in xmm0...xmm3 */
xmm0 = _mm_xor_si128(xmm0, xmm8);
xmm1 = _mm_xor_si128(xmm1, xmm10);
xmm2 = _mm_xor_si128(xmm2, xmm12);
xmm3 = _mm_xor_si128(xmm3, xmm14);
/* xor CV (feed-forward) */
/* result: P(CV+M)+Q(M)+CV in xmm0...xmm3 */
xmm0 = _mm_xor_si128(xmm0, (chaining[0]));
xmm1 = _mm_xor_si128(xmm1, (chaining[1]));
xmm2 = _mm_xor_si128(xmm2, (chaining[2]));
xmm3 = _mm_xor_si128(xmm3, (chaining[3]));
/* store CV */
chaining[0] = xmm0;
chaining[1] = xmm1;
chaining[2] = xmm2;
chaining[3] = xmm3;
#ifdef IACA_TRACE
IACA_END;
#endif
return;
}
void OF512(u64* h)
{
__m128i* const chaining = (__m128i*) h;
static __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
static __m128i xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
static __m128i TEMP_MUL1[8];
static __m128i TEMP_MUL2[8];
static __m128i TEMP_MUL4;
/* load CV into registers xmm8, xmm10, xmm12, xmm14 */
xmm8 = chaining[0];
xmm10 = chaining[1];
xmm12 = chaining[2];
xmm14 = chaining[3];
/* there are now 2 rows of the CV in one xmm register */
/* unpack to get 1 row of P (64 bit) into one half of an xmm register */
/* result: the 8 input rows of P in xmm8 - xmm15 */
Matrix_Transpose_O_B(xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0);
/* compute the permutation P */
/* result: the output of P(CV) in xmm8 - xmm15 */
ROUNDS_P_Q();
/* unpack again to get two rows of P in one xmm register */
/* result: P(CV) in xmm8, xmm10, xmm12, xmm14 */
Matrix_Transpose_O_B_INV(xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);
/* xor CV to P output (feed-forward) */
/* result: P(CV)+CV in xmm8, xmm10, xmm12, xmm14 */
xmm8 = _mm_xor_si128(xmm8, (chaining[0]));
xmm10 = _mm_xor_si128(xmm10, (chaining[1]));
xmm12 = _mm_xor_si128(xmm12, (chaining[2]));
xmm14 = _mm_xor_si128(xmm14, (chaining[3]));
/* transform state back from row ordering into column ordering */
/* result: final hash value in xmm9, xmm11 */
Matrix_Transpose_A(xmm8, xmm10, xmm12, xmm14, xmm4, xmm9, xmm11, xmm0);
VPERM_Transform(xmm9, xmm11, VPERM_OPT, xmm0, xmm1, xmm2, xmm3, xmm5, xmm6, xmm7);
/* we only need to return the truncated half of the state */
chaining[2] = xmm9;
chaining[3] = xmm11;
return;
}//OF512()

View File

@@ -16,48 +16,13 @@
#ifdef __AES__ #ifdef __AES__
#include "groestl-version.h" #include "groestl-intr-aes.h"
#ifdef TASM
#ifdef VAES
#include "groestl-asm-aes.h"
#else
#ifdef VAVX
#include "groestl-asm-avx.h"
#else
#ifdef VVPERM
#include "groestl-asm-vperm.h"
#else
#error NO VERSION SPECIFIED (-DV[AES/AVX/VVPERM])
#endif
#endif
#endif
#else
#ifdef TINTR
#ifdef VAES
#include "groestl-intr-aes.h"
#else
#ifdef VAVX
#include "groestl-intr-avx.h"
#else
#ifdef VVPERM
#include "groestl-intr-vperm.h"
#else
#error NO VERSION SPECIFIED (-DV[AES/AVX/VVPERM])
#endif
#endif
#endif
#else
#error NO TYPE SPECIFIED (-DT[ASM/INTR])
#endif
#endif
HashReturn_gr init_groestl( hashState_groestl* ctx, int hashlen ) HashReturn_gr init_groestl( hashState_groestl* ctx, int hashlen )
{ {
int i; int i;
ctx->hashlen = hashlen; ctx->hashlen = hashlen;
SET_CONSTANTS();
if (ctx->chaining == NULL || ctx->buffer == NULL) if (ctx->chaining == NULL || ctx->buffer == NULL)
return FAIL_GR; return FAIL_GR;
@@ -70,8 +35,6 @@ HashReturn_gr init_groestl( hashState_groestl* ctx, int hashlen )
// The only non-zero in the IV is len. It can be hard coded. // The only non-zero in the IV is len. It can be hard coded.
ctx->chaining[ 6 ] = m128_const_64( 0x0200000000000000, 0 ); ctx->chaining[ 6 ] = m128_const_64( 0x0200000000000000, 0 );
// ((u64*)ctx->chaining)[COLS-1] = U64BIG((u64)LENGTH);
// INIT(ctx->chaining);
ctx->buf_ptr = 0; ctx->buf_ptr = 0;
ctx->rem_ptr = 0; ctx->rem_ptr = 0;
@@ -92,8 +55,6 @@ HashReturn_gr reinit_groestl( hashState_groestl* ctx )
ctx->buffer[i] = _mm_setzero_si128(); ctx->buffer[i] = _mm_setzero_si128();
} }
ctx->chaining[ 6 ] = m128_const_64( 0x0200000000000000, 0 ); ctx->chaining[ 6 ] = m128_const_64( 0x0200000000000000, 0 );
// ((u64*)ctx->chaining)[COLS-1] = U64BIG((u64)LENGTH);
// INIT(ctx->chaining);
ctx->buf_ptr = 0; ctx->buf_ptr = 0;
ctx->rem_ptr = 0; ctx->rem_ptr = 0;
@@ -109,7 +70,7 @@ HashReturn_gr reinit_groestl( hashState_groestl* ctx )
// 5. Midstate will work at reduced impact than full hash, if total hash // 5. Midstate will work at reduced impact than full hash, if total hash
// (midstate + tail) is less than 1 block. // (midstate + tail) is less than 1 block.
// This, unfortunately, is the case with all current users. // This, unfortunately, is the case with all current users.
// 6. the morefull blocks the bigger the gain // 6. the more full blocks the bigger the gain
// use only for midstate precalc // use only for midstate precalc
HashReturn_gr update_groestl( hashState_groestl* ctx, const void* input, HashReturn_gr update_groestl( hashState_groestl* ctx, const void* input,
@@ -143,12 +104,11 @@ HashReturn_gr update_groestl( hashState_groestl* ctx, const void* input,
// deprecated do not use // deprecated do not use
HashReturn_gr final_groestl( hashState_groestl* ctx, void* output ) HashReturn_gr final_groestl( hashState_groestl* ctx, void* output )
{ {
const int len = (int)ctx->databitlen / 128; // bits to __m128i const int len = (int)ctx->databitlen / 128; // bits to __m128i
const int blocks = ctx->blk_count + 1; // adjust for final block const uint64_t blocks = ctx->blk_count + 1; // adjust for final block
const int rem_ptr = ctx->rem_ptr; // end of data start of padding
const int rem_ptr = ctx->rem_ptr; // end of data start of padding const int hashlen_m128i = ctx->hashlen / 16; // bytes to __m128i
const int hashlen_m128i = ctx->hashlen / 16; // bytes to __m128i const int hash_offset = SIZE512 - hashlen_m128i; // where in buffer
const int hash_offset = SIZE512 - hashlen_m128i; // where in buffer
int i; int i;
// first pad byte = 0x80, last pad byte = block count // first pad byte = 0x80, last pad byte = block count
@@ -157,21 +117,18 @@ HashReturn_gr final_groestl( hashState_groestl* ctx, void* output )
if ( rem_ptr == len - 1 ) if ( rem_ptr == len - 1 )
{ {
// only 128 bits left in buffer, all padding at once // only 128 bits left in buffer, all padding at once
ctx->buffer[rem_ptr] = _mm_set_epi8( blocks,0,0,0, 0,0,0,0, ctx->buffer[rem_ptr] = _mm_set_epi64x( blocks << 56, 0x80 );
0,0,0,0, 0,0,0,0x80 );
} }
else else
{ {
// add first padding // add first padding
ctx->buffer[rem_ptr] = _mm_set_epi8( 0,0,0,0, 0,0,0,0, ctx->buffer[rem_ptr] = m128_const_64( 0, 0x80 );
0,0,0,0, 0,0,0,0x80 );
// add zero padding // add zero padding
for ( i = rem_ptr + 1; i < SIZE512 - 1; i++ ) for ( i = rem_ptr + 1; i < SIZE512 - 1; i++ )
ctx->buffer[i] = _mm_setzero_si128(); ctx->buffer[i] = _mm_setzero_si128();
// add length padding, second last byte is zero unless blocks > 255 // add length padding, second last byte is zero unless blocks > 255
ctx->buffer[i] = _mm_set_epi8( blocks, blocks>>8, 0,0, 0,0,0,0, ctx->buffer[i] = _mm_set_epi64x( blocks << 56, 0 );
0, 0 ,0,0, 0,0,0,0 );
} }
// digest final padding block and do output transform // digest final padding block and do output transform
@@ -189,21 +146,20 @@ int groestl512_full( hashState_groestl* ctx, void* output,
const void* input, uint64_t databitlen ) const void* input, uint64_t databitlen )
{ {
int i; int i;
ctx->hashlen = 64;
ctx->hashlen = 64;
SET_CONSTANTS();
for ( i = 0; i < SIZE512; i++ )
{
ctx->chaining[i] = _mm_setzero_si128();
ctx->buffer[i] = _mm_setzero_si128();
}
ctx->chaining[ 6 ] = m128_const_64( 0x0200000000000000, 0 );
ctx->buf_ptr = 0;
ctx->rem_ptr = 0;
for ( i = 0; i < SIZE512; i++ )
{
ctx->chaining[i] = _mm_setzero_si128();
ctx->buffer[i] = _mm_setzero_si128();
}
ctx->chaining[ 6 ] = m128_const_64( 0x0200000000000000, 0 );
ctx->buf_ptr = 0;
ctx->rem_ptr = 0;
// --- update ---
const int len = (int)databitlen / 128; const int len = (int)databitlen / 128;
const int hashlen_m128i = ctx->hashlen / 16; // bytes to __m128i const int hashlen_m128i = ctx->hashlen / 16; // bytes to __m128i
const int hash_offset = SIZE512 - hashlen_m128i; const int hash_offset = SIZE512 - hashlen_m128i;
@@ -211,8 +167,6 @@ int groestl512_full( hashState_groestl* ctx, void* output,
uint64_t blocks = len / SIZE512; uint64_t blocks = len / SIZE512;
__m128i* in = (__m128i*)input; __m128i* in = (__m128i*)input;
// --- update ---
// digest any full blocks, process directly from input // digest any full blocks, process directly from input
for ( i = 0; i < blocks; i++ ) for ( i = 0; i < blocks; i++ )
TF1024( ctx->chaining, &in[ i * SIZE512 ] ); TF1024( ctx->chaining, &in[ i * SIZE512 ] );
@@ -231,26 +185,22 @@ int groestl512_full( hashState_groestl* ctx, void* output,
if ( i == len -1 ) if ( i == len -1 )
{ {
// only 128 bits left in buffer, all padding at once // only 128 bits left in buffer, all padding at once
ctx->buffer[i] = _mm_set_epi8( blocks,0,0,0, 0,0,0,0, ctx->buffer[i] = _mm_set_epi64x( blocks << 56, 0x80 );
0,0,0,0, 0,0,0,0x80 );
} }
else else
{ {
// add first padding // add first padding
ctx->buffer[i] = _mm_set_epi8( 0,0,0,0, 0,0,0,0, ctx->buffer[i] = m128_const_64( 0, 0x80 );
0,0,0,0, 0,0,0,0x80 );
// add zero padding // add zero padding
for ( i += 1; i < SIZE512 - 1; i++ ) for ( i += 1; i < SIZE512 - 1; i++ )
ctx->buffer[i] = _mm_setzero_si128(); ctx->buffer[i] = _mm_setzero_si128();
// add length padding, second last byte is zero unless blocks > 255 // add length padding, second last byte is zero unless blocks > 255
ctx->buffer[i] = _mm_set_epi8( blocks, blocks>>8, 0,0, 0,0,0,0, ctx->buffer[i] = _mm_set_epi64x( blocks << 56, 0 );
0, 0 ,0,0, 0,0,0,0 );
} }
// digest final padding block and do output transform // digest final padding block and do output transform
TF1024( ctx->chaining, ctx->buffer ); TF1024( ctx->chaining, ctx->buffer );
OF1024( ctx->chaining ); OF1024( ctx->chaining );
// store hash result in output // store hash result in output
@@ -268,7 +218,7 @@ HashReturn_gr update_and_final_groestl( hashState_groestl* ctx, void* output,
const int hashlen_m128i = ctx->hashlen / 16; // bytes to __m128i const int hashlen_m128i = ctx->hashlen / 16; // bytes to __m128i
const int hash_offset = SIZE512 - hashlen_m128i; const int hash_offset = SIZE512 - hashlen_m128i;
int rem = ctx->rem_ptr; int rem = ctx->rem_ptr;
int blocks = len / SIZE512; uint64_t blocks = len / SIZE512;
__m128i* in = (__m128i*)input; __m128i* in = (__m128i*)input;
int i; int i;
@@ -292,26 +242,22 @@ HashReturn_gr update_and_final_groestl( hashState_groestl* ctx, void* output,
if ( i == len -1 ) if ( i == len -1 )
{ {
// only 128 bits left in buffer, all padding at once // only 128 bits left in buffer, all padding at once
ctx->buffer[i] = _mm_set_epi8( blocks,0,0,0, 0,0,0,0, ctx->buffer[i] = _mm_set_epi64x( blocks << 56, 0x80 );
0,0,0,0, 0,0,0,0x80 );
} }
else else
{ {
// add first padding // add first padding
ctx->buffer[i] = _mm_set_epi8( 0,0,0,0, 0,0,0,0, ctx->buffer[i] = m128_const_64( 0, 0x80 );
0,0,0,0, 0,0,0,0x80 );
// add zero padding // add zero padding
for ( i += 1; i < SIZE512 - 1; i++ ) for ( i += 1; i < SIZE512 - 1; i++ )
ctx->buffer[i] = _mm_setzero_si128(); ctx->buffer[i] = _mm_setzero_si128();
// add length padding, second last byte is zero unless blocks > 255 // add length padding, second last byte is zero unless blocks > 255
ctx->buffer[i] = _mm_set_epi8( blocks, blocks>>8, 0,0, 0,0,0,0, ctx->buffer[i] = _mm_set_epi64x( blocks << 56, 0 );
0, 0 ,0,0, 0,0,0,0 );
} }
// digest final padding block and do output transform // digest final padding block and do output transform
TF1024( ctx->chaining, ctx->buffer ); TF1024( ctx->chaining, ctx->buffer );
OF1024( ctx->chaining ); OF1024( ctx->chaining );
// store hash result in output // store hash result in output

View File

@@ -13,41 +13,7 @@
#ifdef __AES__ #ifdef __AES__
#include "groestl-version.h" #include "groestl256-intr-aes.h"
#ifdef TASM
#ifdef VAES
#include "groestl256-asm-aes.h"
#else
#ifdef VAVX
#include "groestl256-asm-avx.h"
#else
#ifdef VVPERM
#include "groestl256-asm-vperm.h"
#else
#error NO VERSION SPECIFIED (-DV[AES/AVX/VVPERM])
#endif
#endif
#endif
#else
#ifdef TINTR
#ifdef VAES
#include "groestl256-intr-aes.h"
#else
#ifdef VAVX
#include "groestl256-intr-avx.h"
#else
#ifdef VVPERM
#include "groestl256-intr-vperm.h"
#else
#error NO VERSION SPECIFIED (-DV[AES/AVX/VVPERM])
#endif
#endif
#endif
#else
#error NO TYPE SPECIFIED (-DT[ASM/INTR])
#endif
#endif
/* initialise context */ /* initialise context */
HashReturn_gr init_groestl256( hashState_groestl256* ctx, int hashlen ) HashReturn_gr init_groestl256( hashState_groestl256* ctx, int hashlen )
@@ -55,7 +21,6 @@ HashReturn_gr init_groestl256( hashState_groestl256* ctx, int hashlen )
int i; int i;
ctx->hashlen = hashlen; ctx->hashlen = hashlen;
SET_CONSTANTS();
if (ctx->chaining == NULL || ctx->buffer == NULL) if (ctx->chaining == NULL || ctx->buffer == NULL)
return FAIL_GR; return FAIL_GR;
@@ -249,6 +214,98 @@ HashReturn_gr update_and_final_groestl256( hashState_groestl256* ctx,
return SUCCESS_GR; return SUCCESS_GR;
} }
int groestl256_full( hashState_groestl256* ctx,
void* output, const void* input, DataLength_gr databitlen )
{
int i;
ctx->hashlen = 32;
for ( i = 0; i < SIZE256; i++ )
{
ctx->chaining[i] = _mm_setzero_si128();
ctx->buffer[i] = _mm_setzero_si128();
}
((u64*)ctx->chaining)[COLS-1] = U64BIG((u64)LENGTH);
INIT256( ctx->chaining );
ctx->buf_ptr = 0;
ctx->rem_ptr = 0;
const int len = (int)databitlen / 128;
const int hashlen_m128i = ctx->hashlen / 16; // bytes to __m128i
const int hash_offset = SIZE256 - hashlen_m128i;
int rem = ctx->rem_ptr;
int blocks = len / SIZE256;
__m128i* in = (__m128i*)input;
// --- update ---
// digest any full blocks, process directly from input
for ( i = 0; i < blocks; i++ )
TF512( ctx->chaining, &in[ i * SIZE256 ] );
ctx->buf_ptr = blocks * SIZE256;
// cryptonight has 200 byte input, an odd number of __m128i
// remainder is only 8 bytes, ie u64.
if ( databitlen % 128 !=0 )
{
// must be cryptonight, copy 64 bits of data
*(uint64_t*)(ctx->buffer) = *(uint64_t*)(&in[ ctx->buf_ptr ] );
i = -1; // signal for odd length
}
else
{
// Copy any remaining data to buffer for final transform
for ( i = 0; i < len % SIZE256; i++ )
ctx->buffer[ rem + i ] = in[ ctx->buf_ptr + i ];
i += rem; // use i as rem_ptr in final
}
//--- final ---
// adjust for final block
blocks++;
if ( i == len - 1 )
{
// all padding at once
ctx->buffer[i] = _mm_set_epi8( blocks,blocks>>8,0,0, 0,0,0,0,
0, 0,0,0, 0,0,0,0x80 );
}
else
{
if ( i == -1 )
{
// cryptonight odd length
((uint64_t*)ctx->buffer)[ 1 ] = 0x80ull;
// finish the block with zero and length padding as normal
i = 0;
}
else
{
// add first padding
ctx->buffer[i] = _mm_set_epi8( 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0x80 );
}
// add zero padding
for ( i += 1; i < SIZE256 - 1; i++ )
ctx->buffer[i] = _mm_setzero_si128();
// add length padding
// cheat since we know the block count is trivial, good if block < 256
ctx->buffer[i] = _mm_set_epi8( blocks,blocks>>8,0,0, 0,0,0,0,
0, 0,0,0, 0,0,0,0 );
}
// digest final padding block and do output transform
TF512( ctx->chaining, ctx->buffer );
OF512( ctx->chaining );
// store hash result in output
for ( i = 0; i < hashlen_m128i; i++ )
casti_m128i( output, i ) = ctx->chaining[ hash_offset + i ];
return SUCCESS_GR;
}
/* hash bit sequence */ /* hash bit sequence */
HashReturn_gr hash_groestl256(int hashbitlen, HashReturn_gr hash_groestl256(int hashbitlen,
const BitSequence_gr* data, const BitSequence_gr* data,

View File

@@ -115,4 +115,7 @@ HashReturn_gr hash_groestli256( int, const BitSequence_gr*, DataLength_gr,
HashReturn_gr update_and_final_groestl256( hashState_groestl256*, void*, HashReturn_gr update_and_final_groestl256( hashState_groestl256*, void*,
const void*, DataLength_gr ); const void*, DataLength_gr );
int groestl256_full( hashState_groestl256* ctx,
void* output, const void* input, DataLength_gr databitlen );
#endif /* __hash_h */ #endif /* __hash_h */

View File

@@ -53,7 +53,7 @@ int scanhash_groestl_4way( struct work *work, uint32_t max_nonce,
if ( fulltest( hash+(lane<<3), ptarget) && !opt_benchmark ) if ( fulltest( hash+(lane<<3), ptarget) && !opt_benchmark )
{ {
pdata[19] = n + lane; pdata[19] = n + lane;
submit_lane_solution( work, hash+(lane<<3), mythr, lane ); submit_solution( work, hash+(lane<<3), mythr );
} }
n += 4; n += 4;
} while ( ( n < last_nonce ) && !work_restart[thr_id].restart ); } while ( ( n < last_nonce ) && !work_restart[thr_id].restart );

View File

@@ -1,4 +1,7 @@
#include "groestl-gate.h" #include "groestl-gate.h"
#if !defined(GROESTL_8WAY) && !defined(GROESTLX16R_4WAY)
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
@@ -88,4 +91,4 @@ int scanhash_groestl( struct work *work, uint32_t max_nonce,
*hashes_done = pdata[19] - first_nonce + 1; *hashes_done = pdata[19] - first_nonce + 1;
return 0; return 0;
} }
#endif

View File

@@ -23,7 +23,6 @@ int groestl256_4way_init( groestl256_4way_context* ctx, uint64_t hashlen )
int i; int i;
ctx->hashlen = hashlen; ctx->hashlen = hashlen;
SET_CONSTANTS();
if (ctx->chaining == NULL || ctx->buffer == NULL) if (ctx->chaining == NULL || ctx->buffer == NULL)
return 1; return 1;
@@ -36,9 +35,6 @@ int groestl256_4way_init( groestl256_4way_context* ctx, uint64_t hashlen )
// The only non-zero in the IV is len. It can be hard coded. // The only non-zero in the IV is len. It can be hard coded.
ctx->chaining[ 3 ] = m512_const2_64( 0, 0x0100000000000000 ); ctx->chaining[ 3 ] = m512_const2_64( 0, 0x0100000000000000 );
// uint64_t len = U64BIG((uint64_t)LENGTH);
// ctx->chaining[ COLS/2 -1 ] = _mm512_set4_epi64( len, 0, len, 0 );
// INIT256_4way(ctx->chaining);
ctx->buf_ptr = 0; ctx->buf_ptr = 0;
ctx->rem_ptr = 0; ctx->rem_ptr = 0;
@@ -46,6 +42,77 @@ int groestl256_4way_init( groestl256_4way_context* ctx, uint64_t hashlen )
return 0; return 0;
} }
int groestl256_4way_full( groestl256_4way_context* ctx, void* output,
const void* input, uint64_t databitlen )
{
const int len = (int)databitlen / 128;
const int hashlen_m128i = 32 / 16; // bytes to __m128i
const int hash_offset = SIZE256 - hashlen_m128i;
int rem = ctx->rem_ptr;
int blocks = len / SIZE256;
__m512i* in = (__m512i*)input;
int i;
if (ctx->chaining == NULL || ctx->buffer == NULL)
return 1;
for ( i = 0; i < SIZE256; i++ )
{
ctx->chaining[i] = m512_zero;
ctx->buffer[i] = m512_zero;
}
// The only non-zero in the IV is len. It can be hard coded.
ctx->chaining[ 3 ] = m512_const2_64( 0, 0x0100000000000000 );
ctx->buf_ptr = 0;
ctx->rem_ptr = 0;
// --- update ---
// digest any full blocks, process directly from input
for ( i = 0; i < blocks; i++ )
TF512_4way( ctx->chaining, &in[ i * SIZE256 ] );
ctx->buf_ptr = blocks * SIZE256;
// copy any remaining data to buffer, it may already contain data
// from a previous update for a midstate precalc
for ( i = 0; i < len % SIZE256; i++ )
ctx->buffer[ rem + i ] = in[ ctx->buf_ptr + i ];
i += rem; // use i as rem_ptr in final
//--- final ---
blocks++; // adjust for final block
if ( i == SIZE256 - 1 )
{
// only 1 vector left in buffer, all padding at once
ctx->buffer[i] = m512_const2_64( (uint64_t)blocks << 56, 0x80 );
}
else
{
// add first padding
ctx->buffer[i] = m512_const4_64( 0, 0x80, 0, 0x80 );
// add zero padding
for ( i += 1; i < SIZE256 - 1; i++ )
ctx->buffer[i] = m512_zero;
// add length padding, second last byte is zero unless blocks > 255
ctx->buffer[i] = m512_const2_64( (uint64_t)blocks << 56, 0 );
}
// digest final padding block and do output transform
TF512_4way( ctx->chaining, ctx->buffer );
OF512_4way( ctx->chaining );
// store hash result in output
for ( i = 0; i < hashlen_m128i; i++ )
casti_m512i( output, i ) = ctx->chaining[ hash_offset + i ];
return 0;
}
int groestl256_4way_update_close( groestl256_4way_context* ctx, void* output, int groestl256_4way_update_close( groestl256_4way_context* ctx, void* output,
const void* input, uint64_t databitlen ) const void* input, uint64_t databitlen )
{ {
@@ -75,11 +142,11 @@ int groestl256_4way_update_close( groestl256_4way_context* ctx, void* output,
blocks++; // adjust for final block blocks++; // adjust for final block
if ( i == SIZE256 - 1 ) if ( i == SIZE256 - 1 )
{ {
// only 1 vector left in buffer, all padding at once // only 1 vector left in buffer, all padding at once
ctx->buffer[i] = m512_const1_128( _mm_set_epi8( ctx->buffer[i] = m512_const1_128( _mm_set_epi8(
blocks, blocks>>8,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0x80 ) ); blocks, blocks>>8,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0x80 ) );
} }
else else
{ {
// add first padding // add first padding

View File

@@ -71,5 +71,8 @@ int groestl256_4way_init( groestl256_4way_context*, uint64_t );
int groestl256_4way_update_close( groestl256_4way_context*, void*, int groestl256_4way_update_close( groestl256_4way_context*, void*,
const void*, uint64_t ); const void*, uint64_t );
int groestl256_4way_full( groestl256_4way_context*, void*,
const void*, uint64_t );
#endif #endif
#endif #endif

View File

@@ -14,17 +14,78 @@
#include "groestl256-hash-4way.h" #include "groestl256-hash-4way.h"
#if defined(__VAES__) #if defined(__VAES__)
static const __m128i round_const_l0[] __attribute__ ((aligned (64))) =
{
{ 0x7060504030201000, 0xffffffffffffffff },
{ 0x7161514131211101, 0xffffffffffffffff },
{ 0x7262524232221202, 0xffffffffffffffff },
{ 0x7363534333231303, 0xffffffffffffffff },
{ 0x7464544434241404, 0xffffffffffffffff },
{ 0x7565554535251505, 0xffffffffffffffff },
{ 0x7666564636261606, 0xffffffffffffffff },
{ 0x7767574737271707, 0xffffffffffffffff },
{ 0x7868584838281808, 0xffffffffffffffff },
{ 0x7969594939291909, 0xffffffffffffffff }
};
/* global constants */ static const __m128i round_const_l7[] __attribute__ ((aligned (64))) =
__m512i ROUND_CONST_Lx; {
__m512i ROUND_CONST_L0[ROUNDS512]; { 0x0000000000000000, 0x8f9fafbfcfdfefff },
__m512i ROUND_CONST_L7[ROUNDS512]; { 0x0000000000000000, 0x8e9eaebecedeeefe },
//__m512i ROUND_CONST_P[ROUNDS1024]; { 0x0000000000000000, 0x8d9dadbdcdddedfd },
//__m512i ROUND_CONST_Q[ROUNDS1024]; { 0x0000000000000000, 0x8c9cacbcccdcecfc },
__m512i TRANSP_MASK; { 0x0000000000000000, 0x8b9babbbcbdbebfb },
__m512i SUBSH_MASK[8]; { 0x0000000000000000, 0x8a9aaabacadaeafa },
__m512i ALL_1B; { 0x0000000000000000, 0x8999a9b9c9d9e9f9 },
__m512i ALL_FF; { 0x0000000000000000, 0x8898a8b8c8d8e8f8 },
{ 0x0000000000000000, 0x8797a7b7c7d7e7f7 },
{ 0x0000000000000000, 0x8696a6b6c6d6e6f6 }
};
static const __m512i TRANSP_MASK = { 0x0d0509010c040800, 0x0f070b030e060a02,
0x1d1519111c141810, 0x1f171b131e161a12,
0x2d2529212c242820, 0x2f272b232e262a22,
0x3d3539313c343830, 0x3f373b333e363a32 };
static const __m512i SUBSH_MASK0 = { 0x0c0f0104070b0e00, 0x03060a0d08020509,
0x1c1f1114171b1e10, 0x13161a1d18121519,
0x2c2f2124272b2e20, 0x23262a2d28222529,
0x3c3f3134373b3e30, 0x33363a3d38323539 };
static const __m512i SUBSH_MASK1 = { 0x0e090205000d0801, 0x04070c0f0a03060b,
0x1e191215101d1801, 0x14171c1f1a13161b,
0x2e292225202d2821, 0x24272c2f2a23262b,
0x3e393235303d3831, 0x34373c3f3a33363b };
static const __m512i SUBSH_MASK2 = { 0x080b0306010f0a02, 0x05000e090c04070d,
0x181b1316111f1a12, 0x15101e191c14171d,
0x282b2326212f2a22, 0x25202e292c24272d,
0x383b3336313f3a32, 0x35303e393c34373d };
static const __m512i SUBSH_MASK3 = { 0x0a0d040702090c03, 0x0601080b0e05000f,
0x1a1d141712191c13, 0x1611181b1e15101f,
0x2a2d242722292c23, 0x2621282b2e25202f,
0x3a3d343732393c33, 0x3631383b3e35303f };
static const __m512i SUBSH_MASK4 = { 0x0b0e0500030a0d04, 0x0702090c0f060108,
0x1b1e1510131a1d14, 0x1712191c1f161118,
0x2b2e2520232a2d24, 0x2722292c2f262128,
0x3b3e3530333a3d34, 0x3732393c3f363138 };
static const __m512i SUBSH_MASK5 = { 0x0d080601040c0f05, 0x00030b0e0907020a,
0x1d181611141c1f15, 0x10131b1e1917121a,
0x2d282621242c2f25, 0x20232b2e2927222a,
0x3d383631343c3f35, 0x30333b3e3937323a };
static const __m512i SUBSH_MASK6 = { 0x0f0a0702050e0906, 0x01040d080b00030c,
0x1f1a1712151e1916, 0x11141d181b10131c,
0x2f2a2722252e2926, 0x21242d282b20232c,
0x3f3a3732353e3936, 0x31343d383b30333c };
static const __m512i SUBSH_MASK7 = { 0x090c000306080b07, 0x02050f0a0d01040e,
0x191c101316181b17, 0x12151f1a1d11141e,
0x292c202326282b27, 0x22252f2a2d21242e,
0x393c303336383b37, 0x32353f3a3d31343e };
#define tos(a) #a #define tos(a) #a
#define tostr(a) tos(a) #define tostr(a) tos(a)
@@ -40,8 +101,6 @@ __m512i ALL_FF;
i = _mm512_xor_si512(i, j);\ i = _mm512_xor_si512(i, j);\
} }
/**/
/* Yet another implementation of MixBytes. /* Yet another implementation of MixBytes.
This time we use the formulae (3) from the paper "Byte Slicing Groestl". This time we use the formulae (3) from the paper "Byte Slicing Groestl".
Input: a0, ..., a7 Input: a0, ..., a7
@@ -155,95 +214,36 @@ __m512i ALL_FF;
b1 = _mm512_xor_si512(b1, a4);\ b1 = _mm512_xor_si512(b1, a4);\
}/*MixBytes*/ }/*MixBytes*/
// calculate the round constants seperately and load at startup
#define SET_CONSTANTS(){\
ALL_1B = _mm512_set1_epi32( 0x1b1b1b1b );\
TRANSP_MASK = _mm512_set_epi32( \
0x3f373b33, 0x3e363a32, 0x3d353931, 0x3c343830, \
0x2f272b23, 0x2e262a22, 0x2d252921, 0x2c242820, \
0x1f171b13, 0x1e161a12, 0x1d151911, 0x1c141810, \
0x0f070b03, 0x0e060a02, 0x0d050901, 0x0c040800 ); \
SUBSH_MASK[0] = _mm512_set_epi32( \
0x33363a3d, 0x38323539, 0x3c3f3134, 0x373b3e30, \
0x23262a2d, 0x28222529, 0x2c2f2124, 0x272b2e20, \
0x13161a1d, 0x18121519, 0x1c1f1114, 0x171b1e10, \
0x03060a0d, 0x08020509, 0x0c0f0104, 0x070b0e00 ); \
SUBSH_MASK[1] = _mm512_set_epi32( \
0x34373c3f, 0x3a33363b, 0x3e393235, 0x303d3831, \
0x24272c2f, 0x2a23262b, 0x2e292225, 0x202d2821, \
0x14171c1f, 0x1a13161b, 0x1e191215, 0x101d1801, \
0x04070c0f, 0x0a03060b, 0x0e090205, 0x000d0801 );\
SUBSH_MASK[2] = _mm512_set_epi32( \
0x35303e39, 0x3c34373d, 0x383b3336, 0x313f3a32, \
0x25202e29, 0x2c24272d, 0x282b2326, 0x212f2a22, \
0x15101e19, 0x1c14171d, 0x181b1316, 0x111f1a12, \
0x05000e09, 0x0c04070d, 0x080b0306, 0x010f0a02 );\
SUBSH_MASK[3] = _mm512_set_epi32( \
0x3631383b, 0x3e35303f, 0x3a3d3437, 0x32393c33, \
0x2621282b, 0x2e25202f, 0x2a2d2427, 0x22292c23, \
0x1611181b, 0x1e15101f, 0x1a1d1417, 0x12191c13, \
0x0601080b, 0x0e05000f, 0x0a0d0407, 0x02090c03 );\
SUBSH_MASK[4] = _mm512_set_epi32( \
0x3732393c, 0x3f363138, 0x3b3e3530, 0x333a3d34, \
0x2722292c, 0x2f262128, 0x2b2e2520, 0x232a2d24, \
0x1712191c, 0x1f161118, 0x1b1e1510, 0x131a1d14, \
0x0702090c, 0x0f060108, 0x0b0e0500, 0x030a0d04 );\
SUBSH_MASK[5] = _mm512_set_epi32( \
0x30333b3e, 0x3937323a, 0x3d383631, 0x343c3f35, \
0x20232b2e, 0x2927222a, 0x2d282621, 0x242c2f25, \
0x10131b1e, 0x1917121a, 0x1d181611, 0x141c1f15, \
0x00030b0e, 0x0907020a, 0x0d080601, 0x040c0f05 );\
SUBSH_MASK[6] = _mm512_set_epi32( \
0x31343d38, 0x3b30333c, 0x3f3a3732, 0x353e3936, \
0x21242d28, 0x2b20232c, 0x2f2a2722, 0x252e2926, \
0x11141d18, 0x1b10131c, 0x1f1a1712, 0x151e1916, \
0x01040d08, 0x0b00030c, 0x0f0a0702, 0x050e0906 );\
SUBSH_MASK[7] = _mm512_set_epi32( \
0x32353f3a, 0x3d31343e, 0x393c3033, 0x36383b37, \
0x22252f2a, 0x2d21242e, 0x292c2023, 0x26282b27, \
0x12151f1a, 0x1d11141e, 0x191c1013, 0x16181b17, \
0x02050f0a, 0x0d01040e, 0x090c0003, 0x06080b07 );\
for ( i = 0; i < ROUNDS512; i++ ) \
{\
ROUND_CONST_L0[i] = _mm512_set4_epi32( 0xffffffff, 0xffffffff, \
0x70605040 ^ ( i * 0x01010101 ), 0x30201000 ^ ( i * 0x01010101 ) ); \
ROUND_CONST_L7[i] = _mm512_set4_epi32( 0x8f9fafbf ^ ( i * 0x01010101 ), \
0xcfdfefff ^ ( i * 0x01010101 ), 0x00000000, 0x00000000 ); \
}\
ROUND_CONST_Lx = _mm512_set4_epi32( 0xffffffff, 0xffffffff, \
0x00000000, 0x00000000 ); \
}while(0);\
#define ROUND(i, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\ #define ROUND(i, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\
/* AddRoundConstant */\ /* AddRoundConstant */\
b1 = ROUND_CONST_Lx;\ b1 = m512_const2_64( 0xffffffffffffffff, 0 ); \
a0 = _mm512_xor_si512( a0, (ROUND_CONST_L0[i]) );\ a0 = _mm512_xor_si512( a0, m512_const1_128( round_const_l0[i] ) );\
a1 = _mm512_xor_si512( a1, b1 );\ a1 = _mm512_xor_si512( a1, b1 );\
a2 = _mm512_xor_si512( a2, b1 );\ a2 = _mm512_xor_si512( a2, b1 );\
a3 = _mm512_xor_si512( a3, b1 );\ a3 = _mm512_xor_si512( a3, b1 );\
a4 = _mm512_xor_si512( a4, b1 );\ a4 = _mm512_xor_si512( a4, b1 );\
a5 = _mm512_xor_si512( a5, b1 );\ a5 = _mm512_xor_si512( a5, b1 );\
a6 = _mm512_xor_si512( a6, b1 );\ a6 = _mm512_xor_si512( a6, b1 );\
a7 = _mm512_xor_si512( a7, (ROUND_CONST_L7[i]) );\ a7 = _mm512_xor_si512( a7, m512_const1_128( round_const_l7[i] ) );\
\ \
/* ShiftBytes + SubBytes (interleaved) */\ /* ShiftBytes + SubBytes (interleaved) */\
b0 = _mm512_xor_si512( b0, b0 );\ b0 = _mm512_xor_si512( b0, b0 );\
a0 = _mm512_shuffle_epi8( a0, (SUBSH_MASK[0]) );\ a0 = _mm512_shuffle_epi8( a0, SUBSH_MASK0 );\
a0 = _mm512_aesenclast_epi128(a0, b0 );\ a0 = _mm512_aesenclast_epi128(a0, b0 );\
a1 = _mm512_shuffle_epi8( a1, (SUBSH_MASK[1]) );\ a1 = _mm512_shuffle_epi8( a1, SUBSH_MASK1 );\
a1 = _mm512_aesenclast_epi128(a1, b0 );\ a1 = _mm512_aesenclast_epi128(a1, b0 );\
a2 = _mm512_shuffle_epi8( a2, (SUBSH_MASK[2]) );\ a2 = _mm512_shuffle_epi8( a2, SUBSH_MASK2 );\
a2 = _mm512_aesenclast_epi128(a2, b0 );\ a2 = _mm512_aesenclast_epi128(a2, b0 );\
a3 = _mm512_shuffle_epi8( a3, (SUBSH_MASK[3]) );\ a3 = _mm512_shuffle_epi8( a3, SUBSH_MASK3 );\
a3 = _mm512_aesenclast_epi128(a3, b0 );\ a3 = _mm512_aesenclast_epi128(a3, b0 );\
a4 = _mm512_shuffle_epi8( a4, (SUBSH_MASK[4]) );\ a4 = _mm512_shuffle_epi8( a4, SUBSH_MASK4 );\
a4 = _mm512_aesenclast_epi128(a4, b0 );\ a4 = _mm512_aesenclast_epi128(a4, b0 );\
a5 = _mm512_shuffle_epi8( a5, (SUBSH_MASK[5]) );\ a5 = _mm512_shuffle_epi8( a5, SUBSH_MASK5 );\
a5 = _mm512_aesenclast_epi128(a5, b0 );\ a5 = _mm512_aesenclast_epi128(a5, b0 );\
a6 = _mm512_shuffle_epi8( a6, (SUBSH_MASK[6]) );\ a6 = _mm512_shuffle_epi8( a6, SUBSH_MASK6 );\
a6 = _mm512_aesenclast_epi128(a6, b0 );\ a6 = _mm512_aesenclast_epi128(a6, b0 );\
a7 = _mm512_shuffle_epi8( a7, (SUBSH_MASK[7]) );\ a7 = _mm512_shuffle_epi8( a7, SUBSH_MASK7 );\
a7 = _mm512_aesenclast_epi128( a7, b0 );\ a7 = _mm512_aesenclast_epi128( a7, b0 );\
\ \
/* MixBytes */\ /* MixBytes */\
@@ -390,29 +390,6 @@ __m512i ALL_FF;
}/**/ }/**/
void INIT256_4way( __m512i* chaining )
{
static __m512i xmm0, xmm2, xmm6, xmm7;
static __m512i xmm12, xmm13, xmm14, xmm15;
/* load IV into registers xmm12 - xmm15 */
xmm12 = chaining[0];
xmm13 = chaining[1];
xmm14 = chaining[2];
xmm15 = chaining[3];
/* transform chaining value from column ordering into row ordering */
/* we put two rows (64 bit) of the IV into one 128-bit XMM register */
Matrix_Transpose_A(xmm12, xmm13, xmm14, xmm15, xmm2, xmm6, xmm7, xmm0);
/* store transposed IV */
chaining[0] = xmm12;
chaining[1] = xmm2;
chaining[2] = xmm6;
chaining[3] = xmm7;
}
void TF512_4way( __m512i* chaining, __m512i* message ) void TF512_4way( __m512i* chaining, __m512i* message )
{ {
static __m512i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7; static __m512i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;

View File

@@ -19,10 +19,6 @@
int groestl512_4way_init( groestl512_4way_context* ctx, uint64_t hashlen ) int groestl512_4way_init( groestl512_4way_context* ctx, uint64_t hashlen )
{ {
int i;
SET_CONSTANTS();
if (ctx->chaining == NULL || ctx->buffer == NULL) if (ctx->chaining == NULL || ctx->buffer == NULL)
return 1; return 1;
@@ -99,7 +95,6 @@ int groestl512_4way_full( groestl512_4way_context* ctx, void* output,
// --- init --- // --- init ---
SET_CONSTANTS();
memset_zero_512( ctx->chaining, SIZE512 ); memset_zero_512( ctx->chaining, SIZE512 );
memset_zero_512( ctx->buffer, SIZE512 ); memset_zero_512( ctx->buffer, SIZE512 );
ctx->chaining[ 6 ] = m512_const2_64( 0x0200000000000000, 0 ); ctx->chaining[ 6 ] = m512_const2_64( 0x0200000000000000, 0 );

View File

@@ -15,16 +15,86 @@
#if defined(__VAES__) #if defined(__VAES__)
/* global constants */ static const __m128i round_const_p[] __attribute__ ((aligned (64))) =
__m512i ROUND_CONST_Lx; {
//__m128i ROUND_CONST_L0[ROUNDS512]; { 0x7060504030201000, 0xf0e0d0c0b0a09080 },
//__m128i ROUND_CONST_L7[ROUNDS512]; { 0x7161514131211101, 0xf1e1d1c1b1a19181 },
__m512i ROUND_CONST_P[ROUNDS1024]; { 0x7262524232221202, 0xf2e2d2c2b2a29282 },
__m512i ROUND_CONST_Q[ROUNDS1024]; { 0x7363534333231303, 0xf3e3d3c3b3a39383 },
__m512i TRANSP_MASK; { 0x7464544434241404, 0xf4e4d4c4b4a49484 },
__m512i SUBSH_MASK[8]; { 0x7565554535251505, 0xf5e5d5c5b5a59585 },
__m512i ALL_1B; { 0x7666564636261606, 0xf6e6d6c6b6a69686 },
__m512i ALL_FF; { 0x7767574737271707, 0xf7e7d7c7b7a79787 },
{ 0x7868584838281808, 0xf8e8d8c8b8a89888 },
{ 0x7969594939291909, 0xf9e9d9c9b9a99989 },
{ 0x7a6a5a4a3a2a1a0a, 0xfaeadacabaaa9a8a },
{ 0x7b6b5b4b3b2b1b0b, 0xfbebdbcbbbab9b8b },
{ 0x7c6c5c4c3c2c1c0c, 0xfcecdcccbcac9c8c },
{ 0x7d6d5d4d3d2d1d0d, 0xfdedddcdbdad9d8d }
};
static const __m128i round_const_q[] __attribute__ ((aligned (64))) =
{
{ 0x8f9fafbfcfdfefff, 0x0f1f2f3f4f5f6f7f },
{ 0x8e9eaebecedeeefe, 0x0e1e2e3e4e5e6e7e },
{ 0x8d9dadbdcdddedfd, 0x0d1d2d3d4d5d6d7d },
{ 0x8c9cacbcccdcecfc, 0x0c1c2c3c4c5c6c7c },
{ 0x8b9babbbcbdbebfb, 0x0b1b2b3b4b5b6b7b },
{ 0x8a9aaabacadaeafa, 0x0a1a2a3a4a5a6a7a },
{ 0x8999a9b9c9d9e9f9, 0x0919293949596979 },
{ 0x8898a8b8c8d8e8f8, 0x0818283848586878 },
{ 0x8797a7b7c7d7e7f7, 0x0717273747576777 },
{ 0x8696a6b6c6d6e6f6, 0x0616263646566676 },
{ 0x8595a5b5c5d5e5f5, 0x0515253545556575 },
{ 0x8494a4b4c4d4e4f4, 0x0414243444546474 },
{ 0x8393a3b3c3d3e3f3, 0x0313233343536373 },
{ 0x8292a2b2c2d2e2f2, 0x0212223242526272 }
};
static const __m512i TRANSP_MASK = { 0x0d0509010c040800, 0x0f070b030e060a02,
0x1d1519111c141810, 0x1f171b131e161a12,
0x2d2529212c242820, 0x2f272b232e262a22,
0x3d3539313c343830, 0x3f373b333e363a32 };
static const __m512i SUBSH_MASK0 = { 0x0b0e0104070a0d00, 0x0306090c0f020508,
0x1b1e1114171a1d10, 0x1316191c1f121518,
0x2b2e2124272a2d20, 0x2326292c2f222528,
0x3b3e3134373a3d30, 0x3336393c3f323538 };
static const __m512i SUBSH_MASK1 = { 0x0c0f0205080b0e01, 0x04070a0d00030609,
0x1c1f1215181b1e11, 0x14171a1d10131619,
0x2c2f2225282b2e21, 0x24272a2d20232629,
0x3c3f3235383b3e31, 0x34373a3d30333639 };
static const __m512i SUBSH_MASK2 = { 0x0d000306090c0f02, 0x05080b0e0104070a,
0x1d101316191c1f12, 0x15181b1e1114171a,
0x2d202326292c2f22, 0x25282b2e2124272a,
0x3d303336393c3f32, 0x35383b3e3134373a };
static const __m512i SUBSH_MASK3 = { 0x0e0104070a0d0003, 0x06090c0f0205080b,
0x1e1114171a1d1013, 0x16191c1f1215181b,
0x2e2124272a2d2023, 0x26292c2f2225282b,
0x3e3134373a3d3033, 0x36393c3f3235383b };
static const __m512i SUBSH_MASK4 = { 0x0f0205080b0e0104, 0x070a0d000306090c,
0x1f1215181b1e1114, 0x171a1d101316191c,
0x2f2225282b2e2124, 0x272a2d202326292c,
0x3f3235383b3e3134, 0x373a3d303336393c };
static const __m512i SUBSH_MASK5 = { 0x000306090c0f0205, 0x080b0e0104070a0d,
0x101316191c1f1215, 0x181b1e1114171a1d,
0x202326292c2f2225, 0x282b2e2124272a2d,
0x303336393c3f3235, 0x383b3e3134373a3d };
static const __m512i SUBSH_MASK6 = { 0x0104070a0d000306, 0x090c0f0205080b0e,
0x1114171a1d101316, 0x191c1f1215181b1e,
0x2124272a2d202326, 0x292c2f2225282b2e,
0x3134373a3d303336, 0x393c3f3235383b3e };
static const __m512i SUBSH_MASK7 = { 0x06090c0f0205080b, 0x0e0104070a0d0003,
0x16191c1f1215181b, 0x1e1114171a1d1013,
0x26292c2f2225282b, 0x2e2124272a2d2023,
0x36393c3f3235383b, 0x3e3134373a3d3033 };
#define tos(a) #a #define tos(a) #a
#define tostr(a) tos(a) #define tostr(a) tos(a)
@@ -155,69 +225,6 @@ __m512i ALL_FF;
b1 = _mm512_xor_si512(b1, a4);\ b1 = _mm512_xor_si512(b1, a4);\
}/*MixBytes*/ }/*MixBytes*/
// calculate the round constants seperately and load at startup
#define SET_CONSTANTS(){\
ALL_FF = _mm512_set1_epi32( 0xffffffff );\
ALL_1B = _mm512_set1_epi32( 0x1b1b1b1b );\
TRANSP_MASK = _mm512_set_epi32( \
0x3f373b33, 0x3e363a32, 0x3d353931, 0x3c343830, \
0x2f272b23, 0x2e262a22, 0x2d252921, 0x2c242820, \
0x1f171b13, 0x1e161a12, 0x1d151911, 0x1c141810, \
0x0f070b03, 0x0e060a02, 0x0d050901, 0x0c040800 ); \
SUBSH_MASK[0] = _mm512_set_epi32( \
0x3336393c, 0x3f323538, 0x3b3e3134, 0x373a3d30, \
0x2326292c, 0x2f222528, 0x2b2e2124, 0x272a2d20, \
0x1316191c, 0x1f121518, 0x1b1e1114, 0x171a1d10, \
0x0306090c, 0x0f020508, 0x0b0e0104, 0x070a0d00 ); \
SUBSH_MASK[1] = _mm512_set_epi32( \
0x34373a3d, 0x30333639, 0x3c3f3235, 0x383b3e31, \
0x24272a2d, 0x20232629, 0x2c2f2225, 0x282b2e21, \
0x14171a1d, 0x10131619, 0x1c1f1215, 0x181b1e11, \
0x04070a0d, 0x00030609, 0x0c0f0205, 0x080b0e01 ); \
SUBSH_MASK[2] = _mm512_set_epi32( \
0x35383b3e, 0x3134373a, 0x3d303336, 0x393c3f32, \
0x25282b2e, 0x2124272a, 0x2d202326, 0x292c2f22, \
0x15181b1e, 0x1114171a, 0x1d101316, 0x191c1f12, \
0x05080b0e, 0x0104070a, 0x0d000306, 0x090c0f02 ); \
SUBSH_MASK[3] = _mm512_set_epi32( \
0x36393c3f, 0x3235383b, 0x3e313437, 0x3a3d3033, \
0x26292c2f, 0x2225282b, 0x2e212427, 0x2a2d2023, \
0x16191c1f, 0x1215181b, 0x1e111417, 0x1a1d1013, \
0x06090c0f, 0x0205080b, 0x0e010407, 0x0a0d0003 ); \
SUBSH_MASK[4] = _mm512_set_epi32( \
0x373a3d30, 0x3336393c, 0x3f323538, 0x3b3e3134, \
0x272a2d20, 0x2326292c, 0x2f222528, 0x2b2e2124, \
0x171a1d10, 0x1316191c, 0x1f121518, 0x1b1e1114, \
0x070a0d00, 0x0306090c, 0x0f020508, 0x0b0e0104 ); \
SUBSH_MASK[5] = _mm512_set_epi32( \
0x383b3e31, 0x34373a3d, 0x30333639, 0x3c3f3235, \
0x282b2e21, 0x24272a2d, 0x20232629, 0x2c2f2225, \
0x181b1e11, 0x14171a1d, 0x10131619, 0x1c1f1215, \
0x080b0e01, 0x04070a0d, 0x00030609, 0x0c0f0205 ); \
SUBSH_MASK[6] = _mm512_set_epi32( \
0x393c3f32, 0x35383b3e, 0x3134373a, 0x3d303336, \
0x292c2f22, 0x25282b2e, 0x2124272a, 0x2d202326, \
0x191c1f12, 0x15181b1e, 0x1114171a, 0x1d101316, \
0x090c0f02, 0x05080b0e, 0x0104070a, 0x0d000306 ); \
SUBSH_MASK[7] = _mm512_set_epi32( \
0x3e313437, 0x3a3d3033, 0x36393c3f, 0x3235383b, \
0x2e212427, 0x2a2d2023, 0x26292c2f, 0x2225282b, \
0x1e111417, 0x1a1d1013, 0x16191c1f, 0x1215181b, \
0x0e010407, 0x0a0d0003, 0x06090c0f, 0x0205080b ); \
for( i = 0; i < ROUNDS1024; i++ ) \
{ \
ROUND_CONST_P[i] = _mm512_set4_epi32( 0xf0e0d0c0 ^ (i * 0x01010101), \
0xb0a09080 ^ (i * 0x01010101), \
0x70605040 ^ (i * 0x01010101), \
0x30201000 ^ (i * 0x01010101) ); \
ROUND_CONST_Q[i] = _mm512_set4_epi32( 0x0f1f2f3f ^ (i * 0x01010101), \
0x4f5f6f7f ^ (i * 0x01010101), \
0x8f9fafbf ^ (i * 0x01010101), \
0xcfdfefff ^ (i * 0x01010101));\
} \
}while(0);\
/* one round /* one round
* a0-a7 = input rows * a0-a7 = input rows
* b0-b7 = output rows * b0-b7 = output rows
@@ -242,30 +249,32 @@ __m512i ALL_FF;
for ( round_counter = 0; round_counter < 14; round_counter += 2 ) \ for ( round_counter = 0; round_counter < 14; round_counter += 2 ) \
{ \ { \
/* AddRoundConstant P1024 */\ /* AddRoundConstant P1024 */\
xmm8 = _mm512_xor_si512( xmm8, ( ROUND_CONST_P[ round_counter ] ) );\ xmm8 = _mm512_xor_si512( xmm8, m512_const1_128( \
casti_m128i( round_const_p, round_counter ) ) ); \
/* ShiftBytes P1024 + pre-AESENCLAST */\ /* ShiftBytes P1024 + pre-AESENCLAST */\
xmm8 = _mm512_shuffle_epi8( xmm8, ( SUBSH_MASK[0] ) );\ xmm8 = _mm512_shuffle_epi8( xmm8, SUBSH_MASK0 ); \
xmm9 = _mm512_shuffle_epi8( xmm9, ( SUBSH_MASK[1] ) );\ xmm9 = _mm512_shuffle_epi8( xmm9, SUBSH_MASK1 );\
xmm10 = _mm512_shuffle_epi8( xmm10, ( SUBSH_MASK[2] ) );\ xmm10 = _mm512_shuffle_epi8( xmm10, SUBSH_MASK2 );\
xmm11 = _mm512_shuffle_epi8( xmm11, ( SUBSH_MASK[3] ) );\ xmm11 = _mm512_shuffle_epi8( xmm11, SUBSH_MASK3 );\
xmm12 = _mm512_shuffle_epi8( xmm12, ( SUBSH_MASK[4] ) );\ xmm12 = _mm512_shuffle_epi8( xmm12, SUBSH_MASK4 );\
xmm13 = _mm512_shuffle_epi8( xmm13, ( SUBSH_MASK[5] ) );\ xmm13 = _mm512_shuffle_epi8( xmm13, SUBSH_MASK5 );\
xmm14 = _mm512_shuffle_epi8( xmm14, ( SUBSH_MASK[6] ) );\ xmm14 = _mm512_shuffle_epi8( xmm14, SUBSH_MASK6 );\
xmm15 = _mm512_shuffle_epi8( xmm15, ( SUBSH_MASK[7] ) );\ xmm15 = _mm512_shuffle_epi8( xmm15, SUBSH_MASK7 );\
/* SubBytes + MixBytes */\ /* SubBytes + MixBytes */\
SUBMIX(xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\ SUBMIX(xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\
\ \
/* AddRoundConstant P1024 */\ /* AddRoundConstant P1024 */\
xmm0 = _mm512_xor_si512( xmm0, ( ROUND_CONST_P[ round_counter+1 ] ) );\ xmm0 = _mm512_xor_si512( xmm0, m512_const1_128( \
casti_m128i( round_const_p, round_counter+1 ) ) ); \
/* ShiftBytes P1024 + pre-AESENCLAST */\ /* ShiftBytes P1024 + pre-AESENCLAST */\
xmm0 = _mm512_shuffle_epi8( xmm0, ( SUBSH_MASK[0] ) );\ xmm0 = _mm512_shuffle_epi8( xmm0, SUBSH_MASK0 );\
xmm1 = _mm512_shuffle_epi8( xmm1, ( SUBSH_MASK[1] ) );\ xmm1 = _mm512_shuffle_epi8( xmm1, SUBSH_MASK1 );\
xmm2 = _mm512_shuffle_epi8( xmm2, ( SUBSH_MASK[2] ) );\ xmm2 = _mm512_shuffle_epi8( xmm2, SUBSH_MASK2 );\
xmm3 = _mm512_shuffle_epi8( xmm3, ( SUBSH_MASK[3] ) );\ xmm3 = _mm512_shuffle_epi8( xmm3, SUBSH_MASK3 );\
xmm4 = _mm512_shuffle_epi8( xmm4, ( SUBSH_MASK[4] ) );\ xmm4 = _mm512_shuffle_epi8( xmm4, SUBSH_MASK4 );\
xmm5 = _mm512_shuffle_epi8( xmm5, ( SUBSH_MASK[5] ) );\ xmm5 = _mm512_shuffle_epi8( xmm5, SUBSH_MASK5 );\
xmm6 = _mm512_shuffle_epi8( xmm6, ( SUBSH_MASK[6] ) );\ xmm6 = _mm512_shuffle_epi8( xmm6, SUBSH_MASK6 );\
xmm7 = _mm512_shuffle_epi8( xmm7, ( SUBSH_MASK[7] ) );\ xmm7 = _mm512_shuffle_epi8( xmm7, SUBSH_MASK7 );\
/* SubBytes + MixBytes */\ /* SubBytes + MixBytes */\
SUBMIX(xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\ SUBMIX(xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\
}\ }\
@@ -284,16 +293,17 @@ __m512i ALL_FF;
xmm12 = _mm512_xor_si512( xmm12, xmm1 );\ xmm12 = _mm512_xor_si512( xmm12, xmm1 );\
xmm13 = _mm512_xor_si512( xmm13, xmm1 );\ xmm13 = _mm512_xor_si512( xmm13, xmm1 );\
xmm14 = _mm512_xor_si512( xmm14, xmm1 );\ xmm14 = _mm512_xor_si512( xmm14, xmm1 );\
xmm15 = _mm512_xor_si512( xmm15, ( ROUND_CONST_Q[ round_counter ] ) );\ xmm15 = _mm512_xor_si512( xmm15, m512_const1_128( \
casti_m128i( round_const_q, round_counter ) ) ); \
/* ShiftBytes Q1024 + pre-AESENCLAST */\ /* ShiftBytes Q1024 + pre-AESENCLAST */\
xmm8 = _mm512_shuffle_epi8( xmm8, ( SUBSH_MASK[1] ) );\ xmm8 = _mm512_shuffle_epi8( xmm8, SUBSH_MASK1 );\
xmm9 = _mm512_shuffle_epi8( xmm9, ( SUBSH_MASK[3] ) );\ xmm9 = _mm512_shuffle_epi8( xmm9, SUBSH_MASK3 );\
xmm10 = _mm512_shuffle_epi8( xmm10, ( SUBSH_MASK[5] ) );\ xmm10 = _mm512_shuffle_epi8( xmm10, SUBSH_MASK5 );\
xmm11 = _mm512_shuffle_epi8( xmm11, ( SUBSH_MASK[7] ) );\ xmm11 = _mm512_shuffle_epi8( xmm11, SUBSH_MASK7 );\
xmm12 = _mm512_shuffle_epi8( xmm12, ( SUBSH_MASK[0] ) );\ xmm12 = _mm512_shuffle_epi8( xmm12, SUBSH_MASK0 );\
xmm13 = _mm512_shuffle_epi8( xmm13, ( SUBSH_MASK[2] ) );\ xmm13 = _mm512_shuffle_epi8( xmm13, SUBSH_MASK2 );\
xmm14 = _mm512_shuffle_epi8( xmm14, ( SUBSH_MASK[4] ) );\ xmm14 = _mm512_shuffle_epi8( xmm14, SUBSH_MASK4 );\
xmm15 = _mm512_shuffle_epi8( xmm15, ( SUBSH_MASK[6] ) );\ xmm15 = _mm512_shuffle_epi8( xmm15, SUBSH_MASK6 );\
/* SubBytes + MixBytes */\ /* SubBytes + MixBytes */\
SUBMIX(xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\ SUBMIX(xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);\
\ \
@@ -306,16 +316,17 @@ __m512i ALL_FF;
xmm4 = _mm512_xor_si512( xmm4, xmm9 );\ xmm4 = _mm512_xor_si512( xmm4, xmm9 );\
xmm5 = _mm512_xor_si512( xmm5, xmm9 );\ xmm5 = _mm512_xor_si512( xmm5, xmm9 );\
xmm6 = _mm512_xor_si512( xmm6, xmm9 );\ xmm6 = _mm512_xor_si512( xmm6, xmm9 );\
xmm7 = _mm512_xor_si512( xmm7, ( ROUND_CONST_Q[ round_counter+1 ] ) );\ xmm7 = _mm512_xor_si512( xmm7, m512_const1_128( \
casti_m128i( round_const_q, round_counter+1 ) ) ); \
/* ShiftBytes Q1024 + pre-AESENCLAST */\ /* ShiftBytes Q1024 + pre-AESENCLAST */\
xmm0 = _mm512_shuffle_epi8( xmm0, ( SUBSH_MASK[1] ) );\ xmm0 = _mm512_shuffle_epi8( xmm0, SUBSH_MASK1 );\
xmm1 = _mm512_shuffle_epi8( xmm1, ( SUBSH_MASK[3] ) );\ xmm1 = _mm512_shuffle_epi8( xmm1, SUBSH_MASK3 );\
xmm2 = _mm512_shuffle_epi8( xmm2, ( SUBSH_MASK[5] ) );\ xmm2 = _mm512_shuffle_epi8( xmm2, SUBSH_MASK5 );\
xmm3 = _mm512_shuffle_epi8( xmm3, ( SUBSH_MASK[7] ) );\ xmm3 = _mm512_shuffle_epi8( xmm3, SUBSH_MASK7 );\
xmm4 = _mm512_shuffle_epi8( xmm4, ( SUBSH_MASK[0] ) );\ xmm4 = _mm512_shuffle_epi8( xmm4, SUBSH_MASK0 );\
xmm5 = _mm512_shuffle_epi8( xmm5, ( SUBSH_MASK[2] ) );\ xmm5 = _mm512_shuffle_epi8( xmm5, SUBSH_MASK2 );\
xmm6 = _mm512_shuffle_epi8( xmm6, ( SUBSH_MASK[4] ) );\ xmm6 = _mm512_shuffle_epi8( xmm6, SUBSH_MASK4 );\
xmm7 = _mm512_shuffle_epi8( xmm7, ( SUBSH_MASK[6] ) );\ xmm7 = _mm512_shuffle_epi8( xmm7, SUBSH_MASK6 );\
/* SubBytes + MixBytes */\ /* SubBytes + MixBytes */\
SUBMIX(xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\ SUBMIX(xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15);\
}\ }\

View File

@@ -1,4 +1,7 @@
#include "myrgr-gate.h" #include "myrgr-gate.h"
#if !defined(MYRGR_8WAY) && !defined(MYRGR_4WAY)
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
@@ -86,3 +89,4 @@ int scanhash_myriad( struct work *work, uint32_t max_nonce,
*hashes_done = pdata[19] - first_nonce + 1; *hashes_done = pdata[19] - first_nonce + 1;
return 0; return 0;
} }
#endif

View File

@@ -143,7 +143,7 @@ int scanhash_myriad_8way( struct work *work, uint32_t max_nonce,
if ( fulltest( lane_hash, ptarget ) && !opt_benchmark ) if ( fulltest( lane_hash, ptarget ) && !opt_benchmark )
{ {
pdata[19] = n + lane; pdata[19] = n + lane;
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
n += 8; n += 8;
@@ -226,7 +226,7 @@ int scanhash_myriad_4way( struct work *work, uint32_t max_nonce,
if ( fulltest( lane_hash, ptarget ) && !opt_benchmark ) if ( fulltest( lane_hash, ptarget ) && !opt_benchmark )
{ {
pdata[19] = n + lane; pdata[19] = n + lane;
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
n += 4; n += 4;

View File

@@ -35,6 +35,8 @@
#include "sph_groestl.h" #include "sph_groestl.h"
#if !defined(__AES__)
#ifdef __cplusplus #ifdef __cplusplus
extern "C"{ extern "C"{
#endif #endif
@@ -3116,4 +3118,6 @@ sph_groestl512_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif // !AES
#endif #endif

View File

@@ -42,6 +42,7 @@ extern "C"{
#include <stddef.h> #include <stddef.h>
#include "algo/sha/sph_types.h" #include "algo/sha/sph_types.h"
#if !defined(__AES__)
/** /**
* Output size (in bits) for Groestl-224. * Output size (in bits) for Groestl-224.
*/ */
@@ -326,4 +327,5 @@ void sph_groestl512_addbits_and_close(
} }
#endif #endif
#endif // !AES
#endif #endif

View File

@@ -1,156 +0,0 @@
#include "algo-gate-api.h"
#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
#include <stdint.h>
#include <stdlib.h>
#include "sph_hefty1.h"
#include "algo/luffa/sph_luffa.h"
#include "algo/fugue/sph_fugue.h"
#include "algo/skein/sph_skein.h"
#include "algo/whirlpool/sph_whirlpool.h"
#include "algo/shabal/sph_shabal.h"
#include "algo/echo/sph_echo.h"
#include "algo/hamsi/sph_hamsi.h"
#include "algo/luffa/luffa_for_sse2.h"
#ifdef __AES__
#include "algo/echo/aes_ni/hash_api.h"
#endif
void bastionhash(void *output, const void *input)
{
unsigned char hash[64] __attribute__ ((aligned (64)));
#ifdef __AES__
hashState_echo ctx_echo;
#else
sph_echo512_context ctx_echo;
#endif
hashState_luffa ctx_luffa;
sph_fugue512_context ctx_fugue;
sph_whirlpool_context ctx_whirlpool;
sph_shabal512_context ctx_shabal;
sph_hamsi512_context ctx_hamsi;
sph_skein512_context ctx_skein;
HEFTY1(input, 80, hash);
init_luffa( &ctx_luffa, 512 );
update_and_final_luffa( &ctx_luffa, (BitSequence*)hash,
(const BitSequence*)hash, 64 );
if (hash[0] & 0x8)
{
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, hash, 64);
sph_fugue512_close(&ctx_fugue, hash);
} else {
sph_skein512_init( &ctx_skein );
sph_skein512( &ctx_skein, hash, 64 );
sph_skein512_close( &ctx_skein, hash );
}
sph_whirlpool_init(&ctx_whirlpool);
sph_whirlpool(&ctx_whirlpool, hash, 64);
sph_whirlpool_close(&ctx_whirlpool, hash);
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, hash, 64);
sph_fugue512_close(&ctx_fugue, hash);
if (hash[0] & 0x8)
{
#ifdef __AES__
init_echo( &ctx_echo, 512 );
update_final_echo ( &ctx_echo,(BitSequence*)hash,
(const BitSequence*)hash, 512 );
#else
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
#endif
} else {
init_luffa( &ctx_luffa, 512 );
update_and_final_luffa( &ctx_luffa, (BitSequence*)hash,
(const BitSequence*)hash, 64 );
}
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, hash, 64);
sph_shabal512_close(&ctx_shabal, hash);
sph_skein512_init( &ctx_skein );
sph_skein512( &ctx_skein, hash, 64 );
sph_skein512_close( &ctx_skein, hash );
if (hash[0] & 0x8)
{
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, hash, 64);
sph_shabal512_close(&ctx_shabal, hash);
} else {
sph_whirlpool_init(&ctx_whirlpool);
sph_whirlpool(&ctx_whirlpool, hash, 64);
sph_whirlpool_close(&ctx_whirlpool, hash);
}
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, hash, 64);
sph_shabal512_close(&ctx_shabal, hash);
if (hash[0] & 0x8)
{
sph_hamsi512_init(&ctx_hamsi);
sph_hamsi512(&ctx_hamsi, hash, 64);
sph_hamsi512_close(&ctx_hamsi, hash);
} else {
init_luffa( &ctx_luffa, 512 );
update_and_final_luffa( &ctx_luffa, (BitSequence*)hash,
(const BitSequence*)hash, 64 );
}
memcpy(output, hash, 32);
}
int scanhash_bastion( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr)
{
uint32_t _ALIGN(64) hash32[8];
uint32_t _ALIGN(64) endiandata[20];
uint32_t *pdata = work->data;
uint32_t *ptarget = work->target;
int thr_id = mythr->id; // thr_id arg is deprecated
const uint32_t Htarg = ptarget[7];
const uint32_t first_nonce = pdata[19];
uint32_t n = first_nonce;
for (int i=0; i < 19; i++)
be32enc(&endiandata[i], pdata[i]);
do {
be32enc(&endiandata[19], n);
bastionhash(hash32, endiandata);
if (hash32[7] < Htarg && fulltest(hash32, ptarget)) {
pdata[19] = n;
submit_solution( work, hash32, mythr );
}
n++;
} while (n < max_nonce && !work_restart[thr_id].restart);
*hashes_done = n - first_nonce + 1;
pdata[19] = n;
return 0;
}
bool register_bastion_algo( algo_gate_t* gate )
{
gate->optimizations = SSE2_OPT | AES_OPT;
gate->scanhash = (void*)&scanhash_bastion;
gate->hash = (void*)&bastionhash;
return true;
};

View File

@@ -1,111 +0,0 @@
#include <string.h>
#include <openssl/sha.h>
#include <stdint.h>
#include "algo-gate-api.h"
#include "sph_hefty1.h"
#include "algo/keccak/sph_keccak.h"
#include "algo/blake/sph_blake.h"
#include "algo/groestl/sph_groestl.h"
/* Combines top 64-bits from each hash into a single hash */
static void combine_hashes(uint32_t *out, uint32_t *hash1, uint32_t *hash2, uint32_t *hash3, uint32_t *hash4)
{
uint32_t *hash[4] = { hash1, hash2, hash3, hash4 };
/* Transpose first 64 bits of each hash into out */
memset(out, 0, 32);
int bits = 0;
for (unsigned int i = 7; i >= 6; i--) {
for (uint32_t mask = 0x80000000; mask; mask >>= 1) {
for (unsigned int k = 0; k < 4; k++) {
out[(255 - bits)/32] <<= 1;
if ((hash[k][i] & mask) != 0)
out[(255 - bits)/32] |= 1;
bits++;
}
}
}
}
extern void heavyhash(unsigned char* output, const unsigned char* input, int len)
{
unsigned char hash1[32];
HEFTY1(input, len, hash1);
// HEFTY1 is new, so take an extra security measure to eliminate
// * the possiblity of collisions:
// *
// * Hash(x) = SHA256(x + HEFTY1(x))
// *
// * N.B. '+' is concatenation.
//
unsigned char hash2[32];;
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, input, len);
SHA256_Update(&ctx, hash1, sizeof(hash1));
SHA256_Final(hash2, &ctx);
// * Additional security: Do not rely on a single cryptographic hash
// * function. Instead, combine the outputs of 4 of the most secure
// * cryptographic hash functions-- SHA256, KECCAK512, GROESTL512
// * and BLAKE512.
uint32_t hash3[16];
sph_keccak512_context keccakCtx;
sph_keccak512_init(&keccakCtx);
sph_keccak512(&keccakCtx, input, len);
sph_keccak512(&keccakCtx, hash1, sizeof(hash1));
sph_keccak512_close(&keccakCtx, (void *)&hash3);
uint32_t hash4[16];
sph_groestl512_context groestlCtx;
sph_groestl512_init(&groestlCtx);
sph_groestl512(&groestlCtx, input, len);
sph_groestl512(&groestlCtx, hash1, sizeof(hash1));
sph_groestl512_close(&groestlCtx, (void *)&hash4);
uint32_t hash5[16];
sph_blake512_context blakeCtx;
sph_blake512_init(&blakeCtx);
sph_blake512(&blakeCtx, input, len);
sph_blake512(&blakeCtx, (unsigned char *)&hash1, sizeof(hash1));
sph_blake512_close(&blakeCtx, (void *)&hash5);
uint32_t *final = (uint32_t *)output;
combine_hashes(final, (uint32_t *)hash2, hash3, hash4, hash5);
}
int scanhash_heavy( uint32_t *pdata, const uint32_t *ptarget,
uint32_t max_nonce, uint64_t *hashes_done, struct thr_info *mythr)
{
uint32_t hash[8];
uint32_t start_nonce = pdata[19];
int thr_id = mythr->id; // thr_id arg is deprecated
do {
heavyhash((unsigned char *)hash, (unsigned char *)pdata, 80);
if (hash[7] <= ptarget[7]) {
if (fulltest(hash, ptarget)) {
*hashes_done = pdata[19] - start_nonce;
return 1;
break;
}
}
pdata[19]++;
} while (pdata[19] < max_nonce && !work_restart[thr_id].restart);
*hashes_done = pdata[19] - start_nonce;
return 0;
}
bool register_heavy_algo( algo_gate_t* gate )
{
gate->scanhash = (void*)&scanhash_heavy;
gate->hash = (void*)&heavyhash;
return true;
};

View File

@@ -99,9 +99,13 @@ void hodl_build_block_header( struct work* g_work, uint32_t version,
// called only by thread 0, saves a backup of g_work // called only by thread 0, saves a backup of g_work
void hodl_get_new_work( struct work* work, struct work* g_work) void hodl_get_new_work( struct work* work, struct work* g_work)
{ {
work_free( &hodl_work ); pthread_rwlock_rdlock( &g_work_lock );
work_copy( &hodl_work, g_work );
hodl_work.data[ algo_gate.nonce_index ] = ( clock() + rand() ) % 9999; work_free( &hodl_work );
work_copy( &hodl_work, g_work );
hodl_work.data[ algo_gate.nonce_index ] = ( clock() + rand() ) % 9999;
pthread_rwlock_unlock( &g_work_lock );
} }
json_t *hodl_longpoll_rpc_call( CURL *curl, int *err, char* lp_url ) json_t *hodl_longpoll_rpc_call( CURL *curl, int *err, char* lp_url )
@@ -144,7 +148,7 @@ int hodl_scanhash( struct work* work, uint32_t max_nonce,
#if defined(__AES__) #if defined(__AES__)
GenRandomGarbage( (CacheEntry*)hodl_scratchbuf, work->data, mythr->id ); GenRandomGarbage( (CacheEntry*)hodl_scratchbuf, work->data, mythr->id );
pthread_barrier_wait( &hodl_barrier ); pthread_barrier_wait( &hodl_barrier );
return scanhash_hodl_wolf( work, max_nonce, hashes_done, thr_info ); return scanhash_hodl_wolf( work, max_nonce, hashes_done, mythr );
#endif #endif
return false; return false;
} }
@@ -155,11 +159,10 @@ bool register_hodl_algo( algo_gate_t* gate )
applog( LOG_ERR, "Only CPUs with AES are supported, use legacy version."); applog( LOG_ERR, "Only CPUs with AES are supported, use legacy version.");
return false; return false;
#endif #endif
// if ( TOTAL_CHUNKS % opt_n_threads )
// { if ( GARBAGE_SIZE % opt_n_threads )
// applog(LOG_ERR,"Thread count must be power of 2."); applog( LOG_WARNING,"WARNING: Thread count must be power of 2. Miner may crash or produce invalid hash!" );
// return false;
// }
pthread_barrier_init( &hodl_barrier, NULL, opt_n_threads ); pthread_barrier_init( &hodl_barrier, NULL, opt_n_threads );
gate->optimizations = SSE42_OPT | AES_OPT | AVX2_OPT; gate->optimizations = SSE42_OPT | AES_OPT | AVX2_OPT;
gate->scanhash = (void*)&hodl_scanhash; gate->scanhash = (void*)&hodl_scanhash;
@@ -171,7 +174,7 @@ bool register_hodl_algo( algo_gate_t* gate )
gate->resync_threads = (void*)&hodl_resync_threads; gate->resync_threads = (void*)&hodl_resync_threads;
gate->do_this_thread = (void*)&hodl_do_this_thread; gate->do_this_thread = (void*)&hodl_do_this_thread;
gate->work_cmp_size = 76; gate->work_cmp_size = 76;
hodl_scratchbuf = (unsigned char*)malloc( 1 << 30 ); hodl_scratchbuf = (unsigned char*)_mm_malloc( 1 << 30, 64 );
allow_getwork = false; allow_getwork = false;
opt_target_factor = 8388608.0; opt_target_factor = 8388608.0;
return ( hodl_scratchbuf != NULL ); return ( hodl_scratchbuf != NULL );

View File

@@ -70,7 +70,7 @@ int scanhash_hodl_wolf( struct work* work, uint32_t max_nonce,
uint32_t *ptarget = work->target; uint32_t *ptarget = work->target;
int threadNumber = mythr->id; int threadNumber = mythr->id;
CacheEntry *Garbage = (CacheEntry*)hodl_scratchbuf; CacheEntry *Garbage = (CacheEntry*)hodl_scratchbuf;
CacheEntry Cache[AES_PARALLEL_N]; CacheEntry Cache[AES_PARALLEL_N] __attribute__ ((aligned (64)));
__m128i* data[AES_PARALLEL_N]; __m128i* data[AES_PARALLEL_N];
const __m128i* next[AES_PARALLEL_N]; const __m128i* next[AES_PARALLEL_N];
uint32_t CollisionCount = 0; uint32_t CollisionCount = 0;
@@ -129,9 +129,10 @@ int scanhash_hodl_wolf( struct work* work, uint32_t max_nonce,
if( FinalPoW[7] <= ptarget[7] ) if( FinalPoW[7] <= ptarget[7] )
{ {
pdata[20] = swab32( BlockHdr[20] ); pdata[20] = swab32( BlockHdr[20] );
pdata[21] = swab32( BlockHdr[21] ); pdata[21] = swab32( BlockHdr[21] );
*hashes_done = CollisionCount; *hashes_done = CollisionCount;
return(1); submit_solution( work, FinalPoW, mythr );
return(0);
} }
} }
} }
@@ -198,7 +199,8 @@ int scanhash_hodl_wolf( struct work* work, uint32_t max_nonce,
pdata[20] = swab32( BlockHdr[20] ); pdata[20] = swab32( BlockHdr[20] );
pdata[21] = swab32( BlockHdr[21] ); pdata[21] = swab32( BlockHdr[21] );
*hashes_done = CollisionCount; *hashes_done = CollisionCount;
return(1); submit_solution( work, FinalPoW, mythr );
return(0);
} }
} }
} }

View File

@@ -129,7 +129,7 @@ int scanhash_jha_4way( struct work *work, uint32_t max_nonce,
if ( fulltest( hash+(i<<3), ptarget ) && !opt_benchmark ) if ( fulltest( hash+(i<<3), ptarget ) && !opt_benchmark )
{ {
pdata[19] = n+i; pdata[19] = n+i;
submit_lane_solution( work, lane_hash, mythr, i ); submit_solution( work, lane_hash, mythr );
} }
} }
n += 4; n += 4;

View File

@@ -1,4 +1,7 @@
#include "jha-gate.h" #include "jha-gate.h"
#if !defined(JHA_8WAY) && !defined(JHA_4WAY)
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@@ -133,3 +136,4 @@ int scanhash_jha( struct work *work, uint32_t max_nonce,
return 0; return 0;
} }
#endif

View File

@@ -28,30 +28,32 @@ int scanhash_keccak_8way( struct work *work, uint32_t max_nonce,
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
__m512i *noncev = (__m512i*)vdata + 9; // aligned __m512i *noncev = (__m512i*)vdata + 9; // aligned
const uint32_t Htarg = ptarget[7]; const uint32_t Htarg = ptarget[7];
int thr_id = mythr->id; const int thr_id = mythr->id;
const bool bench = opt_benchmark;
mm512_bswap32_intrlv80_8x64( vdata, pdata ); mm512_bswap32_intrlv80_8x64( vdata, pdata );
*noncev = mm512_intrlv_blend_32(
_mm512_set_epi32( n+7, 0, n+6, 0, n+5, 0, n+4, 0,
n+3, 0, n+2, 0, n+1, 0, n , 0 ), *noncev );
do { do {
*noncev = mm512_intrlv_blend_32( mm512_bswap_32(
_mm512_set_epi32( n+7, 0, n+6, 0, n+5, 0, n+4, 0,
n+3, 0, n+2, 0, n+1, 0, n , 0 ) ), *noncev );
keccakhash_8way( hash, vdata ); keccakhash_8way( hash, vdata );
for ( int lane = 0; lane < 8; lane++ ) for ( int lane = 0; lane < 8; lane++ )
if ( hash7[ lane<<1 ] <= Htarg ) if unlikely( hash7[ lane<<1 ] <= Htarg && !bench )
{ {
extr_lane_8x64( lane_hash, hash, lane, 256 ); extr_lane_8x64( lane_hash, hash, lane, 256 );
if ( fulltest( lane_hash, ptarget ) && !opt_benchmark ) if ( valid_hash( lane_hash, ptarget ) )
{ {
pdata[19] = n + lane; pdata[19] = bswap_32( n + lane );
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
*noncev = _mm512_add_epi32( *noncev,
m512_const1_64( 0x0000000800000000 ) );
n += 8; n += 8;
} while ( (n < max_nonce-8) && !work_restart[thr_id].restart); } while ( (n < max_nonce-8) && !work_restart[thr_id].restart);
pdata[19] = n;
*hashes_done = n - first_nonce + 1; *hashes_done = n - first_nonce + 1;
return 0; return 0;
} }
@@ -79,29 +81,30 @@ int scanhash_keccak_4way( struct work *work, uint32_t max_nonce,
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
__m256i *noncev = (__m256i*)vdata + 9; // aligned __m256i *noncev = (__m256i*)vdata + 9; // aligned
const uint32_t Htarg = ptarget[7]; const uint32_t Htarg = ptarget[7];
int thr_id = mythr->id; const int thr_id = mythr->id;
const bool bench = opt_benchmark;
mm256_bswap32_intrlv80_4x64( vdata, pdata ); mm256_bswap32_intrlv80_4x64( vdata, pdata );
*noncev = mm256_intrlv_blend_32(
_mm256_set_epi32( n+3, 0, n+2, 0, n+1, 0, n, 0 ), *noncev );
do { do {
*noncev = mm256_intrlv_blend_32( mm256_bswap_32(
_mm256_set_epi32( n+3, 0, n+2, 0, n+1, 0, n, 0 ) ), *noncev );
keccakhash_4way( hash, vdata ); keccakhash_4way( hash, vdata );
for ( int lane = 0; lane < 4; lane++ ) for ( int lane = 0; lane < 4; lane++ )
if ( hash7[ lane<<1 ] <= Htarg ) if unlikely( hash7[ lane<<1 ] <= Htarg && !bench )
{ {
extr_lane_4x64( lane_hash, hash, lane, 256 ); extr_lane_4x64( lane_hash, hash, lane, 256 );
if ( fulltest( lane_hash, ptarget ) && !opt_benchmark ) if ( valid_hash( lane_hash, ptarget ))
{ {
pdata[19] = n + lane; pdata[19] = bswap_32( n + lane );
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
*noncev = _mm256_add_epi32( *noncev,
m256_const1_64( 0x0000000400000000 ) );
n += 4; n += 4;
} while ( (n < max_nonce-4) && !work_restart[thr_id].restart); } while ( (n < max_nonce-4) && !work_restart[thr_id].restart);
pdata[19] = n;
*hashes_done = n - first_nonce + 1; *hashes_done = n - first_nonce + 1;
return 0; return 0;
} }

View File

@@ -1,5 +1,9 @@
#include "keccak-gate.h" #include "keccak-gate.h"
#include "sph_keccak.h"
int hard_coded_eb = 1;
// KECCAK
bool register_keccak_algo( algo_gate_t* gate ) bool register_keccak_algo( algo_gate_t* gate )
{ {
@@ -19,6 +23,8 @@ bool register_keccak_algo( algo_gate_t* gate )
return true; return true;
}; };
// KECCAKC
bool register_keccakc_algo( algo_gate_t* gate ) bool register_keccakc_algo( algo_gate_t* gate )
{ {
gate->optimizations = AVX2_OPT | AVX512_OPT; gate->optimizations = AVX2_OPT | AVX512_OPT;
@@ -37,3 +43,50 @@ bool register_keccakc_algo( algo_gate_t* gate )
return true; return true;
}; };
// SHA3D
void sha3d( void *state, const void *input, int len )
{
uint32_t _ALIGN(64) buffer[16], hash[16];
sph_keccak_context ctx_keccak;
sph_keccak256_init( &ctx_keccak );
sph_keccak256 ( &ctx_keccak, input, len );
sph_keccak256_close( &ctx_keccak, (void*) buffer );
sph_keccak256_init( &ctx_keccak );
sph_keccak256 ( &ctx_keccak, buffer, 32 );
sph_keccak256_close( &ctx_keccak, (void*) hash );
memcpy(state, hash, 32);
}
void sha3d_gen_merkle_root( char* merkle_root, struct stratum_ctx* sctx )
{
sha3d( merkle_root, sctx->job.coinbase, (int) sctx->job.coinbase_size );
for ( int i = 0; i < sctx->job.merkle_count; i++ )
{
memcpy( merkle_root + 32, sctx->job.merkle[i], 32 );
sha256d( merkle_root, merkle_root, 64 );
}
}
bool register_sha3d_algo( algo_gate_t* gate )
{
hard_coded_eb = 6;
// opt_extranonce = false;
gate->optimizations = AVX2_OPT | AVX512_OPT;
gate->gen_merkle_root = (void*)&sha3d_gen_merkle_root;
#if defined (KECCAK_8WAY)
gate->scanhash = (void*)&scanhash_sha3d_8way;
gate->hash = (void*)&sha3d_hash_8way;
#elif defined (KECCAK_4WAY)
gate->scanhash = (void*)&scanhash_sha3d_4way;
gate->hash = (void*)&sha3d_hash_4way;
#else
gate->scanhash = (void*)&scanhash_sha3d;
gate->hash = (void*)&sha3d_hash;
#endif
return true;
};

View File

@@ -10,24 +10,37 @@
#define KECCAK_4WAY 1 #define KECCAK_4WAY 1
#endif #endif
extern int hard_coded_eb;
#if defined(KECCAK_8WAY) #if defined(KECCAK_8WAY)
void keccakhash_8way( void *state, const void *input ); void keccakhash_8way( void *state, const void *input );
int scanhash_keccak_8way( struct work *work, uint32_t max_nonce, int scanhash_keccak_8way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ); uint64_t *hashes_done, struct thr_info *mythr );
void sha3d_hash_8way( void *state, const void *input );
int scanhash_sha3d_8way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr );
#elif defined(KECCAK_4WAY) #elif defined(KECCAK_4WAY)
void keccakhash_4way( void *state, const void *input ); void keccakhash_4way( void *state, const void *input );
int scanhash_keccak_4way( struct work *work, uint32_t max_nonce, int scanhash_keccak_4way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ); uint64_t *hashes_done, struct thr_info *mythr );
void sha3d_hash_4way( void *state, const void *input );
int scanhash_sha3d_4way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr );
#else #else
void keccakhash( void *state, const void *input ); void keccakhash( void *state, const void *input );
int scanhash_keccak( struct work *work, uint32_t max_nonce, int scanhash_keccak( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ); uint64_t *hashes_done, struct thr_info *mythr );
#endif void sha3d_hash( void *state, const void *input );
int scanhash_sha3d( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr );
#endif #endif
#endif

View File

@@ -1,6 +1,9 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "keccak-hash-4way.h" #include "keccak-hash-4way.h"
#include "keccak-gate.h"
#if defined(__AVX2__)
static const uint64_t RC[] = { static const uint64_t RC[] = {
0x0000000000000001, 0x0000000000008082, 0x0000000000000001, 0x0000000000008082,
@@ -168,7 +171,7 @@ static void keccak64_8way_close( keccak64_ctx_m512i *kc, void *dst,
size_t j; size_t j;
size_t m512_len = byte_len >> 3; size_t m512_len = byte_len >> 3;
eb = 0x100 >> 8; eb = hard_coded_eb;
if ( kc->ptr == (lim - 8) ) if ( kc->ptr == (lim - 8) )
{ {
const uint64_t t = eb | 0x8000000000000000; const uint64_t t = eb | 0x8000000000000000;
@@ -238,7 +241,7 @@ keccak512_8way_close(void *cc, void *dst)
#endif // AVX512 #endif // AVX512
#if defined(__AVX2__) // AVX2
#define INPUT_BUF(size) do { \ #define INPUT_BUF(size) do { \
size_t j; \ size_t j; \
@@ -349,7 +352,7 @@ static void keccak64_close( keccak64_ctx_m256i *kc, void *dst, size_t byte_len,
size_t j; size_t j;
size_t m256_len = byte_len >> 3; size_t m256_len = byte_len >> 3;
eb = 0x100 >> 8; eb = hard_coded_eb;
if ( kc->ptr == (lim - 8) ) if ( kc->ptr == (lim - 8) )
{ {
const uint64_t t = eb | 0x8000000000000000; const uint64_t t = eb | 0x8000000000000000;

View File

@@ -1,4 +1,6 @@
#include "algo-gate-api.h" #include "keccak-gate.h"
#if !defined(KECCAK_8WAY) && !defined(KECCAK_4WAY)
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -18,36 +20,35 @@ void keccakhash(void *state, const void *input)
memcpy(state, hash, 32); memcpy(state, hash, 32);
} }
int scanhash_keccak( struct work *work, int scanhash_keccak( struct work *work, uint32_t max_nonce,
uint32_t max_nonce, uint64_t *hashes_done, struct thr_info *mythr ) uint64_t *hashes_done, struct thr_info *mythr )
{ {
uint32_t *pdata = work->data; uint32_t _ALIGN(64) hash64[8];
uint32_t *ptarget = work->target; uint32_t _ALIGN(64) endiandata[32];
uint32_t n = pdata[19] - 1; uint32_t *pdata = work->data;
const uint32_t first_nonce = pdata[19]; uint32_t *ptarget = work->target;
//const uint32_t Htarg = ptarget[7]; uint32_t n = pdata[19];
int thr_id = mythr->id; // thr_id arg is deprecated const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce;
const int thr_id = mythr->id;
uint32_t _ALIGN(32) hash64[8]; for ( int i=0; i < 19; i++ )
uint32_t endiandata[32]; be32enc( &endiandata[i], pdata[i] );
for (int i=0; i < 19; i++) do {
be32enc(&endiandata[i], pdata[i]); be32enc( &endiandata[19], n );
keccakhash( hash64, endiandata );
if ( valid_hash( hash64, ptarget ) && !opt_benchmark )
{
pdata[19] = n;
submit_solution( work, hash64, mythr );
}
n++;
} while ( n < last_nonce && !work_restart[thr_id].restart );
do { *hashes_done = n - first_nonce;
pdata[19] = n;
pdata[19] = ++n; return 0;
be32enc(&endiandata[19], n);
keccakhash(hash64, endiandata);
if (((hash64[7]&0xFFFFFF00)==0) &&
fulltest(hash64, ptarget)) {
*hashes_done = n - first_nonce + 1;
return true;
}
} while (n < max_nonce && !work_restart[thr_id].restart);
*hashes_done = n - first_nonce + 1;
pdata[19] = n;
return 0;
} }
#endif

126
algo/keccak/sha3d-4way.c Normal file
View File

@@ -0,0 +1,126 @@
#include "keccak-gate.h"
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "sph_keccak.h"
#include "keccak-hash-4way.h"
#if defined(KECCAK_8WAY)
void sha3d_hash_8way(void *state, const void *input)
{
uint32_t buffer[16*8] __attribute__ ((aligned (128)));
keccak256_8way_context ctx;
keccak256_8way_init( &ctx );
keccak256_8way_update( &ctx, input, 80 );
keccak256_8way_close( &ctx, buffer );
keccak256_8way_init( &ctx );
keccak256_8way_update( &ctx, buffer, 32 );
keccak256_8way_close( &ctx, state );
}
int scanhash_sha3d_8way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr )
{
uint32_t vdata[24*8] __attribute__ ((aligned (128)));
uint32_t hash[16*8] __attribute__ ((aligned (64)));
uint32_t lane_hash[8] __attribute__ ((aligned (64)));
uint32_t *hash7 = &(hash[49]); // 3*16+1
uint32_t *pdata = work->data;
uint32_t *ptarget = work->target;
uint32_t n = pdata[19];
const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 8;
__m512i *noncev = (__m512i*)vdata + 9; // aligned
const uint32_t Htarg = ptarget[7];
const int thr_id = mythr->id;
const bool bench = opt_benchmark;
mm512_bswap32_intrlv80_8x64( vdata, pdata );
*noncev = mm512_intrlv_blend_32(
_mm512_set_epi32( n+7, 0, n+6, 0, n+5, 0, n+4, 0,
n+3, 0, n+2, 0, n+1, 0, n , 0 ), *noncev );
do {
sha3d_hash_8way( hash, vdata );
for ( int lane = 0; lane < 8; lane++ )
if ( unlikely( hash7[ lane<<1 ] <= Htarg && !bench ) )
{
extr_lane_8x64( lane_hash, hash, lane, 256 );
if ( valid_hash( lane_hash, ptarget ) )
{
pdata[19] = bswap_32( n + lane );
submit_solution( work, lane_hash, mythr );
}
}
*noncev = _mm512_add_epi32( *noncev,
m512_const1_64( 0x0000000800000000 ) );
n += 8;
} while ( likely( (n < last_nonce) && !work_restart[thr_id].restart ) );
pdata[19] = n;
*hashes_done = n - first_nonce;
return 0;
}
#elif defined(KECCAK_4WAY)
void sha3d_hash_4way(void *state, const void *input)
{
uint32_t buffer[16*4] __attribute__ ((aligned (64)));
keccak256_4way_context ctx;
keccak256_4way_init( &ctx );
keccak256_4way_update( &ctx, input, 80 );
keccak256_4way_close( &ctx, buffer );
keccak256_4way_init( &ctx );
keccak256_4way_update( &ctx, buffer, 32 );
keccak256_4way_close( &ctx, state );
}
int scanhash_sha3d_4way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr )
{
uint32_t vdata[24*4] __attribute__ ((aligned (64)));
uint32_t hash[16*4] __attribute__ ((aligned (32)));
uint32_t lane_hash[8] __attribute__ ((aligned (32)));
uint32_t *hash7 = &(hash[25]); // 3*8+1
uint32_t *pdata = work->data;
uint32_t *ptarget = work->target;
uint32_t n = pdata[19];
const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 4;
__m256i *noncev = (__m256i*)vdata + 9; // aligned
const uint32_t Htarg = ptarget[7];
const int thr_id = mythr->id;
const bool bench = opt_benchmark;
mm256_bswap32_intrlv80_4x64( vdata, pdata );
*noncev = mm256_intrlv_blend_32(
_mm256_set_epi32( n+3, 0, n+2, 0, n+1, 0, n, 0 ), *noncev );
do {
sha3d_hash_4way( hash, vdata );
for ( int lane = 0; lane < 4; lane++ )
if ( unlikely( hash7[ lane<<1 ] <= Htarg && !bench ) )
{
extr_lane_4x64( lane_hash, hash, lane, 256 );
if ( valid_hash( lane_hash, ptarget ) )
{
pdata[19] = bswap_32( n + lane );
submit_solution( work, lane_hash, mythr );
}
}
*noncev = _mm256_add_epi32( *noncev,
m256_const1_64( 0x0000000400000000 ) );
n += 4;
} while ( likely( (n < last_nonce) && !work_restart[thr_id].restart ) );
pdata[19] = n;
*hashes_done = n - first_nonce;
return 0;
}
#endif

54
algo/keccak/sha3d.c Normal file
View File

@@ -0,0 +1,54 @@
#include "keccak-gate.h"
#if !defined(KECCAK_8WAY) && !defined(KECCAK_4WAY)
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "sph_keccak.h"
void sha3d_hash(void *state, const void *input)
{
uint32_t buffer[16];
sph_keccak256_context ctx_keccak;
sph_keccak256_init( &ctx_keccak );
sph_keccak256 ( &ctx_keccak, input, 80 );
sph_keccak256_close( &ctx_keccak, buffer );
sph_keccak256_init( &ctx_keccak );
sph_keccak256 ( &ctx_keccak, buffer, 32 );
sph_keccak256_close( &ctx_keccak, state );
}
int scanhash_sha3d( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr )
{
uint32_t _ALIGN(64) hash64[8];
uint32_t _ALIGN(64) endiandata[32];
uint32_t *pdata = work->data;
uint32_t *ptarget = work->target;
uint32_t n = pdata[19];
const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce;
const int thr_id = mythr->id;
for ( int i=0; i < 19; i++ )
be32enc( &endiandata[i], pdata[i] );
do {
be32enc( &endiandata[19], n );
sha3d_hash( hash64, endiandata );
if ( valid_hash( hash64, ptarget ) && !opt_benchmark )
{
pdata[19] = n;
submit_solution( work, hash64, mythr );
}
n++;
} while ( n < last_nonce && !work_restart[thr_id].restart );
*hashes_done = n - first_nonce;
pdata[19] = n;
return 0;
}
#endif

View File

@@ -32,8 +32,8 @@
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include "sph_keccak.h" #include "sph_keccak.h"
#include "keccak-gate.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C"{ extern "C"{
@@ -1616,7 +1616,7 @@ keccak_core(sph_keccak_context *kc, const void *data, size_t len, size_t lim)
} u; \ } u; \
size_t j; \ size_t j; \
\ \
eb = (0x100 | (ub & 0xFF)) >> (8 - n); \ eb = hard_coded_eb; \
if (kc->ptr == (lim - 1)) { \ if (kc->ptr == (lim - 1)) { \
if (n == 7) { \ if (n == 7) { \
u.tmp[0] = eb; \ u.tmp[0] = eb; \

View File

@@ -1,63 +0,0 @@
#include "algo-gate-api.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "sph_luffa.h"
void luffahash(void *output, const void *input)
{
unsigned char _ALIGN(128) hash[64];
sph_luffa512_context ctx_luffa;
sph_luffa512_init(&ctx_luffa);
sph_luffa512 (&ctx_luffa, input, 80);
sph_luffa512_close(&ctx_luffa, (void*) hash);
memcpy(output, hash, 32);
}
int scanhash_luffa(int thr_id, struct work *work,
uint32_t max_nonce, uint64_t *hashes_done)
{
uint32_t *pdata = work->data;
uint32_t *ptarget = work->target;
uint32_t _ALIGN(64) hash64[8];
uint32_t _ALIGN(64) endiandata[20];
const uint32_t Htarg = ptarget[7];
const uint32_t first_nonce = pdata[19];
uint32_t n = first_nonce;
for (int i=0; i < 19; i++)
be32enc(&endiandata[i], pdata[i]);
do {
be32enc(&endiandata[19], n);
luffahash(hash64, endiandata);
if (hash64[7] < Htarg && fulltest(hash64, ptarget)) {
*hashes_done = n - first_nonce + 1;
pdata[19] = n;
return true;
}
n++;
} while (n < max_nonce && !work_restart[thr_id].restart);
*hashes_done = n - first_nonce + 1;
pdata[19] = n;
return 0;
}
bool register_luffa_algo( algo_gate_t* gate )
{
gate->scanhash = (void*)&scanhash_luffa;
gate->hash = (void*)&luffahash;
return true;
};

View File

@@ -344,17 +344,12 @@ HashReturn update_and_final_luffa( hashState_luffa *state, BitSequence* output,
// 16 byte partial block exists for 80 byte len // 16 byte partial block exists for 80 byte len
if ( state->rembytes ) if ( state->rembytes )
{ // padding of partial block
// padding of partial block rnd512( state, m128_const_64( 0, 0x80000000 ),
rnd512( state, _mm_set_epi8( 0,0,0,0, 0,0,0,0, 0,0,0,0, 0x80,0,0,0 ),
mm128_bswap_32( cast_m128i( data ) ) ); mm128_bswap_32( cast_m128i( data ) ) );
}
else else
{ // empty pad block
// empty pad block rnd512( state, m128_zero, m128_const_64( 0, 0x80000000 ) );
rnd512( state, _mm_setzero_si128(),
_mm_set_epi8( 0,0,0,0, 0,0,0,0, 0,0,0,0, 0x80,0,0,0 ) );
}
finalization512( state, (uint32*) output ); finalization512( state, (uint32*) output );
if ( state->hashbitlen > 512 ) if ( state->hashbitlen > 512 )
@@ -363,6 +358,56 @@ HashReturn update_and_final_luffa( hashState_luffa *state, BitSequence* output,
return SUCCESS; return SUCCESS;
} }
int luffa_full( hashState_luffa *state, BitSequence* output, int hashbitlen,
const BitSequence* data, size_t inlen )
{
// Optimized for integrals of 16 bytes, good for 64 and 80 byte len
int i;
state->hashbitlen = hashbitlen;
/* set the lower 32 bits to '1' */
MASK= _mm_set_epi32(0x00000000, 0x00000000, 0x00000000, 0xffffffff);
/* set all bits to '1' */
ALLONE = _mm_set_epi32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
/* set the 32-bit round constant values to the 128-bit data field */
for ( i=0; i<32; i++ )
CNS128[i] = _mm_load_si128( (__m128i*)&CNS_INIT[i*4] );
for ( i=0; i<10; i++ )
state->chainv[i] = _mm_load_si128( (__m128i*)&IV[i*4] );
memset(state->buffer, 0, sizeof state->buffer );
// update
int blocks = (int)( inlen / 32 );
state->rembytes = inlen % 32;
// full blocks
for ( i = 0; i < blocks; i++ )
{
rnd512( state, mm128_bswap_32( casti_m128i( data, 1 ) ),
mm128_bswap_32( casti_m128i( data, 0 ) ) );
data += MSG_BLOCK_BYTE_LEN;
}
// final
// 16 byte partial block exists for 80 byte len
if ( state->rembytes )
// padding of partial block
rnd512( state, m128_const_64( 0, 0x80000000 ),
mm128_bswap_32( cast_m128i( data ) ) );
else
// empty pad block
rnd512( state, m128_zero, m128_const_64( 0, 0x80000000 ) );
finalization512( state, (uint32*) output );
if ( state->hashbitlen > 512 )
finalization512( state, (uint32*)( output+128 ) );
return SUCCESS;
}
/***************************************************/ /***************************************************/
/* Round function */ /* Round function */
/* state: hash context */ /* state: hash context */

View File

@@ -1,3 +1,6 @@
#if !defined(LUFFA_FOR_SSE2_H__)
#define LUFFA_FOR_SSE2_H__ 1
/* /*
* luffa_for_sse2.h * luffa_for_sse2.h
* Version 2.0 (Sep 15th 2009) * Version 2.0 (Sep 15th 2009)
@@ -48,8 +51,6 @@
typedef struct { typedef struct {
uint32 buffer[8] __attribute((aligned(32))); uint32 buffer[8] __attribute((aligned(32)));
__m128i chainv[10] __attribute((aligned(32))); /* Chaining values */ __m128i chainv[10] __attribute((aligned(32))); /* Chaining values */
// uint64 bitlen[2]; /* Message length in bits */
// uint32 rembitlen; /* Length of buffer data to be hashed */
int hashbitlen; int hashbitlen;
int rembytes; int rembytes;
} hashState_luffa; } hashState_luffa;
@@ -65,5 +66,6 @@ HashReturn final_luffa( hashState_luffa *state, BitSequence *hashval );
HashReturn update_and_final_luffa( hashState_luffa *state, BitSequence* output, HashReturn update_and_final_luffa( hashState_luffa *state, BitSequence* output,
const BitSequence* data, size_t inlen ); const BitSequence* data, size_t inlen );
int luffa_full( hashState_luffa *state, BitSequence* output, int hashbitlen,
const BitSequence* data, size_t inlen );
#endif // LUFFA_FOR_SSE2_H___

View File

@@ -115,9 +115,8 @@ void allium_16way_hash( void *state, const void *input )
intrlv_4x128( vhashA, hash0, hash1, hash2, hash3, 256 ); intrlv_4x128( vhashA, hash0, hash1, hash2, hash3, 256 );
intrlv_4x128( vhashB, hash4, hash5, hash6, hash7, 256 ); intrlv_4x128( vhashB, hash4, hash5, hash6, hash7, 256 );
cube_4way_update_close( &ctx.cube, vhashA, vhashA, 32 ); cube_4way_full( &ctx.cube, vhashA, 256, vhashA, 32 );
cube_4way_init( &ctx.cube, 256, 16, 32 ); cube_4way_full( &ctx.cube, vhashB, 256, vhashB, 32 );
cube_4way_update_close( &ctx.cube, vhashB, vhashB, 32 );
dintrlv_4x128( hash0, hash1, hash2, hash3, vhashA, 256 ); dintrlv_4x128( hash0, hash1, hash2, hash3, vhashA, 256 );
dintrlv_4x128( hash4, hash5, hash6, hash7, vhashB, 256 ); dintrlv_4x128( hash4, hash5, hash6, hash7, vhashB, 256 );
@@ -125,10 +124,8 @@ void allium_16way_hash( void *state, const void *input )
intrlv_4x128( vhashA, hash8, hash9, hash10, hash11, 256 ); intrlv_4x128( vhashA, hash8, hash9, hash10, hash11, 256 );
intrlv_4x128( vhashB, hash12, hash13, hash14, hash15, 256 ); intrlv_4x128( vhashB, hash12, hash13, hash14, hash15, 256 );
cube_4way_init( &ctx.cube, 256, 16, 32 ); cube_4way_full( &ctx.cube, vhashA, 256, vhashA, 32 );
cube_4way_update_close( &ctx.cube, vhashA, vhashA, 32 ); cube_4way_full( &ctx.cube, vhashB, 256, vhashB, 32 );
cube_4way_init( &ctx.cube, 256, 16, 32 );
cube_4way_update_close( &ctx.cube, vhashB, vhashB, 32 );
dintrlv_4x128( hash8, hash9, hash10, hash11, vhashA, 256 ); dintrlv_4x128( hash8, hash9, hash10, hash11, vhashA, 256 );
dintrlv_4x128( hash12, hash13, hash14, hash15, vhashB, 256 ); dintrlv_4x128( hash12, hash13, hash14, hash15, vhashB, 256 );
@@ -169,7 +166,6 @@ void allium_16way_hash( void *state, const void *input )
skein256_8way_update( &ctx.skein, vhashB, 32 ); skein256_8way_update( &ctx.skein, vhashB, 32 );
skein256_8way_close( &ctx.skein, vhashB ); skein256_8way_close( &ctx.skein, vhashB );
dintrlv_8x64( hash0, hash1, hash2, hash3, hash4, hash5, hash6, hash7, dintrlv_8x64( hash0, hash1, hash2, hash3, hash4, hash5, hash6, hash7,
vhashA, 256 ); vhashA, 256 );
dintrlv_8x64( hash8, hash9, hash10, hash11, hash12, hash13, hash14, hash15, dintrlv_8x64( hash8, hash9, hash10, hash11, hash12, hash13, hash14, hash15,
@@ -179,77 +175,43 @@ void allium_16way_hash( void *state, const void *input )
intrlv_4x128( vhash, hash0, hash1, hash2, hash3, 256 ); intrlv_4x128( vhash, hash0, hash1, hash2, hash3, 256 );
groestl256_4way_update_close( &ctx.groestl, vhash, vhash, 256 ); groestl256_4way_full( &ctx.groestl, vhash, vhash, 256 );
dintrlv_4x128( state, state+32, state+64, state+96, vhash, 256 ); dintrlv_4x128( state, state+32, state+64, state+96, vhash, 256 );
intrlv_4x128( vhash, hash4, hash5, hash6, hash7, 256 ); intrlv_4x128( vhash, hash4, hash5, hash6, hash7, 256 );
groestl256_4way_init( &ctx.groestl, 32 ); groestl256_4way_full( &ctx.groestl, vhash, vhash, 256 );
groestl256_4way_update_close( &ctx.groestl, vhash, vhash, 256 );
dintrlv_4x128( state+128, state+160, state+192, state+224, vhash, 256 ); dintrlv_4x128( state+128, state+160, state+192, state+224, vhash, 256 );
intrlv_4x128( vhash, hash8, hash9, hash10, hash11, 256 ); intrlv_4x128( vhash, hash8, hash9, hash10, hash11, 256 );
groestl256_4way_init( &ctx.groestl, 32 ); groestl256_4way_full( &ctx.groestl, vhash, vhash, 256 );
groestl256_4way_update_close( &ctx.groestl, vhash, vhash, 256 );
dintrlv_4x128( state+256, state+288, state+320, state+352, vhash, 256 ); dintrlv_4x128( state+256, state+288, state+320, state+352, vhash, 256 );
intrlv_4x128( vhash, hash12, hash13, hash14, hash15, 256 ); intrlv_4x128( vhash, hash12, hash13, hash14, hash15, 256 );
groestl256_4way_init( &ctx.groestl, 32 ); groestl256_4way_full( &ctx.groestl, vhash, vhash, 256 );
groestl256_4way_update_close( &ctx.groestl, vhash, vhash, 256 );
dintrlv_4x128( state+384, state+416, state+448, state+480, vhash, 256 ); dintrlv_4x128( state+384, state+416, state+448, state+480, vhash, 256 );
#else #else
update_and_final_groestl256( &ctx.groestl, state, hash0, 256 ); groestl256_full( &ctx.groestl, state, hash0, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl, groestl256_full( &ctx.groestl, state+32, hash1, 256 );
sizeof(hashState_groestl256) ); groestl256_full( &ctx.groestl, state+64, hash2, 256 );
update_and_final_groestl256( &ctx.groestl, state+32, hash1, 256 ); groestl256_full( &ctx.groestl, state+96, hash3, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl, groestl256_full( &ctx.groestl, state+128, hash4, 256 );
sizeof(hashState_groestl256) ); groestl256_full( &ctx.groestl, state+160, hash5, 256 );
update_and_final_groestl256( &ctx.groestl, state+64, hash2, 256 ); groestl256_full( &ctx.groestl, state+192, hash6, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl, groestl256_full( &ctx.groestl, state+224, hash7, 256 );
sizeof(hashState_groestl256) ); groestl256_full( &ctx.groestl, state+256, hash8, 256 );
update_and_final_groestl256( &ctx.groestl, state+96, hash3, 256 ); groestl256_full( &ctx.groestl, state+288, hash9, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl, groestl256_full( &ctx.groestl, state+320, hash10, 256 );
sizeof(hashState_groestl256) ); groestl256_full( &ctx.groestl, state+352, hash11, 256 );
update_and_final_groestl256( &ctx.groestl, state+128, hash4, 256 ); groestl256_full( &ctx.groestl, state+384, hash12, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl, groestl256_full( &ctx.groestl, state+416, hash13, 256 );
sizeof(hashState_groestl256) ); groestl256_full( &ctx.groestl, state+448, hash14, 256 );
update_and_final_groestl256( &ctx.groestl, state+160, hash5, 256 ); groestl256_full( &ctx.groestl, state+480, hash15, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+192, hash6, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+224, hash7, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+256, hash8, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+288, hash9, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+320, hash10, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+352, hash11, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+384, hash12, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+416, hash13, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+448, hash14, 256 );
memcpy( &ctx.groestl, &allium_16way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, state+480, hash15, 256 );
#endif #endif
} }
@@ -263,37 +225,32 @@ int scanhash_allium_16way( struct work *work, uint32_t max_nonce,
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
uint32_t n = first_nonce; uint32_t n = first_nonce;
const uint32_t last_nonce = max_nonce - 16; const uint32_t last_nonce = max_nonce - 16;
const uint32_t Htarg = ptarget[7];
__m512i *noncev = (__m512i*)vdata + 19; // aligned __m512i *noncev = (__m512i*)vdata + 19; // aligned
int thr_id = mythr->id; // thr_id arg is deprecated const int thr_id = mythr->id;
const bool bench = opt_benchmark;
if ( opt_benchmark ) if ( bench ) ( (uint32_t*)ptarget )[7] = 0x0000ff;
( (uint32_t*)ptarget )[7] = 0x0000ff;
mm512_bswap32_intrlv80_16x32( vdata, pdata ); mm512_bswap32_intrlv80_16x32( vdata, pdata );
*noncev = _mm512_set_epi32( n+15, n+14, n+13, n+12, n+11, n+10, n+ 9, n+ 8,
n+ 7, n+ 6, n+ 5, n+ 4, n+ 3, n+ 2, n +1, n );
blake256_16way_init( &allium_16way_ctx.blake ); blake256_16way_init( &allium_16way_ctx.blake );
blake256_16way_update( &allium_16way_ctx.blake, vdata, 64 ); blake256_16way_update( &allium_16way_ctx.blake, vdata, 64 );
do { do {
*noncev = mm512_bswap_32( _mm512_set_epi32( n+15, n+14, n+13, n+12,
n+11, n+10, n+ 9, n+ 8,
n+ 7, n+ 6, n+ 5, n+ 4,
n+ 3, n+ 2, n +1, n ) );
allium_16way_hash( hash, vdata ); allium_16way_hash( hash, vdata );
pdata[19] = n;
for ( int lane = 0; lane < 16; lane++ ) if ( (hash+(lane<<3))[7] <= Htarg ) for ( int lane = 0; lane < 16; lane++ )
if ( unlikely( valid_hash( hash+(lane<<3), ptarget ) && !bench ) )
{ {
if ( fulltest( hash+(lane<<3), ptarget ) && !opt_benchmark ) pdata[19] = bswap_32( n + lane );
{ submit_solution( work, hash+(lane<<3), mythr );
pdata[19] = n + lane;
submit_lane_solution( work, hash+(lane<<3), mythr, lane );
}
} }
*noncev = _mm512_add_epi32( *noncev, m512_const1_32( 16 ) );
n += 16; n += 16;
} while ( (n < last_nonce) && !work_restart[thr_id].restart); } while ( likely( (n < last_nonce) && !work_restart[thr_id].restart) );
pdata[19] = n;
*hashes_done = n - first_nonce; *hashes_done = n - first_nonce;
return 0; return 0;
} }
@@ -324,7 +281,6 @@ void allium_8way_hash( void *hash, const void *input )
{ {
uint64_t vhashA[4*8] __attribute__ ((aligned (64))); uint64_t vhashA[4*8] __attribute__ ((aligned (64)));
uint64_t vhashB[4*8] __attribute__ ((aligned (64))); uint64_t vhashB[4*8] __attribute__ ((aligned (64)));
// uint64_t hash[4*8] __attribute__ ((aligned (64)));
uint64_t *hash0 = (uint64_t*)hash; uint64_t *hash0 = (uint64_t*)hash;
uint64_t *hash1 = (uint64_t*)hash+ 4; uint64_t *hash1 = (uint64_t*)hash+ 4;
uint64_t *hash2 = (uint64_t*)hash+ 8; uint64_t *hash2 = (uint64_t*)hash+ 8;
@@ -399,28 +355,14 @@ void allium_8way_hash( void *hash, const void *input )
dintrlv_4x64( hash0, hash1, hash2, hash3, vhashA, 256 ); dintrlv_4x64( hash0, hash1, hash2, hash3, vhashA, 256 );
dintrlv_4x64( hash4, hash5, hash6, hash7, vhashB, 256 ); dintrlv_4x64( hash4, hash5, hash6, hash7, vhashB, 256 );
update_and_final_groestl256( &ctx.groestl, hash0, hash0, 256 ); groestl256_full( &ctx.groestl, hash0, hash0, 256 );
memcpy( &ctx.groestl, &allium_8way_ctx.groestl, groestl256_full( &ctx.groestl, hash1, hash1, 256 );
sizeof(hashState_groestl256) ); groestl256_full( &ctx.groestl, hash2, hash2, 256 );
update_and_final_groestl256( &ctx.groestl, hash1, hash1, 256 ); groestl256_full( &ctx.groestl, hash3, hash3, 256 );
memcpy( &ctx.groestl, &allium_8way_ctx.groestl, groestl256_full( &ctx.groestl, hash4, hash4, 256 );
sizeof(hashState_groestl256) ); groestl256_full( &ctx.groestl, hash5, hash5, 256 );
update_and_final_groestl256( &ctx.groestl, hash2, hash2, 256 ); groestl256_full( &ctx.groestl, hash6, hash6, 256 );
memcpy( &ctx.groestl, &allium_8way_ctx.groestl, groestl256_full( &ctx.groestl, hash7, hash7, 256 );
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, hash3, hash3, 256 );
memcpy( &ctx.groestl, &allium_8way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, hash4, hash4, 256 );
memcpy( &ctx.groestl, &allium_8way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, hash5, hash5, 256 );
memcpy( &ctx.groestl, &allium_8way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, hash6, hash6, 256 );
memcpy( &ctx.groestl, &allium_8way_ctx.groestl,
sizeof(hashState_groestl256) );
update_and_final_groestl256( &ctx.groestl, hash7, hash7, 256 );
} }
int scanhash_allium_8way( struct work *work, uint32_t max_nonce, int scanhash_allium_8way( struct work *work, uint32_t max_nonce,
@@ -433,14 +375,10 @@ int scanhash_allium_8way( struct work *work, uint32_t max_nonce,
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 8; const uint32_t last_nonce = max_nonce - 8;
uint32_t n = first_nonce; uint32_t n = first_nonce;
const uint64_t Htarg = ptarget[3];
__m256i *noncev = (__m256i*)vdata + 19; // aligned __m256i *noncev = (__m256i*)vdata + 19; // aligned
const int thr_id = mythr->id; const int thr_id = mythr->id;
const bool bench = opt_benchmark; const bool bench = opt_benchmark;
if unlikely( bench )
( (uint32_t*)ptarget )[7] = 0x0000ff;
mm256_bswap32_intrlv80_8x32( vdata, pdata ); mm256_bswap32_intrlv80_8x32( vdata, pdata );
*noncev = _mm256_set_epi32( n+7, n+6, n+5, n+4, n+3, n+2, n+1, n ); *noncev = _mm256_set_epi32( n+7, n+6, n+5, n+4, n+3, n+2, n+1, n );
@@ -453,19 +391,15 @@ int scanhash_allium_8way( struct work *work, uint32_t max_nonce,
for ( int lane = 0; lane < 8; lane++ ) for ( int lane = 0; lane < 8; lane++ )
{ {
const uint64_t *lane_hash = hash + (lane<<2); const uint64_t *lane_hash = hash + (lane<<2);
if unlikely( lane_hash[3] <= Htarg ) if ( unlikely( valid_hash( lane_hash, ptarget ) && !bench ) )
{
if likely( ( lane_hash[3] < Htarg && !bench )
|| valid_hash( lane_hash, ptarget ) )
{ {
pdata[19] = bswap_32( n + lane ); pdata[19] = bswap_32( n + lane );
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
}
} }
} }
n += 8; n += 8;
*noncev = _mm256_add_epi32( *noncev, m256_const1_32( 8 ) ); *noncev = _mm256_add_epi32( *noncev, m256_const1_32( 8 ) );
} while likely( (n <= last_nonce) && !work_restart[thr_id].restart ); } while ( likely( (n <= last_nonce) && !work_restart[thr_id].restart ) );
pdata[19] = n; pdata[19] = n;
*hashes_done = n - first_nonce; *hashes_done = n - first_nonce;
return 0; return 0;

View File

@@ -1,4 +1,7 @@
#include "lyra2-gate.h" #include "lyra2-gate.h"
#if !( defined(ALLIUM_16WAY) || defined(ALLIUM_8WAY) || defined(ALLIUM_4WAY) )
#include <memory.h> #include <memory.h>
#include "algo/blake/sph_blake.h" #include "algo/blake/sph_blake.h"
#include "algo/keccak/sph_keccak.h" #include "algo/keccak/sph_keccak.h"
@@ -73,37 +76,35 @@ int scanhash_allium( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ) uint64_t *hashes_done, struct thr_info *mythr )
{ {
uint32_t _ALIGN(128) hash[8]; uint32_t _ALIGN(128) hash[8];
uint32_t _ALIGN(128) endiandata[20]; uint32_t _ALIGN(128) edata[20];
uint32_t *pdata = work->data; uint32_t *pdata = work->data;
uint32_t *ptarget = work->target; uint32_t *ptarget = work->target;
const uint32_t Htarg = ptarget[7];
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
uint32_t nonce = first_nonce; uint32_t nonce = first_nonce;
int thr_id = mythr->id; // thr_id arg is deprecated const int thr_id = mythr->id;
if ( opt_benchmark ) if ( opt_benchmark )
ptarget[7] = 0x3ffff; ptarget[7] = 0x3ffff;
for ( int i = 0; i < 19; i++ ) for ( int i = 0; i < 19; i++ )
be32enc( &endiandata[i], pdata[i] ); edata[i] = bswap_32( pdata[i] );
sph_blake256_init( &allium_ctx.blake ); sph_blake256_init( &allium_ctx.blake );
sph_blake256( &allium_ctx.blake, endiandata, 64 ); sph_blake256( &allium_ctx.blake, edata, 64 );
do { do {
be32enc( &endiandata[19], nonce ); edata[19] = nonce;
allium_hash( hash, endiandata ); allium_hash( hash, edata );
if ( hash[7] <= Htarg ) if ( valid_hash( hash, ptarget ) && !opt_benchmark )
if ( fulltest( hash, ptarget ) && !opt_benchmark )
{ {
pdata[19] = nonce; pdata[19] = bswap_32( nonce );
submit_solution( work, hash, mythr ); submit_solution( work, hash, mythr );
} }
nonce++; nonce++;
} while ( nonce < max_nonce && !work_restart[thr_id].restart ); } while ( nonce < max_nonce && !work_restart[thr_id].restart );
pdata[19] = nonce; pdata[19] = nonce;
*hashes_done = pdata[19] - first_nonce + 1; *hashes_done = pdata[19] - first_nonce;
return 0; return 0;
} }
#endif

View File

@@ -94,12 +94,12 @@ bool lyra2rev2_thread_init()
const int64_t ROW_LEN_BYTES = ROW_LEN_INT64 * 8; const int64_t ROW_LEN_BYTES = ROW_LEN_INT64 * 8;
int size = (int64_t)ROW_LEN_BYTES * 4; // nRows; int size = (int64_t)ROW_LEN_BYTES * 4; // nRows;
#if defined (LYRA2REV2_8WAY) #if defined (LYRA2REV2_16WAY)
l2v2_wholeMatrix = _mm_malloc( 2 * size, 64 ); // 2 way l2v2_wholeMatrix = _mm_malloc( 2 * size, 64 ); // 2 way
init_lyra2rev2_8way_ctx();; init_lyra2rev2_16way_ctx();;
#elif defined (LYRA2REV2_4WAY) #elif defined (LYRA2REV2_8WAY)
l2v2_wholeMatrix = _mm_malloc( size, 64 ); l2v2_wholeMatrix = _mm_malloc( size, 64 );
init_lyra2rev2_4way_ctx();; init_lyra2rev2_8way_ctx();;
#else #else
l2v2_wholeMatrix = _mm_malloc( size, 64 ); l2v2_wholeMatrix = _mm_malloc( size, 64 );
init_lyra2rev2_ctx(); init_lyra2rev2_ctx();
@@ -109,17 +109,17 @@ bool lyra2rev2_thread_init()
bool register_lyra2rev2_algo( algo_gate_t* gate ) bool register_lyra2rev2_algo( algo_gate_t* gate )
{ {
#if defined (LYRA2REV2_8WAY) #if defined (LYRA2REV2_16WAY)
gate->scanhash = (void*)&scanhash_lyra2rev2_16way;
gate->hash = (void*)&lyra2rev2_16way_hash;
#elif defined (LYRA2REV2_8WAY)
gate->scanhash = (void*)&scanhash_lyra2rev2_8way; gate->scanhash = (void*)&scanhash_lyra2rev2_8way;
gate->hash = (void*)&lyra2rev2_8way_hash; gate->hash = (void*)&lyra2rev2_8way_hash;
#elif defined (LYRA2REV2_4WAY)
gate->scanhash = (void*)&scanhash_lyra2rev2_4way;
gate->hash = (void*)&lyra2rev2_4way_hash;
#else #else
gate->scanhash = (void*)&scanhash_lyra2rev2; gate->scanhash = (void*)&scanhash_lyra2rev2;
gate->hash = (void*)&lyra2rev2_hash; gate->hash = (void*)&lyra2rev2_hash;
#endif #endif
gate->optimizations = SSE2_OPT | AES_OPT | AVX2_OPT | AVX512_OPT; gate->optimizations = SSE2_OPT | AVX2_OPT | AVX512_OPT;
gate->miner_thread_init = (void*)&lyra2rev2_thread_init; gate->miner_thread_init = (void*)&lyra2rev2_thread_init;
opt_target_factor = 256.0; opt_target_factor = 256.0;
return true; return true;
@@ -194,7 +194,7 @@ bool register_allium_algo( algo_gate_t* gate )
///////////////////////////////////////// /////////////////////////////////////////
bool phi2_has_roots; bool phi2_has_roots = false;
bool phi2_use_roots = false; bool phi2_use_roots = false;
int phi2_get_work_data_size() { return phi2_use_roots ? 144 : 128; } int phi2_get_work_data_size() { return phi2_use_roots ? 144 : 128; }
@@ -215,26 +215,23 @@ void phi2_build_extraheader( struct work* g_work, struct stratum_ctx* sctx )
size_t t; size_t t;
algo_gate.gen_merkle_root( merkle_tree, sctx ); algo_gate.gen_merkle_root( merkle_tree, sctx );
// Increment extranonce2
for ( t = 0; t < sctx->xnonce2_size && !( ++sctx->job.xnonce2[t] ); t++ );
// Assemble block header
algo_gate.build_block_header( g_work, le32dec( sctx->job.version ), algo_gate.build_block_header( g_work, le32dec( sctx->job.version ),
(uint32_t*) sctx->job.prevhash, (uint32_t*) merkle_tree, (uint32_t*) sctx->job.prevhash, (uint32_t*) merkle_tree,
le32dec( sctx->job.ntime ), le32dec(sctx->job.nbits) ); le32dec( sctx->job.ntime ), le32dec(sctx->job.nbits), NULL );
for ( t = 0; t < 16; t++ ) for ( t = 0; t < 16; t++ )
g_work->data[ 20+t ] = ((uint32_t*)sctx->job.extra)[t]; g_work->data[ 20+t ] = ((uint32_t*)sctx->job.extra)[t];
} }
bool register_phi2_algo( algo_gate_t* gate ) bool register_phi2_algo( algo_gate_t* gate )
{ {
// init_phi2_ctx(); gate->optimizations = SSE2_OPT | AES_OPT | AVX2_OPT | AVX512_OPT | VAES_OPT;
gate->optimizations = SSE2_OPT | AES_OPT | AVX2_OPT | AVX512_OPT;
gate->get_work_data_size = (void*)&phi2_get_work_data_size; gate->get_work_data_size = (void*)&phi2_get_work_data_size;
gate->decode_extra_data = (void*)&phi2_decode_extra_data; gate->decode_extra_data = (void*)&phi2_decode_extra_data;
gate->build_extraheader = (void*)&phi2_build_extraheader; gate->build_extraheader = (void*)&phi2_build_extraheader;
opt_target_factor = 256.0; opt_target_factor = 256.0;
#if defined(PHI2_4WAY) #if defined(PHI2_8WAY)
gate->scanhash = (void*)&scanhash_phi2_8way;
#elif defined(PHI2_4WAY)
gate->scanhash = (void*)&scanhash_phi2_4way; gate->scanhash = (void*)&scanhash_phi2_4way;
#else #else
init_phi2_ctx(); init_phi2_ctx();

View File

@@ -51,28 +51,29 @@ bool init_lyra2rev3_ctx();
////////////////////////////////// //////////////////////////////////
#if defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512DQ__) && defined(__AVX512BW__) #if defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512DQ__) && defined(__AVX512BW__)
#define LYRA2REV2_8WAY 1 #define LYRA2REV2_16WAY 1
#elif defined(__AVX2__) #elif defined(__AVX2__)
#define LYRA2REV2_4WAY 1 #define LYRA2REV2_8WAY 1
#endif #endif
extern __thread uint64_t* l2v2_wholeMatrix; extern __thread uint64_t* l2v2_wholeMatrix;
bool register_lyra2rev2_algo( algo_gate_t* gate ); bool register_lyra2rev2_algo( algo_gate_t* gate );
#if defined(LYRA2REV2_8WAY) #if defined(LYRA2REV2_16WAY)
void lyra2rev2_16way_hash( void *state, const void *input );
int scanhash_lyra2rev2_16way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr );
bool init_lyra2rev2_16way_ctx();
#elif defined(LYRA2REV2_8WAY)
void lyra2rev2_8way_hash( void *state, const void *input ); void lyra2rev2_8way_hash( void *state, const void *input );
int scanhash_lyra2rev2_8way( struct work *work, uint32_t max_nonce, int scanhash_lyra2rev2_8way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ); uint64_t *hashes_done, struct thr_info *mythr );
bool init_lyra2rev2_8way_ctx(); bool init_lyra2rev2_8way_ctx();
#elif defined(LYRA2REV2_4WAY)
void lyra2rev2_4way_hash( void *state, const void *input );
int scanhash_lyra2rev2_4way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr );
bool init_lyra2rev2_4way_ctx();
#else #else
@@ -185,19 +186,26 @@ bool init_allium_ctx();
///////////////////////////////////////// /////////////////////////////////////////
#if defined(__AVX2__) && defined(__AES__) #if defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512DQ__) && defined(__AVX512BW__)
// #define PHI2_4WAY #define PHI2_8WAY 1
#elif defined(__AVX2__) && defined(__AES__)
#define PHI2_4WAY 1
#endif #endif
bool phi2_has_roots; extern bool phi2_has_roots;
bool register_phi2_algo( algo_gate_t* gate ); bool register_phi2_algo( algo_gate_t* gate );
#if defined(PHI2_4WAY) #if defined(PHI2_8WAY)
void phi2_8way_hash( void *state, const void *input );
int scanhash_phi2_8way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr );
#elif defined(PHI2_4WAY)
void phi2_hash_4way( void *state, const void *input ); void phi2_hash_4way( void *state, const void *input );
int scanhash_phi2_4way( struct work *work, uint32_t max_nonce, int scanhash_phi2_4way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ); uint64_t *hashes_done, struct thr_info *mythr );
//void init_phi2_ctx();
#else #else

View File

@@ -76,7 +76,7 @@ int scanhash_lyra2h_4way( struct work *work, uint32_t max_nonce,
&& !opt_benchmark ) && !opt_benchmark )
{ {
pdata[19] = n+i; pdata[19] = n+i;
submit_lane_solution( work, hash+(i<<3), mythr, i ); submit_solution( work, hash+(i<<3), mythr );
} }
n += 4; n += 4;
} while ( (n < max_nonce-4) && !work_restart[thr_id].restart); } while ( (n < max_nonce-4) && !work_restart[thr_id].restart);

View File

@@ -1,4 +1,7 @@
#include "lyra2-gate.h" #include "lyra2-gate.h"
#if !( defined(LYRA2H_8WAY) || defined(LYRA2H_4WAY) )
#include <memory.h> #include <memory.h>
#include <mm_malloc.h> #include <mm_malloc.h>
#include "lyra2.h" #include "lyra2.h"
@@ -71,3 +74,4 @@ int scanhash_lyra2h( struct work *work, uint32_t max_nonce,
*hashes_done = pdata[19] - first_nonce + 1; *hashes_done = pdata[19] - first_nonce + 1;
return 0; return 0;
} }
#endif

View File

@@ -7,23 +7,227 @@
#include "algo/cubehash/cubehash_sse2.h" #include "algo/cubehash/cubehash_sse2.h"
#include "algo/cubehash/cube-hash-2way.h" #include "algo/cubehash/cube-hash-2way.h"
#if defined (LYRA2REV2_8WAY)
#if defined (LYRA2REV2_16WAY)
typedef struct {
blake256_16way_context blake;
keccak256_8way_context keccak;
cubehashParam cube;
skein256_8way_context skein;
bmw256_16way_context bmw;
} lyra2v2_16way_ctx_holder __attribute__ ((aligned (64)));
static lyra2v2_16way_ctx_holder l2v2_16way_ctx;
bool init_lyra2rev2_16way_ctx()
{
keccak256_8way_init( &l2v2_16way_ctx.keccak );
cubehashInit( &l2v2_16way_ctx.cube, 256, 16, 32 );
skein256_8way_init( &l2v2_16way_ctx.skein );
bmw256_16way_init( &l2v2_16way_ctx.bmw );
return true;
}
void lyra2rev2_16way_hash( void *state, const void *input )
{
uint32_t vhash[8*16] __attribute__ ((aligned (128)));
uint32_t hash0[8] __attribute__ ((aligned (64)));
uint32_t hash1[8] __attribute__ ((aligned (64)));
uint32_t hash2[8] __attribute__ ((aligned (64)));
uint32_t hash3[8] __attribute__ ((aligned (64)));
uint32_t hash4[8] __attribute__ ((aligned (64)));
uint32_t hash5[8] __attribute__ ((aligned (64)));
uint32_t hash6[8] __attribute__ ((aligned (64)));
uint32_t hash7[8] __attribute__ ((aligned (64)));
uint32_t hash8[8] __attribute__ ((aligned (64)));
uint32_t hash9[8] __attribute__ ((aligned (64)));
uint32_t hash10[8] __attribute__ ((aligned (64)));
uint32_t hash11[8] __attribute__ ((aligned (64)));
uint32_t hash12[8] __attribute__ ((aligned (64)));
uint32_t hash13[8] __attribute__ ((aligned (64)));
uint32_t hash14[8] __attribute__ ((aligned (64)));
uint32_t hash15[8] __attribute__ ((aligned (64)));
lyra2v2_16way_ctx_holder ctx __attribute__ ((aligned (64)));
memcpy( &ctx, &l2v2_16way_ctx, sizeof(l2v2_16way_ctx) );
blake256_16way_update( &ctx.blake, input + (64<<4), 16 );
blake256_16way_close( &ctx.blake, vhash );
dintrlv_16x32( hash0, hash1, hash2, hash3,
hash4, hash5, hash6, hash7,
hash8, hash9, hash10, hash11,
hash12, hash13, hash14, hash15, vhash, 256 );
intrlv_8x64( vhash, hash0, hash1, hash2, hash3,
hash4, hash5, hash6, hash7, 256 );
keccak256_8way_update( &ctx.keccak, vhash, 32 );
keccak256_8way_close( &ctx.keccak, vhash );
dintrlv_8x64( hash0, hash1, hash2, hash3,
hash4, hash5, hash6, hash7, vhash, 256 );
intrlv_8x64( vhash, hash8, hash9, hash10, hash11,
hash12, hash13, hash14, hash15, 256 );
keccak256_8way_init( &ctx.keccak );
keccak256_8way_update( &ctx.keccak, vhash, 32 );
keccak256_8way_close( &ctx.keccak, vhash );
dintrlv_8x64( hash8, hash9, hash10, hash11,
hash12, hash13, hash14, hash5, vhash, 256 );
cubehash_full( &ctx.cube, (byte*) hash0, 256, (const byte*) hash0, 32 );
cubehash_full( &ctx.cube, (byte*) hash1, 256, (const byte*) hash1, 32 );
cubehash_full( &ctx.cube, (byte*) hash2, 256, (const byte*) hash2, 32 );
cubehash_full( &ctx.cube, (byte*) hash3, 256, (const byte*) hash3, 32 );
cubehash_full( &ctx.cube, (byte*) hash4, 256, (const byte*) hash4, 32 );
cubehash_full( &ctx.cube, (byte*) hash5, 256, (const byte*) hash5, 32 );
cubehash_full( &ctx.cube, (byte*) hash6, 256, (const byte*) hash6, 32 );
cubehash_full( &ctx.cube, (byte*) hash7, 256, (const byte*) hash7, 32 );
cubehash_full( &ctx.cube, (byte*) hash8, 256, (const byte*) hash8, 32 );
cubehash_full( &ctx.cube, (byte*) hash9, 256, (const byte*) hash9, 32 );
cubehash_full( &ctx.cube, (byte*) hash10, 256, (const byte*) hash10, 32 );
cubehash_full( &ctx.cube, (byte*) hash11, 256, (const byte*) hash11, 32 );
cubehash_full( &ctx.cube, (byte*) hash12, 256, (const byte*) hash12, 32 );
cubehash_full( &ctx.cube, (byte*) hash13, 256, (const byte*) hash13, 32 );
cubehash_full( &ctx.cube, (byte*) hash14, 256, (const byte*) hash14, 32 );
cubehash_full( &ctx.cube, (byte*) hash15, 256, (const byte*) hash15, 32 );
intrlv_2x256( vhash, hash0, hash1, 256 );
LYRA2REV2_2WAY( l2v2_wholeMatrix, vhash, 32, vhash, 32, 1, 4, 4 );
dintrlv_2x256( hash0, hash1, vhash, 256 );
intrlv_2x256( vhash, hash2, hash3, 256 );
LYRA2REV2_2WAY( l2v2_wholeMatrix, vhash, 32, vhash, 32, 1, 4, 4 );
dintrlv_2x256( hash2, hash3, vhash, 256 );
intrlv_2x256( vhash, hash4, hash5, 256 );
LYRA2REV2_2WAY( l2v2_wholeMatrix, vhash, 32, vhash, 32, 1, 4, 4 );
dintrlv_2x256( hash4, hash5, vhash, 256 );
intrlv_2x256( vhash, hash6, hash7, 256 );
LYRA2REV2_2WAY( l2v2_wholeMatrix, vhash, 32, vhash, 32, 1, 4, 4 );
dintrlv_2x256( hash6, hash7, vhash, 256 );
intrlv_2x256( vhash, hash8, hash9, 256 );
LYRA2REV2_2WAY( l2v2_wholeMatrix, vhash, 32, vhash, 32, 1, 4, 4 );
dintrlv_2x256( hash8, hash9, vhash, 256 );
intrlv_2x256( vhash, hash10, hash11, 256 );
LYRA2REV2_2WAY( l2v2_wholeMatrix, vhash, 32, vhash, 32, 1, 4, 4 );
dintrlv_2x256( hash10, hash11, vhash, 256 );
intrlv_2x256( vhash, hash12, hash13, 256 );
LYRA2REV2_2WAY( l2v2_wholeMatrix, vhash, 32, vhash, 32, 1, 4, 4 );
dintrlv_2x256( hash12, hash13, vhash, 256 );
intrlv_2x256( vhash, hash14, hash15, 256 );
LYRA2REV2_2WAY( l2v2_wholeMatrix, vhash, 32, vhash, 32, 1, 4, 4 );
dintrlv_2x256( hash14, hash15, vhash, 256 );
intrlv_8x64( vhash, hash0, hash1, hash2, hash3,
hash4, hash5, hash6, hash7, 256 );
skein256_8way_update( &ctx.skein, vhash, 32 );
skein256_8way_close( &ctx.skein, vhash );
dintrlv_8x64( hash0, hash1, hash2, hash3,
hash4, hash5, hash6, hash7, vhash, 256 );
intrlv_8x64( vhash, hash8, hash9, hash10, hash11, hash12,
hash13, hash14, hash15, 256 );
skein256_8way_init( &ctx.skein );
skein256_8way_update( &ctx.skein, vhash, 32 );
skein256_8way_close( &ctx.skein, vhash );
dintrlv_8x64( hash8, hash9, hash10, hash11,
hash12, hash13, hash14, hash15, vhash, 256 );
cubehash_full( &ctx.cube, (byte*) hash0, 256, (const byte*) hash0, 32 );
cubehash_full( &ctx.cube, (byte*) hash1, 256, (const byte*) hash1, 32 );
cubehash_full( &ctx.cube, (byte*) hash2, 256, (const byte*) hash2, 32 );
cubehash_full( &ctx.cube, (byte*) hash3, 256, (const byte*) hash3, 32 );
cubehash_full( &ctx.cube, (byte*) hash4, 256, (const byte*) hash4, 32 );
cubehash_full( &ctx.cube, (byte*) hash5, 256, (const byte*) hash5, 32 );
cubehash_full( &ctx.cube, (byte*) hash6, 256, (const byte*) hash6, 32 );
cubehash_full( &ctx.cube, (byte*) hash7, 256, (const byte*) hash7, 32 );
cubehash_full( &ctx.cube, (byte*) hash8, 256, (const byte*) hash8, 32 );
cubehash_full( &ctx.cube, (byte*) hash9, 256, (const byte*) hash9, 32 );
cubehash_full( &ctx.cube, (byte*) hash10, 256, (const byte*) hash10, 32 );
cubehash_full( &ctx.cube, (byte*) hash11, 256, (const byte*) hash11, 32 );
cubehash_full( &ctx.cube, (byte*) hash12, 256, (const byte*) hash12, 32 );
cubehash_full( &ctx.cube, (byte*) hash13, 256, (const byte*) hash13, 32 );
cubehash_full( &ctx.cube, (byte*) hash14, 256, (const byte*) hash14, 32 );
cubehash_full( &ctx.cube, (byte*) hash15, 256, (const byte*) hash15, 32 );
intrlv_16x32( vhash, hash0, hash1, hash2, hash3,
hash4, hash5, hash6, hash7,
hash8, hash9, hash10, hash11,
hash12, hash13, hash14, hash15, 256 );
bmw256_16way_update( &ctx.bmw, vhash, 32 );
bmw256_16way_close( &ctx.bmw, state );
}
int scanhash_lyra2rev2_16way( struct work *work, const uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr )
{
uint32_t hash[8*16] __attribute__ ((aligned (128)));
uint32_t vdata[20*16] __attribute__ ((aligned (64)));
uint32_t *hashd7 = &hash[7*16];
uint32_t lane_hash[8] __attribute__ ((aligned (32)));
uint32_t *pdata = work->data;
uint32_t *ptarget = work->target;
const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 16;
uint32_t n = first_nonce;
const uint32_t targ32 = ptarget[7];
__m512i *noncev = (__m512i*)vdata + 19;
const int thr_id = mythr->id;
const bool bench = opt_benchmark;
if ( bench ) ptarget[7] = 0x0000ff;
mm512_bswap32_intrlv80_16x32( vdata, pdata );
*noncev = _mm512_set_epi32( n+15, n+14, n+13, n+12, n+11, n+10, n+ 9, n+ 8,
n+ 7, n+ 6, n+ 5, n+ 4, n+ 3, n+ 2, n+ 1, n );
blake256_16way_init( &l2v2_16way_ctx.blake );
blake256_16way_update( &l2v2_16way_ctx.blake, vdata, 64 );
do
{
lyra2rev2_16way_hash( hash, vdata );
for ( int lane = 0; lane < 16; lane++ )
if ( unlikely( hashd7[lane] <= targ32 ) )
{
extr_lane_16x32( lane_hash, hash, lane, 256 );
if ( likely( valid_hash( lane_hash, ptarget ) && !bench ) )
{
pdata[19] = bswap_32( n + lane );
submit_solution( work, lane_hash, mythr );
}
}
*noncev = _mm512_add_epi32( *noncev, m512_const1_32( 16 ) );
n += 16;
} while ( likely( (n < last_nonce) && !work_restart[thr_id].restart ) );
pdata[19] = n;
*hashes_done = n - first_nonce;
return 0;
}
#elif defined (LYRA2REV2_8WAY)
typedef struct { typedef struct {
blake256_8way_context blake; blake256_8way_context blake;
keccak256_8way_context keccak; keccak256_4way_context keccak;
cube_4way_context cube; cubehashParam cube;
skein256_8way_context skein; skein256_4way_context skein;
bmw256_8way_context bmw; bmw256_8way_context bmw;
} lyra2v2_8way_ctx_holder __attribute__ ((aligned (64))); } lyra2v2_8way_ctx_holder __attribute__ ((aligned (64)));
static lyra2v2_8way_ctx_holder l2v2_8way_ctx; static lyra2v2_8way_ctx_holder l2v2_8way_ctx;
bool init_lyra2rev2_8way_ctx() bool init_lyra2rev2_8way_ctx()
{ {
keccak256_8way_init( &l2v2_8way_ctx.keccak ); keccak256_4way_init( &l2v2_8way_ctx.keccak );
cube_4way_init( &l2v2_8way_ctx.cube, 256, 16, 32 ); cubehashInit( &l2v2_8way_ctx.cube, 256, 16, 32 );
skein256_8way_init( &l2v2_8way_ctx.skein ); skein256_4way_init( &l2v2_8way_ctx.skein );
bmw256_8way_init( &l2v2_8way_ctx.bmw ); bmw256_8way_init( &l2v2_8way_ctx.bmw );
return true; return true;
} }
@@ -31,8 +235,6 @@ bool init_lyra2rev2_8way_ctx()
void lyra2rev2_8way_hash( void *state, const void *input ) void lyra2rev2_8way_hash( void *state, const void *input )
{ {
uint32_t vhash[8*8] __attribute__ ((aligned (128))); uint32_t vhash[8*8] __attribute__ ((aligned (128)));
uint32_t vhashA[8*8] __attribute__ ((aligned (64)));
uint32_t vhashB[8*8] __attribute__ ((aligned (64)));
uint32_t hash0[8] __attribute__ ((aligned (64))); uint32_t hash0[8] __attribute__ ((aligned (64)));
uint32_t hash1[8] __attribute__ ((aligned (64))); uint32_t hash1[8] __attribute__ ((aligned (64)));
uint32_t hash2[8] __attribute__ ((aligned (64))); uint32_t hash2[8] __attribute__ ((aligned (64)));
@@ -47,103 +249,113 @@ void lyra2rev2_8way_hash( void *state, const void *input )
blake256_8way_update( &ctx.blake, input + (64<<3), 16 ); blake256_8way_update( &ctx.blake, input + (64<<3), 16 );
blake256_8way_close( &ctx.blake, vhash ); blake256_8way_close( &ctx.blake, vhash );
rintrlv_8x32_8x64( vhashA, vhash, 256 ); dintrlv_8x32( hash0, hash1, hash2, hash3,
hash4, hash5, hash6, hash7, vhash, 256 );
keccak256_8way_update( &ctx.keccak, vhashA, 32 ); intrlv_4x64( vhash, hash0, hash1, hash2, hash3, 256 );
keccak256_8way_close( &ctx.keccak, vhash ); keccak256_4way_update( &ctx.keccak, vhash, 32 );
keccak256_4way_close( &ctx.keccak, vhash );
dintrlv_4x64( hash0, hash1, hash2, hash3, vhash, 256 );
intrlv_4x64( vhash, hash4, hash5, hash6, hash7, 256 );
keccak256_4way_init( &ctx.keccak );
keccak256_4way_update( &ctx.keccak, vhash, 32 );
keccak256_4way_close( &ctx.keccak, vhash );
dintrlv_4x64( hash4, hash5, hash6, hash7, vhash, 256 );
rintrlv_8x64_4x128( vhashA, vhashB, vhash, 256 ); cubehash_full( &ctx.cube, (byte*) hash0, 256, (const byte*) hash0, 32 );
cubehash_full( &ctx.cube, (byte*) hash1, 256, (const byte*) hash1, 32 );
cubehash_full( &ctx.cube, (byte*) hash2, 256, (const byte*) hash2, 32 );
cubehash_full( &ctx.cube, (byte*) hash3, 256, (const byte*) hash3, 32 );
cubehash_full( &ctx.cube, (byte*) hash4, 256, (const byte*) hash4, 32 );
cubehash_full( &ctx.cube, (byte*) hash5, 256, (const byte*) hash5, 32 );
cubehash_full( &ctx.cube, (byte*) hash6, 256, (const byte*) hash6, 32 );
cubehash_full( &ctx.cube, (byte*) hash7, 256, (const byte*) hash7, 32 );
cube_4way_update_close( &ctx.cube, vhashA, vhashA, 32 );
cube_4way_init( &ctx.cube, 256, 16, 32 );
cube_4way_update_close( &ctx.cube, vhashB, vhashB, 32 );
dintrlv_4x128( hash0, hash1, hash2, hash3, vhashA, 256 ); LYRA2REV2( l2v2_wholeMatrix, hash0, 32, hash0, 32, hash0, 32, 1, 4, 4 );
dintrlv_4x128( hash4, hash5, hash6, hash7, vhashB, 256 ); LYRA2REV2( l2v2_wholeMatrix, hash1, 32, hash1, 32, hash1, 32, 1, 4, 4 );
LYRA2REV2( l2v2_wholeMatrix, hash2, 32, hash2, 32, hash2, 32, 1, 4, 4 );
intrlv_2x256( vhash, hash0, hash1, 256 ); LYRA2REV2( l2v2_wholeMatrix, hash3, 32, hash3, 32, hash3, 32, 1, 4, 4 );
LYRA2REV2_2WAY( l2v2_wholeMatrix, vhash, 32, vhash, 32, 1, 4, 4 ); LYRA2REV2( l2v2_wholeMatrix, hash4, 32, hash4, 32, hash4, 32, 1, 4, 4 );
dintrlv_2x256( hash0, hash1, vhash, 256 ); LYRA2REV2( l2v2_wholeMatrix, hash5, 32, hash5, 32, hash5, 32, 1, 4, 4 );
intrlv_2x256( vhash, hash2, hash3, 256 ); LYRA2REV2( l2v2_wholeMatrix, hash6, 32, hash6, 32, hash6, 32, 1, 4, 4 );
LYRA2REV2_2WAY( l2v2_wholeMatrix, vhash, 32, vhash, 32, 1, 4, 4 ); LYRA2REV2( l2v2_wholeMatrix, hash7, 32, hash7, 32, hash7, 32, 1, 4, 4 );
dintrlv_2x256( hash2, hash3, vhash, 256 );
intrlv_2x256( vhash, hash4, hash5, 256 );
LYRA2REV2_2WAY( l2v2_wholeMatrix, vhash, 32, vhash, 32, 1, 4, 4 );
dintrlv_2x256( hash4, hash5, vhash, 256 );
intrlv_2x256( vhash, hash6, hash7, 256 );
LYRA2REV2_2WAY( l2v2_wholeMatrix, vhash, 32, vhash, 32, 1, 4, 4 );
dintrlv_2x256( hash6, hash7, vhash, 256 );
intrlv_8x64( vhash, hash0, hash1, hash2, hash3, hash4, hash5, hash6,
hash7, 256 );
skein256_8way_update( &ctx.skein, vhash, 32 );
skein256_8way_close( &ctx.skein, vhash );
rintrlv_8x64_4x128( vhashA, vhashB, vhash, 256 );
cube_4way_init( &ctx.cube, 256, 16, 32 );
cube_4way_update_close( &ctx.cube, vhashA, vhashA, 32 );
cube_4way_init( &ctx.cube, 256, 16, 32 );
cube_4way_update_close( &ctx.cube, vhashB, vhashB, 32 );
dintrlv_4x128( hash0, hash1, hash2, hash3, vhashA, 256 ); intrlv_4x64( vhash, hash0, hash1, hash2, hash3, 256 );
dintrlv_4x128( hash4, hash5, hash6, hash7, vhashB, 256 ); skein256_4way_update( &ctx.skein, vhash, 32 );
skein256_4way_close( &ctx.skein, vhash );
dintrlv_4x64( hash0, hash1, hash2, hash3, vhash, 256 );
intrlv_4x64( vhash, hash4, hash5, hash6, hash7, 256 );
skein256_4way_init( &ctx.skein );
skein256_4way_update( &ctx.skein, vhash, 32 );
skein256_4way_close( &ctx.skein, vhash );
dintrlv_4x64( hash4, hash5, hash6, hash7, vhash, 256 );
intrlv_8x32( vhash, hash0, hash1, hash2, hash3, hash4, hash5, hash6, cubehash_full( &ctx.cube, (byte*) hash0, 256, (const byte*) hash0, 32 );
hash7, 256 ); cubehash_full( &ctx.cube, (byte*) hash1, 256, (const byte*) hash1, 32 );
cubehash_full( &ctx.cube, (byte*) hash2, 256, (const byte*) hash2, 32 );
cubehash_full( &ctx.cube, (byte*) hash3, 256, (const byte*) hash3, 32 );
cubehash_full( &ctx.cube, (byte*) hash4, 256, (const byte*) hash4, 32 );
cubehash_full( &ctx.cube, (byte*) hash5, 256, (const byte*) hash5, 32 );
cubehash_full( &ctx.cube, (byte*) hash6, 256, (const byte*) hash6, 32 );
cubehash_full( &ctx.cube, (byte*) hash7, 256, (const byte*) hash7, 32 );
intrlv_8x32( vhash, hash0, hash1, hash2, hash3,
hash4, hash5, hash6, hash7, 256 );
bmw256_8way_update( &ctx.bmw, vhash, 32 ); bmw256_8way_update( &ctx.bmw, vhash, 32 );
bmw256_8way_close( &ctx.bmw, state ); bmw256_8way_close( &ctx.bmw, state );
} }
int scanhash_lyra2rev2_8way( struct work *work, uint32_t max_nonce, int scanhash_lyra2rev2_8way( struct work *work, const uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ) uint64_t *hashes_done, struct thr_info *mythr )
{ {
uint32_t hash[8*8] __attribute__ ((aligned (128))); uint32_t hash[8*8] __attribute__ ((aligned (128)));
uint32_t vdata[20*8] __attribute__ ((aligned (64))); uint32_t vdata[20*8] __attribute__ ((aligned (64)));
uint32_t *hash7 = &(hash[7<<3]); uint32_t *hashd7 = &hash[7*8];
uint32_t lane_hash[8] __attribute__ ((aligned (64))); uint32_t lane_hash[8] __attribute__ ((aligned (32)));
uint32_t *pdata = work->data; uint32_t *pdata = work->data;
uint32_t *ptarget = work->target; uint32_t *ptarget = work->target;
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 8; const uint32_t last_nonce = max_nonce - 8;
uint32_t n = first_nonce; uint32_t n = first_nonce;
const uint32_t Htarg = ptarget[7]; const uint32_t targ32 = ptarget[7];
__m256i *noncev = (__m256i*)vdata + 19; // aligned __m256i *noncev = (__m256i*)vdata + 19;
int thr_id = mythr->id; const int thr_id = mythr->id;
const bool bench = opt_benchmark;
if ( opt_benchmark ) if ( bench ) ptarget[7] = 0x0000ff;
( (uint32_t*)ptarget )[7] = 0x0000ff;
mm256_bswap32_intrlv80_8x32( vdata, pdata ); mm256_bswap32_intrlv80_8x32( vdata, pdata );
*noncev = _mm256_set_epi32( n+7, n+6, n+5, n+4, n+3, n+2, n+1, n );
blake256_8way_init( &l2v2_8way_ctx.blake ); blake256_8way_init( &l2v2_8way_ctx.blake );
blake256_8way_update( &l2v2_8way_ctx.blake, vdata, 64 ); blake256_8way_update( &l2v2_8way_ctx.blake, vdata, 64 );
do do
{ {
*noncev = mm256_bswap_32( _mm256_set_epi32( n+7, n+6, n+5, n+4,
n+3, n+2, n+1, n ) );
lyra2rev2_8way_hash( hash, vdata ); lyra2rev2_8way_hash( hash, vdata );
pdata[19] = n;
for ( int lane = 0; lane < 8; lane++ ) if ( hash7[lane] <= Htarg ) for ( int lane = 0; lane < 8; lane++ )
if ( unlikely( hashd7[lane] <= targ32 ) )
{ {
extr_lane_8x32( lane_hash, hash, lane, 256 ); extr_lane_8x32( lane_hash, hash, lane, 256 );
if ( fulltest( lane_hash, ptarget ) && !opt_benchmark ) if ( likely( valid_hash( lane_hash, ptarget ) && !bench ) )
{ {
pdata[19] = n + lane; pdata[19] = bswap_32( n + lane );
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
*noncev = _mm256_add_epi32( *noncev, m256_const1_32( 8 ) );
n += 8; n += 8;
} while ( (n < last_nonce) && !work_restart[thr_id].restart); } while ( likely( (n < last_nonce) && !work_restart[thr_id].restart ) );
pdata[19] = n;
*hashes_done = n - first_nonce; *hashes_done = n - first_nonce;
return 0; return 0;
} }
#endif
/*
#elif defined (LYRA2REV2_4WAY) #elif defined (LYRA2REV2_4WAY)
typedef struct { typedef struct {
@@ -226,15 +438,16 @@ int scanhash_lyra2rev2_4way( struct work *work, uint32_t max_nonce,
{ {
uint32_t hash[8*4] __attribute__ ((aligned (64))); uint32_t hash[8*4] __attribute__ ((aligned (64)));
uint32_t vdata[20*4] __attribute__ ((aligned (64))); uint32_t vdata[20*4] __attribute__ ((aligned (64)));
uint32_t *hash7 = &(hash[7<<2]); uint32_t *hashd7 = &(hash[7<<2]);
uint32_t lane_hash[8] __attribute__ ((aligned (32))); uint32_t lane_hash[8] __attribute__ ((aligned (32)));
uint32_t *pdata = work->data; uint32_t *pdata = work->data;
uint32_t *ptarget = work->target; uint32_t *ptarget = work->target;
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 4;
uint32_t n = first_nonce; uint32_t n = first_nonce;
const uint32_t Htarg = ptarget[7]; const uint32_t targ32 = ptarget[7];
__m128i *noncev = (__m128i*)vdata + 19; // aligned __m128i *noncev = (__m128i*)vdata + 19;
int thr_id = mythr->id; // thr_id arg is deprecated int thr_id = mythr->id;
if ( opt_benchmark ) if ( opt_benchmark )
( (uint32_t*)ptarget )[7] = 0x0000ff; ( (uint32_t*)ptarget )[7] = 0x0000ff;
@@ -249,21 +462,22 @@ int scanhash_lyra2rev2_4way( struct work *work, uint32_t max_nonce,
*noncev = mm128_bswap_32( _mm_set_epi32( n+3, n+2, n+1, n ) ); *noncev = mm128_bswap_32( _mm_set_epi32( n+3, n+2, n+1, n ) );
lyra2rev2_4way_hash( hash, vdata ); lyra2rev2_4way_hash( hash, vdata );
pdata[19] = n;
for ( int lane = 0; lane < 4; lane++ ) if ( hash7[lane] <= Htarg ) for ( int lane = 0; lane < 4; lane++ ) if ( hashd7[lane] <= targ32 )
{ {
extr_lane_4x32( lane_hash, hash, lane, 256 ); extr_lane_4x32( lane_hash, hash, lane, 256 );
if ( fulltest( lane_hash, ptarget ) && !opt_benchmark ) if ( valid_hash( lane_hash, ptarget ) && !opt_benchmark )
{ {
pdata[19] = n + lane; pdata[19] = n + lane;
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
n += 4; n += 4;
} while ( (n < max_nonce-4) && !work_restart[thr_id].restart); } while ( (n < last_nonce) && !work_restart[thr_id].restart);
*hashes_done = n - first_nonce + 1; pdata[19] = n;
*hashes_done = n - first_nonce;
return 0; return 0;
} }
#endif #endif
*/

View File

@@ -1,4 +1,7 @@
#include "lyra2-gate.h" #include "lyra2-gate.h"
#if !( defined(LYRA2REV2_16WAY) || defined(LYRA2REV2_8WAY) || defined(LYRA2REV2_4WAY) )
#include <memory.h> #include <memory.h>
#include "algo/blake/sph_blake.h" #include "algo/blake/sph_blake.h"
#include "algo/cubehash/sph_cubehash.h" #include "algo/cubehash/sph_cubehash.h"
@@ -96,7 +99,7 @@ int scanhash_lyra2rev2( struct work *work,
lyra2rev2_hash(hash, endiandata); lyra2rev2_hash(hash, endiandata);
if (hash[7] <= Htarg ) if (hash[7] <= Htarg )
if( fulltest( hash, ptarget ) && !opt_benchmark ) if( valid_hash( hash, ptarget ) && !opt_benchmark )
{ {
pdata[19] = nonce; pdata[19] = nonce;
submit_solution( work, hash, mythr ); submit_solution( work, hash, mythr );
@@ -107,4 +110,4 @@ int scanhash_lyra2rev2( struct work *work,
*hashes_done = pdata[19] - first_nonce + 1; *hashes_done = pdata[19] - first_nonce + 1;
return 0; return 0;
} }
#endif

View File

@@ -79,19 +79,16 @@ void lyra2rev3_16way_hash( void *state, const void *input )
dintrlv_2x256( hash14, hash15, vhash, 256 ); dintrlv_2x256( hash14, hash15, vhash, 256 );
intrlv_4x128( vhash, hash0, hash1, hash2, hash3, 256 ); intrlv_4x128( vhash, hash0, hash1, hash2, hash3, 256 );
cube_4way_update_close( &ctx.cube, vhash, vhash, 32 ); cube_4way_full( &ctx.cube, vhash, 256, vhash, 32 );
dintrlv_4x128( hash0, hash1, hash2, hash3, vhash, 256 ); dintrlv_4x128( hash0, hash1, hash2, hash3, vhash, 256 );
intrlv_4x128( vhash, hash4, hash5, hash6, hash7, 256 ); intrlv_4x128( vhash, hash4, hash5, hash6, hash7, 256 );
cube_4way_init( &ctx.cube, 256, 16, 32 ); cube_4way_full( &ctx.cube, vhash, 256, vhash, 32 );
cube_4way_update_close( &ctx.cube, vhash, vhash, 32 );
dintrlv_4x128( hash4, hash5, hash6, hash7, vhash, 256 ); dintrlv_4x128( hash4, hash5, hash6, hash7, vhash, 256 );
intrlv_4x128( vhash, hash8, hash9, hash10, hash11, 256 ); intrlv_4x128( vhash, hash8, hash9, hash10, hash11, 256 );
cube_4way_init( &ctx.cube, 256, 16, 32 ); cube_4way_full( &ctx.cube, vhash, 256, vhash, 32 );
cube_4way_update_close( &ctx.cube, vhash, vhash, 32 );
dintrlv_4x128( hash8, hash9, hash10, hash11, vhash, 256 ); dintrlv_4x128( hash8, hash9, hash10, hash11, vhash, 256 );
intrlv_4x128( vhash, hash12, hash13, hash14, hash15, 256 ); intrlv_4x128( vhash, hash12, hash13, hash14, hash15, 256 );
cube_4way_init( &ctx.cube, 256, 16, 32 ); cube_4way_full( &ctx.cube, vhash, 256, vhash, 32 );
cube_4way_update_close( &ctx.cube, vhash, vhash, 32 );
dintrlv_4x128( hash12, hash13, hash14, hash15, vhash, 256 ); dintrlv_4x128( hash12, hash13, hash14, hash15, vhash, 256 );
intrlv_2x256( vhash, hash0, hash1, 256 ); intrlv_2x256( vhash, hash0, hash1, 256 );
@@ -133,15 +130,15 @@ int scanhash_lyra2rev3_16way( struct work *work, const uint32_t max_nonce,
{ {
uint32_t hash[8*16] __attribute__ ((aligned (128))); uint32_t hash[8*16] __attribute__ ((aligned (128)));
uint32_t vdata[20*16] __attribute__ ((aligned (64))); uint32_t vdata[20*16] __attribute__ ((aligned (64)));
uint32_t *hash7 = &hash[7<<4]; uint32_t *hashd7 = &hash[7*16];
uint32_t lane_hash[8] __attribute__ ((aligned (64))); uint32_t lane_hash[8] __attribute__ ((aligned (64)));
uint32_t *pdata = work->data; uint32_t *pdata = work->data;
const uint32_t *ptarget = work->target; const uint32_t *ptarget = work->target;
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
uint32_t n = first_nonce; uint32_t n = first_nonce;
const uint32_t last_nonce = max_nonce - 16; const uint32_t last_nonce = max_nonce - 16;
const uint32_t Htarg = ptarget[7]; const uint32_t targ32 = ptarget[7];
__m512i *noncev = (__m512i*)vdata + 19; // aligned __m512i *noncev = (__m512i*)vdata + 19;
const int thr_id = mythr->id; const int thr_id = mythr->id;
if ( opt_benchmark ) ( (uint32_t*)ptarget )[7] = 0x0000ff; if ( opt_benchmark ) ( (uint32_t*)ptarget )[7] = 0x0000ff;
@@ -162,17 +159,18 @@ int scanhash_lyra2rev3_16way( struct work *work, const uint32_t max_nonce,
pdata[19] = n; pdata[19] = n;
for ( int lane = 0; lane < 16; lane++ ) for ( int lane = 0; lane < 16; lane++ )
if ( unlikely( hash7[lane] <= Htarg ) ) if ( unlikely( hashd7[lane] <= targ32 ) )
{ {
extr_lane_16x32( lane_hash, hash, lane, 256 ); extr_lane_16x32( lane_hash, hash, lane, 256 );
if ( likely( fulltest( lane_hash, ptarget ) && !opt_benchmark ) ) if ( likely( valid_hash( lane_hash, ptarget ) && !opt_benchmark ) )
{ {
pdata[19] = n + lane; pdata[19] = n + lane;
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
n += 16; n += 16;
} while ( likely( (n < last_nonce) && !work_restart[thr_id].restart ) ); } while ( likely( (n < last_nonce) && !work_restart[thr_id].restart ) );
pdata[19] = n;
*hashes_done = n - first_nonce; *hashes_done = n - first_nonce;
return 0; return 0;
} }
@@ -197,7 +195,7 @@ bool init_lyra2rev3_8way_ctx()
void lyra2rev3_8way_hash( void *state, const void *input ) void lyra2rev3_8way_hash( void *state, const void *input )
{ {
uint32_t vhash[8*8] __attribute__ ((aligned (64))); uint32_t vhash[8*8] __attribute__ ((aligned (128)));
uint32_t hash0[8] __attribute__ ((aligned (64))); uint32_t hash0[8] __attribute__ ((aligned (64)));
uint32_t hash1[8] __attribute__ ((aligned (32))); uint32_t hash1[8] __attribute__ ((aligned (32)));
uint32_t hash2[8] __attribute__ ((aligned (32))); uint32_t hash2[8] __attribute__ ((aligned (32)));
@@ -224,21 +222,14 @@ void lyra2rev3_8way_hash( void *state, const void *input )
LYRA2REV3( l2v3_wholeMatrix, hash6, 32, hash6, 32, hash6, 32, 1, 4, 4 ); LYRA2REV3( l2v3_wholeMatrix, hash6, 32, hash6, 32, hash6, 32, 1, 4, 4 );
LYRA2REV3( l2v3_wholeMatrix, hash7, 32, hash7, 32, hash7, 32, 1, 4, 4 ); LYRA2REV3( l2v3_wholeMatrix, hash7, 32, hash7, 32, hash7, 32, 1, 4, 4 );
cubehashUpdateDigest( &ctx.cube, (byte*) hash0, (const byte*) hash0, 32 ); cubehash_full( &ctx.cube, (byte*) hash0, 256, (const byte*) hash0, 32 );
cubehashInit( &ctx.cube, 256, 16, 32 ); cubehash_full( &ctx.cube, (byte*) hash1, 256, (const byte*) hash1, 32 );
cubehashUpdateDigest( &ctx.cube, (byte*) hash1, (const byte*) hash1, 32 ); cubehash_full( &ctx.cube, (byte*) hash2, 256, (const byte*) hash2, 32 );
cubehashInit( &ctx.cube, 256, 16, 32 ); cubehash_full( &ctx.cube, (byte*) hash3, 256, (const byte*) hash3, 32 );
cubehashUpdateDigest( &ctx.cube, (byte*) hash2, (const byte*) hash2, 32 ); cubehash_full( &ctx.cube, (byte*) hash4, 256, (const byte*) hash4, 32 );
cubehashInit( &ctx.cube, 256, 16, 32 ); cubehash_full( &ctx.cube, (byte*) hash5, 256, (const byte*) hash5, 32 );
cubehashUpdateDigest( &ctx.cube, (byte*) hash3, (const byte*) hash3, 32 ); cubehash_full( &ctx.cube, (byte*) hash6, 256, (const byte*) hash6, 32 );
cubehashInit( &ctx.cube, 256, 16, 32 ); cubehash_full( &ctx.cube, (byte*) hash7, 256, (const byte*) hash7, 32 );
cubehashUpdateDigest( &ctx.cube, (byte*) hash4, (const byte*) hash4, 32 );
cubehashInit( &ctx.cube, 256, 16, 32 );
cubehashUpdateDigest( &ctx.cube, (byte*) hash5, (const byte*) hash5, 32 );
cubehashInit( &ctx.cube, 256, 16, 32 );
cubehashUpdateDigest( &ctx.cube, (byte*) hash6, (const byte*) hash6, 32 );
cubehashInit( &ctx.cube, 256, 16, 32 );
cubehashUpdateDigest( &ctx.cube, (byte*) hash7, (const byte*) hash7, 32 );
LYRA2REV3( l2v3_wholeMatrix, hash0, 32, hash0, 32, hash0, 32, 1, 4, 4 ); LYRA2REV3( l2v3_wholeMatrix, hash0, 32, hash0, 32, hash0, 32, 1, 4, 4 );
LYRA2REV3( l2v3_wholeMatrix, hash1, 32, hash1, 32, hash1, 32, 1, 4, 4 ); LYRA2REV3( l2v3_wholeMatrix, hash1, 32, hash1, 32, hash1, 32, 1, 4, 4 );
@@ -260,46 +251,47 @@ void lyra2rev3_8way_hash( void *state, const void *input )
int scanhash_lyra2rev3_8way( struct work *work, const uint32_t max_nonce, int scanhash_lyra2rev3_8way( struct work *work, const uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ) uint64_t *hashes_done, struct thr_info *mythr )
{ {
uint32_t hash[8*8] __attribute__ ((aligned (64))); uint32_t hash[8*8] __attribute__ ((aligned (128)));
uint32_t vdata[20*8] __attribute__ ((aligned (64))); uint32_t vdata[20*8] __attribute__ ((aligned (64)));
uint32_t *hash7 = &hash[7<<3]; uint32_t *hashd7 = &hash[7*8];
uint32_t lane_hash[8] __attribute__ ((aligned (32))); uint32_t lane_hash[8] __attribute__ ((aligned (32)));
uint32_t *pdata = work->data; uint32_t *pdata = work->data;
const uint32_t *ptarget = work->target; uint32_t *ptarget = work->target;
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 8;
uint32_t n = first_nonce; uint32_t n = first_nonce;
const uint32_t Htarg = ptarget[7]; const uint32_t targ32 = ptarget[7];
__m256i *noncev = (__m256i*)vdata + 19; // aligned __m256i *noncev = (__m256i*)vdata + 19;
const int thr_id = mythr->id; const int thr_id = mythr->id;
const bool bench = opt_benchmark;
if ( opt_benchmark ) ( (uint32_t*)ptarget )[7] = 0x0000ff; if ( bench ) ptarget[7] = 0x0000ff;
mm256_bswap32_intrlv80_8x32( vdata, pdata ); mm256_bswap32_intrlv80_8x32( vdata, pdata );
*noncev = _mm256_set_epi32( n+7, n+6, n+5, n+4, n+3, n+2, n+1, n );
blake256_8way_init( &l2v3_8way_ctx.blake ); blake256_8way_init( &l2v3_8way_ctx.blake );
blake256_8way_update( &l2v3_8way_ctx.blake, vdata, 64 ); blake256_8way_update( &l2v3_8way_ctx.blake, vdata, 64 );
do do
{ {
*noncev = mm256_bswap_32( _mm256_set_epi32( n+7, n+6, n+5, n+4,
n+3, n+2, n+1, n ) );
lyra2rev3_8way_hash( hash, vdata ); lyra2rev3_8way_hash( hash, vdata );
pdata[19] = n; pdata[19] = n;
for ( int lane = 0; lane < 8; lane++ ) for ( int lane = 0; lane < 8; lane++ )
if ( unlikely( hash7[lane] <= Htarg ) ) if ( unlikely( hashd7[lane] <= targ32 ) )
{ {
extr_lane_8x32( lane_hash, hash, lane, 256 ); extr_lane_8x32( lane_hash, hash, lane, 256 );
if ( likely( fulltest( lane_hash, ptarget ) && !opt_benchmark ) ) if ( likely( valid_hash( lane_hash, ptarget ) && !bench ) )
{ {
pdata[19] = n + lane; pdata[19] = bswap_32( n + lane );
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
*noncev = _mm256_add_epi32( *noncev, m256_const1_32( 8 ) );
n += 8; n += 8;
} while ( likely( (n < max_nonce-8) && !work_restart[thr_id].restart ) ); } while ( likely( (n < last_nonce) && !work_restart[thr_id].restart ) );
*hashes_done = n - first_nonce + 1; pdata[19] = n;
*hashes_done = n - first_nonce;
return 0; return 0;
} }
@@ -366,42 +358,41 @@ int scanhash_lyra2rev3_4way( struct work *work, const uint32_t max_nonce,
{ {
uint32_t hash[8*4] __attribute__ ((aligned (64))); uint32_t hash[8*4] __attribute__ ((aligned (64)));
uint32_t vdata[20*4] __attribute__ ((aligned (64))); uint32_t vdata[20*4] __attribute__ ((aligned (64)));
uint32_t *hash7 = &(hash[7<<2]); uint32_t *hashd7 = &(hash[7*4]);
uint32_t lane_hash[8] __attribute__ ((aligned (32))); uint32_t lane_hash[8] __attribute__ ((aligned (32)));
uint32_t *pdata = work->data; uint32_t *pdata = work->data;
const uint32_t *ptarget = work->target; const uint32_t *ptarget = work->target;
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
uint32_t n = first_nonce; uint32_t n = first_nonce;
const uint32_t Htarg = ptarget[7]; const uint32_t targ32 = ptarget[7];
__m128i *noncev = (__m128i*)vdata + 19; // aligned __m128i *noncev = (__m128i*)vdata + 19;
const int thr_id = mythr->id; // thr_id arg is deprecated const int thr_id = mythr->id;
if ( opt_benchmark ) if ( opt_benchmark )
( (uint32_t*)ptarget )[7] = 0x0000ff; ( (uint32_t*)ptarget )[7] = 0x0000ff;
mm128_bswap32_intrlv80_4x32( vdata, pdata ); mm128_bswap32_intrlv80_4x32( vdata, pdata );
*noncev = _mm_set_epi32( n+3, n+2, n+1, n );
blake256_4way_init( &l2v3_4way_ctx.blake ); blake256_4way_init( &l2v3_4way_ctx.blake );
blake256_4way_update( &l2v3_4way_ctx.blake, vdata, 64 ); blake256_4way_update( &l2v3_4way_ctx.blake, vdata, 64 );
do do
{ {
*noncev = mm128_bswap_32( _mm_set_epi32( n+3, n+2, n+1, n ) );
lyra2rev3_4way_hash( hash, vdata ); lyra2rev3_4way_hash( hash, vdata );
pdata[19] = n; for ( int lane = 0; lane < 4; lane++ ) if ( hashd7[lane] <= targ32 )
for ( int lane = 0; lane < 4; lane++ ) if ( hash7[lane] <= Htarg )
{ {
extr_lane_4x32( lane_hash, hash, lane, 256 ); extr_lane_4x32( lane_hash, hash, lane, 256 );
if ( fulltest( lane_hash, ptarget ) && !opt_benchmark ) if ( valid_hash( lane_hash, ptarget ) && !opt_benchmark )
{ {
pdata[19] = n + lane; pdata[19] = bswap_32( n + lane );
submit_lane_solution( work, lane_hash, mythr, lane ); submit_solution( work, lane_hash, mythr );
} }
} }
*noncev = _mm_add_epi32( *noncev, m128_const1_32( 4 ) );
n += 4; n += 4;
} while ( (n < max_nonce-4) && !work_restart[thr_id].restart); } while ( (n < max_nonce-4) && !work_restart[thr_id].restart);
pdata[19] = n;
*hashes_done = n - first_nonce + 1; *hashes_done = n - first_nonce + 1;
return 0; return 0;
} }

View File

@@ -1,4 +1,7 @@
#include "lyra2-gate.h" #include "lyra2-gate.h"
#if !( defined(LYRA2REV3_16WAY) || defined(LYRA2REV3_8WAY) || defined(LYRA2REV3_4WAY) )
#include <memory.h> #include <memory.h>
#include "algo/blake/sph_blake.h" #include "algo/blake/sph_blake.h"
#include "algo/cubehash/sph_cubehash.h" #include "algo/cubehash/sph_cubehash.h"
@@ -85,7 +88,7 @@ int scanhash_lyra2rev3( struct work *work,
lyra2rev3_hash(hash, endiandata); lyra2rev3_hash(hash, endiandata);
if (hash[7] <= Htarg ) if (hash[7] <= Htarg )
if( fulltest( hash, ptarget ) && !opt_benchmark ) if( valid_hash( hash, ptarget ) && !opt_benchmark )
{ {
pdata[19] = nonce; pdata[19] = nonce;
submit_solution( work, hash, mythr ); submit_solution( work, hash, mythr );
@@ -96,4 +99,4 @@ int scanhash_lyra2rev3( struct work *work,
*hashes_done = pdata[19] - first_nonce + 1; *hashes_done = pdata[19] - first_nonce + 1;
return 0; return 0;
} }
#endif

View File

@@ -97,41 +97,42 @@ void lyra2z_16way_hash( void *state, const void *input )
int scanhash_lyra2z_16way( struct work *work, uint32_t max_nonce, int scanhash_lyra2z_16way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ) uint64_t *hashes_done, struct thr_info *mythr )
{ {
uint32_t hash[8*16] __attribute__ ((aligned (128))); uint64_t hash[4*16] __attribute__ ((aligned (128)));
uint32_t vdata[20*16] __attribute__ ((aligned (64))); uint32_t vdata[20*16] __attribute__ ((aligned (64)));
uint32_t *pdata = work->data; uint32_t *pdata = work->data;
uint32_t *ptarget = work->target; uint32_t *ptarget = work->target;
const uint32_t Htarg = ptarget[7];
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
uint32_t n = first_nonce; uint32_t n = first_nonce;
const uint32_t last_nonce = max_nonce - 16;
__m512i *noncev = (__m512i*)vdata + 19; // aligned __m512i *noncev = (__m512i*)vdata + 19; // aligned
int thr_id = mythr->id; // thr_id arg is deprecated const int thr_id = mythr->id;
const bool bench = opt_benchmark;
if ( opt_benchmark ) if ( bench ) ptarget[7] = 0x0000ff;
ptarget[7] = 0x0000ff;
mm512_bswap32_intrlv80_16x32( vdata, pdata ); mm512_bswap32_intrlv80_16x32( vdata, pdata );
*noncev = _mm512_set_epi32( n+15, n+14, n+13, n+12, n+11, n+10, n+ 9, n+ 8,
n+ 7, n+ 6, n+ 5, n+ 4, n+ 3, n+ 2, n +1, n );
lyra2z_16way_midstate( vdata ); lyra2z_16way_midstate( vdata );
do { do {
*noncev = mm512_bswap_32( _mm512_set_epi32( n+15, n+14, n+13, n+12,
n+11, n+10, n+ 9, n+ 8,
n+ 7, n+ 6, n+ 5, n+ 4,
n+ 3, n+ 2, n+ 1, n ) );
lyra2z_16way_hash( hash, vdata ); lyra2z_16way_hash( hash, vdata );
pdata[19] = n;
for ( int i = 0; i < 16; i++ ) for ( int lane = 0; lane < 16; lane++ )
if ( (hash+(i<<3))[7] <= Htarg && fulltest( hash+(i<<3), ptarget )
&& !opt_benchmark )
{ {
pdata[19] = n+i; const uint64_t *lane_hash = hash + (lane<<2);
submit_lane_solution( work, hash+(i<<3), mythr, i ); if ( unlikely( valid_hash( lane_hash, ptarget ) && !bench ) )
{
pdata[19] = bswap_32( n + lane );
submit_solution( work, lane_hash, mythr );
}
} }
*noncev = _mm512_add_epi32( *noncev, m512_const1_32( 16 ) );
n += 16; n += 16;
} while ( (n < max_nonce-16) && !work_restart[thr_id].restart); } while ( likely( (n < last_nonce) && !work_restart[thr_id].restart ) );
*hashes_done = n - first_nonce + 1; pdata[19] = n;
*hashes_done = n - first_nonce;
return 0; return 0;
} }
@@ -195,39 +196,40 @@ void lyra2z_8way_hash( void *state, const void *input )
int scanhash_lyra2z_8way( struct work *work, uint32_t max_nonce, int scanhash_lyra2z_8way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ) uint64_t *hashes_done, struct thr_info *mythr )
{ {
uint32_t hash[8*8] __attribute__ ((aligned (64))); uint64_t hash[4*8] __attribute__ ((aligned (64)));
uint32_t vdata[20*8] __attribute__ ((aligned (64))); uint32_t vdata[20*8] __attribute__ ((aligned (64)));
uint32_t *pdata = work->data; uint32_t *pdata = work->data;
uint32_t *ptarget = work->target; uint32_t *ptarget = work->target;
const uint32_t Htarg = ptarget[7];
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 8;
uint32_t n = first_nonce; uint32_t n = first_nonce;
__m256i *noncev = (__m256i*)vdata + 19; // aligned __m256i *noncev = (__m256i*)vdata + 19; // aligned
int thr_id = mythr->id; // thr_id arg is deprecated const int thr_id = mythr->id;
const bool bench = opt_benchmark;
if ( opt_benchmark ) if ( bench ) ptarget[7] = 0x0000ff;
ptarget[7] = 0x0000ff;
mm256_bswap32_intrlv80_8x32( vdata, pdata ); mm256_bswap32_intrlv80_8x32( vdata, pdata );
*noncev = _mm256_set_epi32( n+7, n+6, n+5, n+4, n+3, n+2, n+1, n );
lyra2z_8way_midstate( vdata ); lyra2z_8way_midstate( vdata );
do { do {
*noncev = mm256_bswap_32(
_mm256_set_epi32( n+7, n+6, n+5, n+4, n+3, n+2, n+1, n ) );
lyra2z_8way_hash( hash, vdata ); lyra2z_8way_hash( hash, vdata );
pdata[19] = n;
for ( int i = 0; i < 8; i++ ) for ( int lane = 0; lane < 8; lane++ )
if ( (hash+(i<<3))[7] <= Htarg && fulltest( hash+(i<<3), ptarget )
&& !opt_benchmark )
{ {
pdata[19] = n+i; const uint64_t *lane_hash = hash + (lane<<2);
submit_lane_solution( work, hash+(i<<3), mythr, i ); if ( unlikely( valid_hash( lane_hash, ptarget ) && !bench ) )
{
pdata[19] = bswap_32( n + lane );
submit_solution( work, lane_hash, mythr );
}
} }
*noncev = _mm256_add_epi32( *noncev, m256_const1_32( 8 ) );
n += 8; n += 8;
} while ( (n < max_nonce-8) && !work_restart[thr_id].restart); } while ( likely( (n < last_nonce) && !work_restart[thr_id].restart) );
pdata[19] = n;
*hashes_done = n - first_nonce + 1; *hashes_done = n - first_nonce;
return 0; return 0;
} }
@@ -274,39 +276,40 @@ void lyra2z_4way_hash( void *state, const void *input )
int scanhash_lyra2z_4way( struct work *work, uint32_t max_nonce, int scanhash_lyra2z_4way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ) uint64_t *hashes_done, struct thr_info *mythr )
{ {
uint32_t hash[8*4] __attribute__ ((aligned (64))); uint64_t hash[4*4] __attribute__ ((aligned (64)));
uint32_t vdata[20*4] __attribute__ ((aligned (64))); uint32_t vdata[20*4] __attribute__ ((aligned (64)));
uint32_t *pdata = work->data; uint32_t *pdata = work->data;
uint32_t *ptarget = work->target; uint32_t *ptarget = work->target;
const uint32_t Htarg = ptarget[7];
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 4;
uint32_t n = first_nonce; uint32_t n = first_nonce;
__m128i *noncev = (__m128i*)vdata + 19; // aligned __m128i *noncev = (__m128i*)vdata + 19; // aligned
int thr_id = mythr->id; // thr_id arg is deprecated const int thr_id = mythr->id;
const bool bench = opt_benchmark;
if ( opt_benchmark ) if ( bench ) ptarget[7] = 0x0000ff;
ptarget[7] = 0x0000ff;
mm128_bswap32_intrlv80_4x32( vdata, pdata ); mm128_bswap32_intrlv80_4x32( vdata, pdata );
*noncev = _mm_set_epi32( n+3, n+2, n+1, n );
lyra2z_4way_midstate( vdata ); lyra2z_4way_midstate( vdata );
do { do {
*noncev = mm128_bswap_32( _mm_set_epi32( n+3, n+2, n+1, n ) );
lyra2z_4way_hash( hash, vdata ); lyra2z_4way_hash( hash, vdata );
pdata[19] = n; for ( int lane = 0; lane < 4; lane++ )
for ( int i = 0; i < 4; i++ )
if ( (hash+(i<<3))[7] <= Htarg && fulltest( hash+(i<<3), ptarget )
&& !opt_benchmark )
{ {
pdata[19] = n+i; const uint64_t *lane_hash = hash + (lane<<2);
submit_lane_solution( work, hash+(i<<3), mythr, i ); if ( unlikely( valid_hash( lane_hash, ptarget ) && !bench ) )
{
pdata[19] = bswap_32( n + lane );
submit_solution( work, lane_hash, mythr );
}
} }
*noncev = _mm_add_epi32( *noncev, m128_const1_32( 4 ) );
n += 4; n += 4;
} while ( (n < max_nonce-4) && !work_restart[thr_id].restart); } while ( likely( (n < last_nonce) && !work_restart[thr_id].restart ) );
*hashes_done = n - first_nonce + 1; pdata[19] = n;
*hashes_done = n - first_nonce;
return 0; return 0;
} }

View File

@@ -1,6 +1,9 @@
#include <memory.h> #include <memory.h>
#include <mm_malloc.h> #include <mm_malloc.h>
#include "lyra2-gate.h" #include "lyra2-gate.h"
#if !( defined(LYRA2Z_16WAY) || defined(LYRA2Z_8WAY) || defined(LYRA2Z_4WAY) )
#include "lyra2.h" #include "lyra2.h"
#include "algo/blake/sph_blake.h" #include "algo/blake/sph_blake.h"
#include "simd-utils.h" #include "simd-utils.h"
@@ -53,7 +56,7 @@ int scanhash_lyra2z( struct work *work, uint32_t max_nonce,
const uint32_t Htarg = ptarget[7]; const uint32_t Htarg = ptarget[7];
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
uint32_t nonce = first_nonce; uint32_t nonce = first_nonce;
int thr_id = mythr->id; // thr_id arg is deprecated int thr_id = mythr->id;
if (opt_benchmark) if (opt_benchmark)
ptarget[7] = 0x0000ff; ptarget[7] = 0x0000ff;
@@ -62,14 +65,13 @@ int scanhash_lyra2z( struct work *work, uint32_t max_nonce,
be32enc(&endiandata[i], pdata[i]); be32enc(&endiandata[i], pdata[i]);
} }
lyra2z_midstate( endiandata ); lyra2z_midstate( endiandata );
do { do {
be32enc(&endiandata[19], nonce); be32enc(&endiandata[19], nonce);
lyra2z_hash( hash, endiandata ); lyra2z_hash( hash, endiandata );
if ( hash[7] <= Htarg ) if ( valid_hash( hash, ptarget ) && !opt_benchmark )
if ( fulltest( hash, ptarget ) && !opt_benchmark )
{ {
pdata[19] = nonce; pdata[19] = nonce;
submit_solution( work, hash, mythr ); submit_solution( work, hash, mythr );
@@ -80,4 +82,4 @@ int scanhash_lyra2z( struct work *work, uint32_t max_nonce,
*hashes_done = pdata[19] - first_nonce + 1; *hashes_done = pdata[19] - first_nonce + 1;
return 0; return 0;
} }
#endif

View File

@@ -9,7 +9,7 @@ void lyra2z330_hash(void *state, const void *input, uint32_t height)
{ {
uint32_t _ALIGN(256) hash[16]; uint32_t _ALIGN(256) hash[16];
LYRA2Z( lyra2z330_wholeMatrix, hash, 32, input, 80, input, 80, LYRA2Z( lyra2z330_wholeMatrix, hash, 32, input, 80, input, 80,
2, 330, 256 ); 2, 330, 256 );
memcpy(state, hash, 32); memcpy(state, hash, 32);
@@ -18,38 +18,40 @@ void lyra2z330_hash(void *state, const void *input, uint32_t height)
int scanhash_lyra2z330( struct work *work, uint32_t max_nonce, int scanhash_lyra2z330( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ) uint64_t *hashes_done, struct thr_info *mythr )
{ {
uint32_t hash[8] __attribute__ ((aligned (64))); uint32_t hash[8] __attribute__ ((aligned (128)));
uint32_t endiandata[20] __attribute__ ((aligned (64))); uint32_t edata[20] __attribute__ ((aligned (64)));
uint32_t *pdata = work->data; uint32_t *pdata = work->data;
uint32_t *ptarget = work->target; uint32_t *ptarget = work->target;
const uint32_t Htarg = ptarget[7];
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
uint32_t nonce = first_nonce; uint32_t nonce = first_nonce;
int thr_id = mythr->id; // thr_id arg is deprecated const int thr_id = mythr->id;
if (opt_benchmark) if (opt_benchmark)
ptarget[7] = 0x0000ff; ptarget[7] = 0x0000ff;
casti_m128i( endiandata, 0 ) = mm128_bswap_32( casti_m128i( pdata, 0 ) ); casti_m128i( edata, 0 ) = mm128_bswap_32( casti_m128i( pdata, 0 ) );
casti_m128i( endiandata, 1 ) = mm128_bswap_32( casti_m128i( pdata, 1 ) ); casti_m128i( edata, 1 ) = mm128_bswap_32( casti_m128i( pdata, 1 ) );
casti_m128i( endiandata, 2 ) = mm128_bswap_32( casti_m128i( pdata, 2 ) ); casti_m128i( edata, 2 ) = mm128_bswap_32( casti_m128i( pdata, 2 ) );
casti_m128i( endiandata, 3 ) = mm128_bswap_32( casti_m128i( pdata, 3 ) ); casti_m128i( edata, 3 ) = mm128_bswap_32( casti_m128i( pdata, 3 ) );
casti_m128i( endiandata, 4 ) = mm128_bswap_32( casti_m128i( pdata, 4 ) ); casti_m128i( edata, 4 ) = mm128_bswap_32( casti_m128i( pdata, 4 ) );
do do
{ {
be32enc( &endiandata[19], nonce ); edata[19] = nonce;
lyra2z330_hash( hash, endiandata, work->height );
if ( hash[7] <= Htarg ) LYRA2Z( lyra2z330_wholeMatrix, hash, 32, edata, 80, edata, 80,
if ( fulltest( hash, ptarget ) && !opt_benchmark ) 2, 330, 256 );
// lyra2z330_hash( hash, edata, work->height );
if ( valid_hash( hash, ptarget ) && !opt_benchmark )
{ {
pdata[19] = nonce; be32enc( pdata + 19, nonce );
submit_solution( work, hash, mythr ); submit_solution( work, hash, mythr );
} }
nonce++; nonce++;
} while ( nonce < max_nonce && !work_restart[thr_id].restart ); } while ( nonce < max_nonce && !work_restart[thr_id].restart );
pdata[19] = nonce; pdata[19] = nonce;
*hashes_done = pdata[19] - first_nonce + 1; *hashes_done = nonce - first_nonce;
return 0; return 0;
} }
@@ -66,7 +68,7 @@ bool lyra2z330_thread_init()
bool register_lyra2z330_algo( algo_gate_t* gate ) bool register_lyra2z330_algo( algo_gate_t* gate )
{ {
gate->optimizations = SSE42_OPT | AVX2_OPT; gate->optimizations = SSE2_OPT | AVX2_OPT;
gate->miner_thread_init = (void*)&lyra2z330_thread_init; gate->miner_thread_init = (void*)&lyra2z330_thread_init;
gate->scanhash = (void*)&scanhash_lyra2z330; gate->scanhash = (void*)&scanhash_lyra2z330;
gate->hash = (void*)&lyra2z330_hash; gate->hash = (void*)&lyra2z330_hash;

View File

@@ -1,233 +1,501 @@
/**
* Phi-2 algo Implementation
*/
#include "lyra2-gate.h" #include "lyra2-gate.h"
#if defined(PHI2_4WAY)
#include "algo/skein/skein-hash-4way.h" #include "algo/skein/skein-hash-4way.h"
#include "algo/jh/jh-hash-4way.h" #include "algo/jh/jh-hash-4way.h"
#include "algo/gost/sph_gost.h" #include "algo/gost/sph_gost.h"
#include "algo/cubehash/cubehash_sse2.h" #include "algo/cubehash/cubehash_sse2.h"
#include "algo/echo/aes_ni/hash_api.h" #include "lyra2.h"
#if defined(__VAES__)
#include "algo/echo/echo-hash-4way.h"
#elif defined(__AES__)
#include "algo/echo/aes_ni/hash_api.h"
#endif
#if defined(PHI2_8WAY)
typedef struct {
cubehashParam cube;
jh512_8way_context jh;
#if defined(__VAES__)
echo_4way_context echo;
#else
hashState_echo echo;
#endif
sph_gost512_context gost;
skein512_8way_context skein;
} phi2_8way_ctx_holder;
void phi2_8way_hash( void *state, const void *input )
{
unsigned char _ALIGN(128) hash[64*8];
unsigned char _ALIGN(128) hashA[64*2];
unsigned char _ALIGN(64) hash0[64];
unsigned char _ALIGN(64) hash1[64];
unsigned char _ALIGN(64) hash2[64];
unsigned char _ALIGN(64) hash3[64];
unsigned char _ALIGN(64) hash4[64];
unsigned char _ALIGN(64) hash5[64];
unsigned char _ALIGN(64) hash6[64];
unsigned char _ALIGN(64) hash7[64];
const int size = phi2_has_roots ? 144 : 80 ;
phi2_8way_ctx_holder ctx __attribute__ ((aligned (64)));
cubehash_full( &ctx.cube, (byte*)hash0, 512,
(const byte*)input, size );
cubehash_full( &ctx.cube, (byte*)hash1, 512,
(const byte*)input + 144, size );
cubehash_full( &ctx.cube, (byte*)hash2, 512,
(const byte*)input + 2*144, size );
cubehash_full( &ctx.cube, (byte*)hash3, 512,
(const byte*)input + 3*144, size );
cubehash_full( &ctx.cube, (byte*)hash4, 512,
(const byte*)input + 4*144, size );
cubehash_full( &ctx.cube, (byte*)hash5, 512,
(const byte*)input + 5*144, size );
cubehash_full( &ctx.cube, (byte*)hash6, 512,
(const byte*)input + 6*144, size );
cubehash_full( &ctx.cube, (byte*)hash7, 512,
(const byte*)input + 7*144, size );
intrlv_2x256( hashA, hash0, hash1, 512 );
LYRA2RE_2WAY( hash, 32, hashA, 32, 1, 8, 8 );
LYRA2RE_2WAY( hash + 2*32, 32, hashA + 2*32, 32, 1, 8, 8 );
dintrlv_2x256( hash0, hash1, hash, 512 );
intrlv_2x256( hashA, hash2, hash3, 512 );
LYRA2RE_2WAY( hash, 32, hashA, 32, 1, 8, 8 );
LYRA2RE_2WAY( hash + 2*32, 32, hashA + 2*32, 32, 1, 8, 8 );
dintrlv_2x256( hash2, hash3, hash, 512 );
intrlv_2x256( hashA, hash4, hash5, 512 );
LYRA2RE_2WAY( hash, 32, hashA, 32, 1, 8, 8 );
LYRA2RE_2WAY( hash + 2*32, 32, hashA + 2*32, 32, 1, 8, 8 );
dintrlv_2x256( hash4, hash5, hash, 512 );
intrlv_2x256( hashA, hash6, hash7, 512 );
LYRA2RE_2WAY( hash, 32, hashA, 32, 1, 8, 8 );
LYRA2RE_2WAY( hash + 2*32, 32, hashA + 2*32, 32, 1, 8, 8 );
dintrlv_2x256( hash6, hash7, hash, 512 );
intrlv_8x64_512( hash, hash0, hash1, hash2, hash3,
hash4, hash5, hash6, hash7 );
jh512_8way_init( &ctx.jh );
jh512_8way_update( &ctx.jh, (const void*)hash, 64 );
jh512_8way_close( &ctx.jh, (void*)hash );
dintrlv_8x64_512( hash0, hash1, hash2, hash3,
hash4, hash5, hash6, hash7, hash );
#if defined (__VAES__)
unsigned char _ALIGN(64) hashA0[64];
unsigned char _ALIGN(64) hashA1[64];
unsigned char _ALIGN(64) hashA2[64];
unsigned char _ALIGN(64) hashA3[64];
unsigned char _ALIGN(64) hashA4[64];
unsigned char _ALIGN(64) hashA5[64];
unsigned char _ALIGN(64) hashA6[64];
unsigned char _ALIGN(64) hashA7[64];
intrlv_4x128_512( hash, hash0, hash1, hash2, hash3 );
echo_4way_full( &ctx.echo, hash, 512, hash, 64 );
echo_4way_full( &ctx.echo, hash, 512, hash, 64 );
dintrlv_4x128_512( hashA0, hashA1, hashA2, hashA3, hash );
intrlv_4x128_512( hash, hash4, hash5, hash6, hash7 );
echo_4way_full( &ctx.echo, hash, 512, hash, 64 );
echo_4way_full( &ctx.echo, hash, 512, hash, 64 );
dintrlv_4x128_512( hashA4, hashA5, hashA6, hashA7, hash );
#endif
if ( hash0[0] & 1 )
{
sph_gost512_init( &ctx.gost );
sph_gost512( &ctx.gost, (const void*)hash0, 64 );
sph_gost512_close( &ctx.gost, (void*)hash0 );
}
else
#if defined (__VAES__)
memcpy( hash0, hashA0, 64 );
#else
{
echo_full( &ctx.echo, (BitSequence *)hash0, 512,
(const BitSequence *)hash0, 64 );
echo_full( &ctx.echo, (BitSequence *)hash0, 512,
(const BitSequence *)hash0, 64 );
}
#endif
if ( hash1[0] & 1 )
{
sph_gost512_init( &ctx.gost );
sph_gost512( &ctx.gost, (const void*)hash1, 64 );
sph_gost512_close( &ctx.gost, (void*)hash1 );
}
else
#if defined (__VAES__)
memcpy( hash1, hashA1, 64 );
#else
{
echo_full( &ctx.echo, (BitSequence *)hash1, 512,
(const BitSequence *)hash1, 64 );
echo_full( &ctx.echo, (BitSequence *)hash1, 512,
(const BitSequence *)hash1, 64 );
}
#endif
if ( hash2[0] & 1 )
{
sph_gost512_init( &ctx.gost );
sph_gost512( &ctx.gost, (const void*)hash2, 64 );
sph_gost512_close( &ctx.gost, (void*)hash2 );
}
else
#if defined (__VAES__)
memcpy( hash2, hashA2, 64 );
#else
{
echo_full( &ctx.echo, (BitSequence *)hash2, 512,
(const BitSequence *)hash2, 64 );
echo_full( &ctx.echo, (BitSequence *)hash2, 512,
(const BitSequence *)hash2, 64 );
}
#endif
if ( hash3[0] & 1 )
{
sph_gost512_init( &ctx.gost );
sph_gost512( &ctx.gost, (const void*)hash3, 64 );
sph_gost512_close( &ctx.gost, (void*)hash3 );
}
else
#if defined (__VAES__)
memcpy( hash3, hashA3, 64 );
#else
{
echo_full( &ctx.echo, (BitSequence *)hash3, 512,
(const BitSequence *)hash3, 64 );
echo_full( &ctx.echo, (BitSequence *)hash3, 512,
(const BitSequence *)hash3, 64 );
}
#endif
if ( hash4[0] & 1 )
{
sph_gost512_init( &ctx.gost );
sph_gost512( &ctx.gost, (const void*)hash4, 64 );
sph_gost512_close( &ctx.gost, (void*)hash4 );
}
else
#if defined (__VAES__)
memcpy( hash4, hashA4, 64 );
#else
{
echo_full( &ctx.echo, (BitSequence *)hash4, 512,
(const BitSequence *)hash4, 64 );
echo_full( &ctx.echo, (BitSequence *)hash4, 512,
(const BitSequence *)hash4, 64 );
}
#endif
if ( hash5[0] & 1 )
{
sph_gost512_init( &ctx.gost );
sph_gost512( &ctx.gost, (const void*)hash5, 64 );
sph_gost512_close( &ctx.gost, (void*)hash5 );
}
else
#if defined (__VAES__)
memcpy( hash5, hashA5, 64 );
#else
{
echo_full( &ctx.echo, (BitSequence *)hash5, 512,
(const BitSequence *)hash5, 64 );
echo_full( &ctx.echo, (BitSequence *)hash5, 512,
(const BitSequence *)hash5, 64 );
}
#endif
if ( hash6[0] & 1 )
{
sph_gost512_init( &ctx.gost );
sph_gost512( &ctx.gost, (const void*)hash6, 64 );
sph_gost512_close( &ctx.gost, (void*)hash6 );
}
else
#if defined (__VAES__)
memcpy( hash6, hashA6, 64 );
#else
{
echo_full( &ctx.echo, (BitSequence *)hash6, 512,
(const BitSequence *)hash6, 64 );
echo_full( &ctx.echo, (BitSequence *)hash6, 512,
(const BitSequence *)hash6, 64 );
}
#endif
if ( hash7[0] & 1 )
{
sph_gost512_init( &ctx.gost );
sph_gost512( &ctx.gost, (const void*)hash7, 64 );
sph_gost512_close( &ctx.gost, (void*)hash7 );
}
else
#if defined (__VAES__)
memcpy( hash7, hashA7, 64 );
#else
{
echo_full( &ctx.echo, (BitSequence *)hash7, 512,
(const BitSequence *)hash7, 64 );
echo_full( &ctx.echo, (BitSequence *)hash7, 512,
(const BitSequence *)hash7, 64 );
}
#endif
intrlv_8x64_512( hash, hash0, hash1, hash2, hash3,
hash4, hash5, hash6, hash7 );
skein512_8way_init( &ctx.skein );
skein512_8way_update( &ctx.skein, (const void*)hash, 64 );
skein512_8way_close( &ctx.skein, (void*)hash );
for ( int i = 0; i < 4; i++ )
casti_m512i( state, i ) = _mm512_xor_si512( casti_m512i( hash, i ),
casti_m512i( hash, i+4 ) );
}
int scanhash_phi2_8way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr )
{
uint32_t _ALIGN(128) hash[16*8];
uint32_t _ALIGN(128) edata[36*8];
uint32_t *pdata = work->data;
uint32_t *ptarget = work->target;
uint32_t *hash7 = &(hash[49]);
const uint32_t Htarg = ptarget[7];
const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 8;
uint32_t n = first_nonce;
const int thr_id = mythr->id;
const bool bench = opt_benchmark;
if ( bench ) ptarget[7] = 0x00ff;
phi2_has_roots = false;
for ( int i = 0; i < 36; i++ )
{
be32enc( &edata[i], pdata[i] );
edata[ i + 36 ] = edata[ i + 2*36 ] = edata[ i + 3*36 ] =
edata[ i + 4*36 ] = edata[ i + 5*36 ] = edata[ i + 6*36 ] =
edata[ i + 7*36 ] = edata[ i ];
if ( i >= 20 && pdata[i] ) phi2_has_roots = true;
}
edata[ 19 ] = n;
edata[ 36 + 19 ] = n+1;
edata[ 2*36 + 19 ] = n+2;
edata[ 3*36 + 19 ] = n+3;
edata[ 4*36 + 19 ] = n+4;
edata[ 5*36 + 19 ] = n+5;
edata[ 6*36 + 19 ] = n+6;
edata[ 7*36 + 19 ] = n+7;
do {
phi2_8way_hash( hash, edata );
for ( int lane = 0; lane < 8; lane++ )
if ( unlikely( hash7[ lane<<1 ] <= Htarg && !bench ) )
{
uint64_t _ALIGN(64) lane_hash[8];
extr_lane_8x64( lane_hash, hash, lane, 256 );
if ( valid_hash( lane_hash, ptarget ) )
{
be32enc( pdata + 19, n + lane );
submit_solution( work, lane_hash, mythr );
}
}
n += 8;
edata[ 19 ] += 8;
edata[ 36 + 19 ] += 8;
edata[ 2*36 + 19 ] += 8;
edata[ 3*36 + 19 ] += 8;
edata[ 4*36 + 19 ] += 8;
edata[ 5*36 + 19 ] += 8;
edata[ 6*36 + 19 ] += 8;
edata[ 7*36 + 19 ] += 8;
} while ( (n < last_nonce) && !work_restart[thr_id].restart);
pdata[19] = n;
*hashes_done = n - first_nonce;
return 0;
}
#elif defined(PHI2_4WAY)
typedef struct { typedef struct {
cubehashParam cube; cubehashParam cube;
jh512_4way_context jh; jh512_4way_context jh;
#if defined(__AES__)
hashState_echo echo; hashState_echo echo;
// hashState_echo echo2; #else
sph_echo512_context echo;
#endif
sph_gost512_context gost; sph_gost512_context gost;
skein512_4way_context skein; skein512_4way_context skein;
} phi2_ctx_holder; } phi2_4way_ctx_holder;
/*
phi2_ctx_holder phi2_ctx;
void init_phi2_ctx() phi2_4way_ctx_holder phi2_4way_ctx;
void phi2_4way_hash(void *state, const void *input)
{ {
cubehashInit( &phi2_ctx.cube, 512, 16, 32 ); unsigned char _ALIGN(128) hash[64*4];
sph_jh512_init(&phi2_ctx.jh); unsigned char _ALIGN(64) hash0[64];
init_echo( &phi2_ctx.echo1, 512 ); unsigned char _ALIGN(64) hash1[64];
init_echo( &phi2_ctx.echo2, 512 ); unsigned char _ALIGN(64) hash2[64];
sph_gost512_init(&phi2_ctx.gost); unsigned char _ALIGN(64) hash3[64];
sph_skein512_init(&phi2_ctx.skein); unsigned char _ALIGN(64) hash0A[64];
}; unsigned char _ALIGN(64) hash1A[64];
*/ unsigned char _ALIGN(64) hash2A[64];
void phi2_hash_4way( void *state, const void *input ) unsigned char _ALIGN(64) hash3A[64];
{ const int size = phi2_has_roots ? 144 : 80 ;
uint32_t hash[4][16] __attribute__ ((aligned (64))); phi2_4way_ctx_holder ctx __attribute__ ((aligned (64)));
uint32_t hashA[4][16] __attribute__ ((aligned (64)));
uint32_t hashB[4][16] __attribute__ ((aligned (64)));
uint32_t vhash[4*16] __attribute__ ((aligned (64)));
// unsigned char _ALIGN(128) hash[64]; cubehash_full( &ctx.cube, (byte*)hash0A, 512,
// unsigned char _ALIGN(128) hashA[64]; (const byte*)input, size );
// unsigned char _ALIGN(128) hashB[64]; cubehash_full( &ctx.cube, (byte*)hash1A, 512,
(const byte*)input + 144, size );
cubehash_full( &ctx.cube, (byte*)hash2A, 512,
(const byte*)input + 2*144, size );
cubehash_full( &ctx.cube, (byte*)hash3A, 512,
(const byte*)input + 3*144, size );
LYRA2RE( &hash0[ 0], 32, hash0A, 32, hash0A, 32, 1, 8, 8 );
LYRA2RE( &hash0[32], 32, hash0A+32, 32, hash0A+32, 32, 1, 8, 8 );
LYRA2RE( &hash1[ 0], 32, hash1A, 32, hash1A, 32, 1, 8, 8 );
LYRA2RE( &hash1[32], 32, hash1A+32, 32, hash1A+32, 32, 1, 8, 8 );
LYRA2RE( &hash2[ 0], 32, hash2A, 32, hash2A, 32, 1, 8, 8 );
LYRA2RE( &hash2[32], 32, hash2A+32, 32, hash2A+32, 32, 1, 8, 8 );
LYRA2RE( &hash3[ 0], 32, hash3A, 32, hash3A, 32, 1, 8, 8 );
LYRA2RE( &hash3[32], 32, hash3A+32, 32, hash3A+32, 32, 1, 8, 8 );
phi2_ctx_holder ctx __attribute__ ((aligned (64))); intrlv_4x64_512( hash, hash0, hash1, hash2, hash3 );
// memcpy( &ctx, &phi2_ctx, sizeof(phi2_ctx) );
cubehashInit( &ctx.cube, 512, 16, 32 );
cubehashUpdateDigest( &ctx.cube, (byte*)hashB[0], (const byte*)input,
phi2_has_roots ? 144 : 80 );
cubehashInit( &ctx.cube, 512, 16, 32 );
cubehashUpdateDigest( &ctx.cube, (byte*)hashB[1], (const byte*)input+144,
phi2_has_roots ? 144 : 80 );
cubehashInit( &ctx.cube, 512, 16, 32 );
cubehashUpdateDigest( &ctx.cube, (byte*)hashB[2], (const byte*)input+288,
phi2_has_roots ? 144 : 80 );
cubehashInit( &ctx.cube, 512, 16, 32 );
cubehashUpdateDigest( &ctx.cube, (byte*)hashB[3], (const byte*)input+432,
phi2_has_roots ? 144 : 80 );
LYRA2RE( &hashA[0][0], 32, &hashB[0][0], 32, &hashB[0][0], 32, 1, 8, 8 );
LYRA2RE( &hashA[0][8], 32, &hashB[0][8], 32, &hashB[0][8], 32, 1, 8, 8 );
LYRA2RE( &hashA[1][0], 32, &hashB[1][0], 32, &hashB[1][0], 32, 1, 8, 8 );
LYRA2RE( &hashA[1][8], 32, &hashB[1][8], 32, &hashB[1][8], 32, 1, 8, 8 );
LYRA2RE( &hashA[2][0], 32, &hashB[2][0], 32, &hashB[2][0], 32, 1, 8, 8 );
LYRA2RE( &hashA[2][8], 32, &hashB[2][8], 32, &hashB[2][8], 32, 1, 8, 8 );
LYRA2RE( &hashA[3][0], 32, &hashB[3][0], 32, &hashB[3][0], 32, 1, 8, 8 );
LYRA2RE( &hashA[3][8], 32, &hashB[3][8], 32, &hashB[3][8], 32, 1, 8, 8 );
intrlv_4x64( vhash, hashA[0], hashA[1], hashA[2], hashA[3], 512 );
jh512_4way_init( &ctx.jh ); jh512_4way_init( &ctx.jh );
jh512_4way( &ctx.jh, vhash, 64 ); jh512_4way_update( &ctx.jh, (const void*)hash, 64 );
jh512_4way_close( &ctx.jh, vhash ); jh512_4way_close( &ctx.jh, (void*)hash );
dintrlv_4x64( hash[0], hash[1], hash[2], hash[3], vhash, 512 ); dintrlv_4x64_512( hash0, hash1, hash2, hash3, hash );
if ( hash[0][0] & 1 ) if ( hash0[0] & 1 )
{ {
sph_gost512_init( &ctx.gost ); sph_gost512_init( &ctx.gost );
sph_gost512( &ctx.gost, (const void*)hash[0], 64 ); sph_gost512( &ctx.gost, (const void*)hash0, 64 );
sph_gost512_close( &ctx.gost, (void*)hash[0] ); sph_gost512_close( &ctx.gost, (void*)hash0 );
} }
else else
{ {
init_echo( &ctx.echo, 512 ); echo_full( &ctx.echo, (BitSequence *)hash0, 512,
update_final_echo ( &ctx.echo, (BitSequence *)hash[0], (const BitSequence *)hash0, 64 );
(const BitSequence *)hash[0], 512 ); echo_full( &ctx.echo, (BitSequence *)hash0, 512,
init_echo( &ctx.echo, 512 ); (const BitSequence *)hash0, 64 );
update_final_echo ( &ctx.echo, (BitSequence *)hash[0],
(const BitSequence *)hash[0], 512 );
} }
if ( hash1[0] & 1 )
if ( hash[1][0] & 1 )
{ {
sph_gost512_init( &ctx.gost ); sph_gost512_init( &ctx.gost );
sph_gost512( &ctx.gost, (const void*)hash[1], 64 ); sph_gost512( &ctx.gost, (const void*)hash1, 64 );
sph_gost512_close( &ctx.gost, (void*)hash[1] ); sph_gost512_close( &ctx.gost, (void*)hash1 );
} }
else else
{ {
init_echo( &ctx.echo, 512 ); echo_full( &ctx.echo, (BitSequence *)hash1, 512,
update_final_echo ( &ctx.echo, (BitSequence *)hash[1], (const BitSequence *)hash1, 64 );
(const BitSequence *)hash[1], 512 ); echo_full( &ctx.echo, (BitSequence *)hash1, 512,
init_echo( &ctx.echo, 512 ); (const BitSequence *)hash1, 64 );
update_final_echo ( &ctx.echo, (BitSequence *)hash[1],
(const BitSequence *)hash[1], 512 );
} }
if ( hash2[0] & 1 )
if ( hash[2][0] & 1 )
{ {
sph_gost512_init( &ctx.gost ); sph_gost512_init( &ctx.gost );
sph_gost512( &ctx.gost, (const void*)hash[2], 64 ); sph_gost512( &ctx.gost, (const void*)hash2, 64 );
sph_gost512_close( &ctx.gost, (void*)hash[2] ); sph_gost512_close( &ctx.gost, (void*)hash2 );
} }
else else
{ {
init_echo( &ctx.echo, 512 ); echo_full( &ctx.echo, (BitSequence *)hash2, 512,
update_final_echo ( &ctx.echo, (BitSequence *)hash[2], (const BitSequence *)hash2, 64 );
(const BitSequence *)hash[2], 512 ); echo_full( &ctx.echo, (BitSequence *)hash2, 512,
init_echo( &ctx.echo, 512 ); (const BitSequence *)hash2, 64 );
update_final_echo ( &ctx.echo, (BitSequence *)hash[2],
(const BitSequence *)hash[2], 512 );
} }
if ( hash3[0] & 1 )
if ( hash[3][0] & 1 )
{ {
sph_gost512_init( &ctx.gost ); sph_gost512_init( &ctx.gost );
sph_gost512( &ctx.gost, (const void*)hash[3], 64 ); sph_gost512( &ctx.gost, (const void*)hash3, 64 );
sph_gost512_close( &ctx.gost, (void*)hash[3] ); sph_gost512_close( &ctx.gost, (void*)hash3 );
} }
else else
{ {
init_echo( &ctx.echo, 512 ); echo_full( &ctx.echo, (BitSequence *)hash3, 512,
update_final_echo ( &ctx.echo, (BitSequence *)hash[3], (const BitSequence *)hash3, 64 );
(const BitSequence *)hash[3], 512 ); echo_full( &ctx.echo, (BitSequence *)hash3, 512,
init_echo( &ctx.echo, 512 ); (const BitSequence *)hash3, 64 );
update_final_echo ( &ctx.echo, (BitSequence *)hash[3],
(const BitSequence *)hash[3], 512 );
} }
intrlv_4x64( vhash, hash[0], hash[1], hash[2], hash[3], 512 ); intrlv_4x64_512( hash, hash0, hash1, hash2, hash3 );
skein512_4way_init( &ctx.skein ); skein512_4way_init( &ctx.skein );
skein512_4way( &ctx.skein, vhash, 64 ); skein512_4way_update( &ctx.skein, (const void*)hash, 64 );
skein512_4way_close( &ctx.skein, vhash ); skein512_4way_close( &ctx.skein, (void*)hash );
for (int i=0; i<4; i++)
{
( (uint64_t*)vhash )[i] ^= ( (uint64_t*)vhash )[i+4];
( (uint64_t*)vhash+ 8 )[i] ^= ( (uint64_t*)vhash+ 8 )[i+4];
( (uint64_t*)vhash+16 )[i] ^= ( (uint64_t*)vhash+16 )[i+4];
( (uint64_t*)vhash+24 )[i] ^= ( (uint64_t*)vhash+24 )[i+4];
}
// for ( int i = 0; i < 4; i++ )
// casti_m256i( vhash, i ) = _mm256_xor_si256( casti_m256i( vhash, i ),
// casti_m256i( vhash, i+4 ) );
memcpy( state, vhash, 128 ); for ( int i = 0; i < 4; i++ )
casti_m256i( state, i ) = _mm256_xor_si256( casti_m256i( hash, i ),
casti_m256i( hash, i+4 ) );
} }
int scanhash_phi2_4way( struct work *work, uint32_t max_nonce, int scanhash_phi2_4way( struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr ) uint64_t *hashes_done, struct thr_info *mythr )
{ {
uint32_t _ALIGN(128) hash[8]; uint32_t _ALIGN(128) hash[16*4];
uint32_t _ALIGN(128) edata[36]; uint32_t _ALIGN(128) edata[36*4];
uint32_t vdata[4][36] __attribute__ ((aligned (64)));
uint32_t *hash7 = &(hash[25]);
uint32_t lane_hash[8] __attribute__ ((aligned (32)));
uint32_t *pdata = work->data; uint32_t *pdata = work->data;
uint32_t *ptarget = work->target; uint32_t *ptarget = work->target;
uint32_t *hash7 = &(hash[25]); // 3*8+1
const uint32_t Htarg = ptarget[7]; const uint32_t Htarg = ptarget[7];
const uint32_t first_nonce = pdata[19]; const uint32_t first_nonce = pdata[19];
const uint32_t last_nonce = max_nonce - 4;
uint32_t n = first_nonce; uint32_t n = first_nonce;
int thr_id = mythr->id; // thr_id arg is deprecated const int thr_id = mythr->id;
const bool bench = opt_benchmark;
if(opt_benchmark){ if ( bench ) ptarget[7] = 0x00ff;
ptarget[7] = 0x00ff;
}
// Data is not interleaved, but hash is.
// any non-zero data at index 20 or above sets roots true.
// Split up the operations, bswap first, then set roots.
phi2_has_roots = false;
for ( int i=0; i < 36; i++ )
{
be32enc(&edata[i], pdata[i]);
if (i >= 20 && pdata[i]) phi2_has_roots = true;
}
/*
casti_m256i( vdata[0], 0 ) = mm256_bswap_32( casti_m256i( pdata, 0 ) );
casti_m256i( vdata[0], 1 ) = mm256_bswap_32( casti_m256i( pdata, 1 ) );
casti_m256i( vdata[0], 2 ) = mm256_bswap_32( casti_m256i( pdata, 2 ) );
casti_m256i( vdata[0], 3 ) = mm256_bswap_32( casti_m256i( pdata, 3 ) );
casti_m128i( vdata[0], 8 ) = mm128_bswap_32( casti_m128i( pdata, 8 ) );
phi2_has_roots = mm128_anybits1( casti_m128i( vdata[0], 5 ) ) ||
mm128_anybits1( casti_m128i( vdata[0], 6 ) ) ||
mm128_anybits1( casti_m128i( vdata[0], 7 ) ) ||
mm128_anybits1( casti_m128i( vdata[0], 8 ) );
*/
memcpy( vdata[0], edata, 144 );
memcpy( vdata[1], edata, 144 );
memcpy( vdata[2], edata, 144 );
memcpy( vdata[3], edata, 144 );
do {
be32enc( &vdata[0][19], n );
be32enc( &vdata[1][19], n+1 );
be32enc( &vdata[2][19], n+2 );
be32enc( &vdata[3][19], n+3 );
phi2_hash_4way( hash, vdata );
for ( int lane = 0; lane < 4; lane++ ) if ( hash7[ lane<<1 ] < Htarg )
{
extr_lane_4x64( lane_hash, hash, lane, 256 );
if ( fulltest( lane_hash, ptarget ) && !opt_benchmark )
{
pdata[19] = n + lane;
submit_lane_solution( work, lane_hash, mythr, lane );
}
}
n += 4;
} while ( ( n < max_nonce - 4 ) && !work_restart[thr_id].restart );
*hashes_done = n - first_nonce + 1;
return 0;
}
#endif // PHI2_4WAY phi2_has_roots = false;
for ( int i = 0; i < 36; i++ )
{
be32enc( &edata[i], pdata[i] );
edata[ i+36 ] = edata[ i+72 ] = edata[ i+108 ] = edata[i];
if ( i >= 20 && pdata[i] ) phi2_has_roots = true;
}
edata[ 19 ] = n;
edata[ 36 + 19 ] = n+1;
edata[ 2*36 + 19 ] = n+2;
edata[ 3*36 + 19 ] = n+3;
do {
phi2_4way_hash( hash, edata );
for ( int lane = 0; lane < 4; lane++ )
if ( unlikely( hash7[ lane<<1 ] <= Htarg && !bench ) )
{
uint64_t _ALIGN(64) lane_hash[8];
extr_lane_4x64( lane_hash, hash, lane, 256 );
if ( valid_hash( lane_hash, ptarget ) )
{
be32enc( pdata + 19, n + lane );
submit_solution( work, lane_hash, mythr );
}
}
edata[ 19 ] += 4;
edata[ 36 + 19 ] += 4;
edata[ 2*36 + 19 ] += 4;
edata[ 3*36 + 19 ] += 4;
n +=4;
} while ( (n < last_nonce) && !work_restart[thr_id].restart);
pdata[19] = n;
*hashes_done = n - first_nonce;
return 0;
}
#endif

Some files were not shown because too many files have changed in this diff Show More