From bc11937502d88a4702797a064c19dae318178200 Mon Sep 17 00:00:00 2001 From: Ugochukwu Mmaduekwe Date: Thu, 9 Jul 2026 14:45:54 +0100 Subject: [PATCH 1/6] Vertical ChaCha SIMD kernels + IBulkStreamCipher 512B AEAD + shared stream tests Kernels / engines: - Replace the row-layout ChaCha AVX2 kernels with vertical (word-per-lane) kernels: SSE2/SSSE3 4-way (256B) and AVX2 8-way (512B), on x86_64 and i386; retire the old row kernels. - Add TChaChaBaseEngine as the shared ChaCha core (block function + the 512/256/128/64B dispatch ladder). TChaCha7539Engine and the legacy DJB TChaChaEngine derive from it and differ only in counter width: one CHACHA_CTR64-parameterized kernel serves both variants (DJB advances the 64-bit counter; a WideBlocksSafe guard drops a tier near the low-word wrap). IBulkStreamCipher: - Add ClpIBulkStreamCipher, the stream analog of IBulkBlockCipher. TSalsa20Engine and TChaChaBaseEngine implement ProcessBlocks(count) via a virtual DoProcessBlocks ladder (Salsa 2->1, ChaCha 8->4->2->1) with pointer-form *Fast inner helpers. - TChaCha20Poly1305 resolves it and processes the AEAD body 512 bytes (8-way) per call instead of the interface-capped 256, keeping the same running-count bookkeeping. ~40% AEAD throughput on large buffers (16MB: 690 -> 982 MB/s). Tests: - Add TStreamCipherTestBase (engine-factory + label hooks, AES-test pattern) with reusable whole-vs-chunked, ProcessBytes-vs-ReturnByte and bulk-vs-single-block checks. Reparent the Salsa20 / XSalsa20 / ChaCha (DJB) / ChaCha7539 / XChaCha20 suites onto it, keeping their KAT vectors and dropping the duplicated per-suite harnesses. --- .../Delphi/CryptoLib.BenchmarkConsole.dpr | 1 + .../Delphi.Examples/CryptoLib.Examples.dpr | 1 + .../Delphi.Tests/CryptoLib.Tests.Mobile.dpr | 4 +- .../Delphi.Tests/CryptoLib.Tests.Mobile.dproj | 4 +- .../Delphi.Tests/CryptoLib.Tests.dpr | 4 +- .../FreePascal.Tests/CryptoLib.Tests.lpi | 8 +- .../FreePascal.Tests/CryptoLib.lpr | 2 +- .../FreePascal.Tests/CryptoLibConsole.lpi | 8 +- .../FreePascal.Tests/CryptoLibConsole.lpr | 2 +- .../Crypto/ChaCha7539ProcessBlocks2Tests.pas | 184 ------ .../src/Crypto/ChaCha7539Tests.pas | 84 +++ CryptoLib.Tests/src/Crypto/ChaChaTests.pas | 34 +- CryptoLib.Tests/src/Crypto/Salsa20Tests.pas | 71 ++- .../src/Crypto/StreamCipherTestBase.pas | 213 +++++++ CryptoLib.Tests/src/Crypto/XChaCha20Tests.pas | 80 ++- CryptoLib.Tests/src/Crypto/XSalsa20Tests.pas | 34 +- .../Crypto/Engines/ClpChaCha7539Engine.pas | 289 +--------- .../src/Crypto/Engines/ClpChaChaEngine.pas | 522 ++++++++++++++--- .../src/Crypto/Engines/ClpChaChaSimd.pas | 28 +- .../Crypto/Engines/ClpChaChaX86Backend.pas | 124 +++- .../src/Crypto/Engines/ClpSalsa20Engine.pas | 90 ++- .../src/Crypto/Modes/ClpChaCha20Poly1305.pas | 41 ++ .../ChaCha/ChaCha7539Blocks4Sse2_i386.inc | 531 ++++++++++++++++++ .../ChaCha/ChaCha7539Blocks4Sse2_x86_64.inc | 460 +++++++++++++++ .../ChaCha/ChaCha7539Blocks4Ssse3_i386.inc | 493 ++++++++++++++++ .../ChaCha/ChaCha7539Blocks4Ssse3_x86_64.inc | 422 ++++++++++++++ .../ChaCha/ChaCha7539Blocks8Avx2_x86_64.inc | 448 +++++++++++++++ .../ChaCha7539ProcessBlocks2Avx2_i386.inc | 16 - .../ChaCha7539ProcessBlocks2Avx2_x86_64.inc | 13 - .../ChaCha7539ProcessBlocks4Avx2_i386.inc | 27 - .../ChaCha7539ProcessBlocks4Avx2_x86_64.inc | 24 - .../ChaCha7539_Avx2_128B_LoadState_i386.inc | 27 - .../ChaCha7539_Avx2_128B_LoadState_x86_64.inc | 27 - .../ChaCha7539_Avx2_128B_XorStore_i386.inc | 26 - .../ChaCha7539_Avx2_128B_XorStore_x86_64.inc | 26 - .../ChaCha/ChaCha7539_Avx2_DoubleRound.inc | 57 -- .../Crypto/ClpIBulkStreamCipher.pas | 53 ++ .../Delphi/CryptoLib4PascalPackage.dpk | 1 + .../Packages/FPC/CryptoLib4PascalPackage.lpk | 6 +- .../Packages/FPC/CryptoLib4PascalPackage.pas | 2 +- 40 files changed, 3575 insertions(+), 912 deletions(-) delete mode 100644 CryptoLib.Tests/src/Crypto/ChaCha7539ProcessBlocks2Tests.pas create mode 100644 CryptoLib.Tests/src/Crypto/ChaCha7539Tests.pas create mode 100644 CryptoLib.Tests/src/Crypto/StreamCipherTestBase.pas create mode 100644 CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Sse2_i386.inc create mode 100644 CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Sse2_x86_64.inc create mode 100644 CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Ssse3_i386.inc create mode 100644 CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Ssse3_x86_64.inc create mode 100644 CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks8Avx2_x86_64.inc delete mode 100644 CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks2Avx2_i386.inc delete mode 100644 CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks2Avx2_x86_64.inc delete mode 100644 CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks4Avx2_i386.inc delete mode 100644 CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks4Avx2_x86_64.inc delete mode 100644 CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_LoadState_i386.inc delete mode 100644 CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_LoadState_x86_64.inc delete mode 100644 CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_XorStore_i386.inc delete mode 100644 CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_XorStore_x86_64.inc delete mode 100644 CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_DoubleRound.inc create mode 100644 CryptoLib/src/Interfaces/Crypto/ClpIBulkStreamCipher.pas diff --git a/CryptoLib.Benchmark/Delphi/CryptoLib.BenchmarkConsole.dpr b/CryptoLib.Benchmark/Delphi/CryptoLib.BenchmarkConsole.dpr index f1ccdfd7..ad1ad510 100644 --- a/CryptoLib.Benchmark/Delphi/CryptoLib.BenchmarkConsole.dpr +++ b/CryptoLib.Benchmark/Delphi/CryptoLib.BenchmarkConsole.dpr @@ -658,6 +658,7 @@ uses ClpIBlockCipherMode in '..\..\CryptoLib\src\Interfaces\Crypto\Modes\ClpIBlockCipherMode.pas', ClpIBulkBlockCipherMode in '..\..\CryptoLib\src\Interfaces\Crypto\Modes\ClpIBulkBlockCipherMode.pas', ClpIBulkBlockCipher in '..\..\CryptoLib\src\Interfaces\Crypto\ClpIBulkBlockCipher.pas', + ClpIBulkStreamCipher in '..\..\CryptoLib\src\Interfaces\Crypto\ClpIBulkStreamCipher.pas', ClpIEcbBlockCipher in '..\..\CryptoLib\src\Interfaces\Crypto\Modes\ClpIEcbBlockCipher.pas', ClpEcbBlockCipher in '..\..\CryptoLib\src\Crypto\Modes\ClpEcbBlockCipher.pas', ClpGnuObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Gnu\ClpGnuObjectIdentifiers.pas', diff --git a/CryptoLib.Examples/Delphi.Examples/CryptoLib.Examples.dpr b/CryptoLib.Examples/Delphi.Examples/CryptoLib.Examples.dpr index a370cb5d..a0be813e 100644 --- a/CryptoLib.Examples/Delphi.Examples/CryptoLib.Examples.dpr +++ b/CryptoLib.Examples/Delphi.Examples/CryptoLib.Examples.dpr @@ -674,6 +674,7 @@ uses ClpIBlockCipherMode in '..\..\CryptoLib\src\Interfaces\Crypto\Modes\ClpIBlockCipherMode.pas', ClpIBulkBlockCipherMode in '..\..\CryptoLib\src\Interfaces\Crypto\Modes\ClpIBulkBlockCipherMode.pas', ClpIBulkBlockCipher in '..\..\CryptoLib\src\Interfaces\Crypto\ClpIBulkBlockCipher.pas', + ClpIBulkStreamCipher in '..\..\CryptoLib\src\Interfaces\Crypto\ClpIBulkStreamCipher.pas', ClpIEcbBlockCipher in '..\..\CryptoLib\src\Interfaces\Crypto\Modes\ClpIEcbBlockCipher.pas', ClpEcbBlockCipher in '..\..\CryptoLib\src\Crypto\Modes\ClpEcbBlockCipher.pas', ClpGnuObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Gnu\ClpGnuObjectIdentifiers.pas', diff --git a/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dpr b/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dpr index 575fd462..35178dd1 100644 --- a/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dpr +++ b/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dpr @@ -655,6 +655,7 @@ uses ClpIBlockCipherMode in '..\..\CryptoLib\src\Interfaces\Crypto\Modes\ClpIBlockCipherMode.pas', ClpIBulkBlockCipherMode in '..\..\CryptoLib\src\Interfaces\Crypto\Modes\ClpIBulkBlockCipherMode.pas', ClpIBulkBlockCipher in '..\..\CryptoLib\src\Interfaces\Crypto\ClpIBulkBlockCipher.pas', + ClpIBulkStreamCipher in '..\..\CryptoLib\src\Interfaces\Crypto\ClpIBulkStreamCipher.pas', ClpIEcbBlockCipher in '..\..\CryptoLib\src\Interfaces\Crypto\Modes\ClpIEcbBlockCipher.pas', ClpEcbBlockCipher in '..\..\CryptoLib\src\Crypto\Modes\ClpEcbBlockCipher.pas', ClpGnuObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Gnu\ClpGnuObjectIdentifiers.pas', @@ -890,7 +891,8 @@ uses SecP256R1FieldTests in '..\src\Math\EC\Custom\Sec\SecP256R1FieldTests.pas', Salsa20Tests in '..\src\Crypto\Salsa20Tests.pas', ChaChaTests in '..\src\Crypto\ChaChaTests.pas', - ChaCha7539ProcessBlocks2Tests in '..\src\Crypto\ChaCha7539ProcessBlocks2Tests.pas', + ChaCha7539Tests in '..\src\Crypto\ChaCha7539Tests.pas', + StreamCipherTestBase in '..\src\Crypto\StreamCipherTestBase.pas', HChaCha20Tests in '..\src\Crypto\HChaCha20Tests.pas', XChaCha20Tests in '..\src\Crypto\XChaCha20Tests.pas', XChaCha20Poly1305Tests in '..\src\Crypto\XChaCha20Poly1305Tests.pas', diff --git a/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dproj b/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dproj index f0c8319e..9c815f7a 100644 --- a/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dproj +++ b/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dproj @@ -998,6 +998,7 @@ + @@ -1228,7 +1229,8 @@ - + + diff --git a/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr b/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr index 261747d0..c7e20866 100644 --- a/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr +++ b/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr @@ -674,6 +674,7 @@ uses ClpIBlockCipherMode in '..\..\CryptoLib\src\Interfaces\Crypto\Modes\ClpIBlockCipherMode.pas', ClpIBulkBlockCipherMode in '..\..\CryptoLib\src\Interfaces\Crypto\Modes\ClpIBulkBlockCipherMode.pas', ClpIBulkBlockCipher in '..\..\CryptoLib\src\Interfaces\Crypto\ClpIBulkBlockCipher.pas', + ClpIBulkStreamCipher in '..\..\CryptoLib\src\Interfaces\Crypto\ClpIBulkStreamCipher.pas', ClpIEcbBlockCipher in '..\..\CryptoLib\src\Interfaces\Crypto\Modes\ClpIEcbBlockCipher.pas', ClpEcbBlockCipher in '..\..\CryptoLib\src\Crypto\Modes\ClpEcbBlockCipher.pas', ClpGnuObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Gnu\ClpGnuObjectIdentifiers.pas', @@ -909,7 +910,8 @@ uses SecP256R1FieldTests in '..\src\Math\EC\Custom\Sec\SecP256R1FieldTests.pas', Salsa20Tests in '..\src\Crypto\Salsa20Tests.pas', ChaChaTests in '..\src\Crypto\ChaChaTests.pas', - ChaCha7539ProcessBlocks2Tests in '..\src\Crypto\ChaCha7539ProcessBlocks2Tests.pas', + ChaCha7539Tests in '..\src\Crypto\ChaCha7539Tests.pas', + StreamCipherTestBase in '..\src\Crypto\StreamCipherTestBase.pas', HChaCha20Tests in '..\src\Crypto\HChaCha20Tests.pas', XChaCha20Tests in '..\src\Crypto\XChaCha20Tests.pas', XChaCha20Poly1305Tests in '..\src\Crypto\XChaCha20Poly1305Tests.pas', diff --git a/CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi b/CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi index 4ec355e6..abd65594 100644 --- a/CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi +++ b/CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi @@ -79,7 +79,7 @@ - + @@ -618,7 +618,7 @@ - + @@ -845,6 +845,10 @@ + + + + diff --git a/CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr b/CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr index cf4d0936..16ccb173 100644 --- a/CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr +++ b/CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr @@ -18,7 +18,7 @@ IESCipherTests, HMacTests, Pkcs5Tests, HkdfGeneratorTests, ECIESTests, PascalCoinECIESTests, ECNRTests, PrimesTests, ECEncodingTests, GF256AesTests, PaddingTests, DSATests, DeterministicDsaTests, Salsa20Tests, XSalsa20Tests, - ChaChaTests, ChaCha7539ProcessBlocks2Tests, HChaCha20Tests, XChaCha20Tests, + ChaChaTests, ChaCha7539Tests, StreamCipherTestBase, HChaCha20Tests, XChaCha20Tests, XChaCha20Poly1305Tests, StreamCipherResetTests, CTSTests, X25519Tests, X448Tests, Ed25519Tests, Ed448Tests, X25519HigherLevelTests, Ed25519HigherLevelTests, ShortenedDigestTests, Kdf1GeneratorTests, diff --git a/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpi b/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpi index ce438b02..a7f291f4 100644 --- a/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpi +++ b/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpi @@ -39,7 +39,7 @@ - + @@ -577,7 +577,7 @@ - + @@ -804,6 +804,10 @@ + + + + diff --git a/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr b/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr index 059fb17a..35b33c6c 100644 --- a/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr +++ b/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr @@ -19,7 +19,7 @@ IESCipherTests, HMacTests, Pkcs5Tests, HkdfGeneratorTests, ECIESTests, PascalCoinECIESTests, ECNRTests, PrimesTests, ECEncodingTests, GF256AesTests, PaddingTests, DSATests, DeterministicDsaTests, Salsa20Tests, XSalsa20Tests, - ChaChaTests, ChaCha7539ProcessBlocks2Tests, HChaCha20Tests, XChaCha20Tests, + ChaChaTests, ChaCha7539Tests, StreamCipherTestBase, HChaCha20Tests, XChaCha20Tests, XChaCha20Poly1305Tests, StreamCipherResetTests, CTSTests, X25519Tests, X448Tests, Ed25519Tests, Ed448Tests, X25519HigherLevelTests, Ed25519HigherLevelTests, Curve25519KeyUtilitiesTests, ShortenedDigestTests, diff --git a/CryptoLib.Tests/src/Crypto/ChaCha7539ProcessBlocks2Tests.pas b/CryptoLib.Tests/src/Crypto/ChaCha7539ProcessBlocks2Tests.pas deleted file mode 100644 index 526c8e65..00000000 --- a/CryptoLib.Tests/src/Crypto/ChaCha7539ProcessBlocks2Tests.pas +++ /dev/null @@ -1,184 +0,0 @@ -{ *********************************************************************************** } -{ * CryptoLib Library * } -{ * Author - Ugochukwu Mmaduekwe * } -{ * Github Repository * } -{ * * } -{ * Distributed under the MIT software license, see the accompanying file LICENSE * } -{ * or visit http://www.opensource.org/licenses/mit-license.php. * } -{ * * } -{ * Acknowledgements: * } -{ * * } -{ * Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring * } -{ * the development of this library * } -{ * ******************************************************************************* * } - -(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *) - -unit ChaCha7539ProcessBlocks2Tests; - -interface - -{$IFDEF FPC} -{$MODE DELPHI} -{$ENDIF FPC} - -uses - SysUtils, -{$IFDEF FPC} - fpcunit, - testregistry, -{$ELSE} - TestFramework, -{$ENDIF FPC} - ClpChaCha7539Engine, - ClpIKeyParameter, - ClpKeyParameter, - ClpParametersWithIV, - ClpIParametersWithIV, - CryptoLibTestBase; - -type - - TTestChaCha7539ProcessBlocks2 = class(TCryptoLibAlgorithmTestCase) - published - procedure Test128ByteProcessBlocks2VsTwoBlockCalls; - procedure Test256ByteProcessBlocks4VsTwoProcessBlocks2; - procedure TestProcessBytesVsReturnByte; - end; - -implementation - -{ TTestChaCha7539ProcessBlocks2 } - -procedure TTestChaCha7539ProcessBlocks2.Test128ByteProcessBlocks2VsTwoBlockCalls; -var - LKey, LNonce, LIn, LOutA, LOutB: TBytes; - LParams: IParametersWithIV; - LA, LB: TChaCha7539Engine; - LIdx: Int32; -begin - LKey := DecodeHex('000102030405060708090A0B0C0D0E0F' + - '101112131415161718191A1B1C1D1E1F'); - LNonce := DecodeHex('00000000000000000000000A'); - LParams := TParametersWithIV.Create( - TKeyParameter.Create(LKey) as IKeyParameter, LNonce); - SetLength(LIn, 128); - for LIdx := 0 to 127 do - begin - LIn[LIdx] := Byte(LIdx); - end; - SetLength(LOutA, 128); - SetLength(LOutB, 128); - LA := TChaCha7539Engine.Create; - try - LA.Init(True, LParams); - LA.ProcessBlocks2(LIn, 0, LOutA, 0); - finally - LA.Free; - end; - LB := TChaCha7539Engine.Create; - try - LB.Init(True, LParams); - LB.ProcessBlock(LIn, 0, LOutB, 0); - LB.ProcessBlock(LIn, 64, LOutB, 64); - finally - LB.Free; - end; - if not AreEqual(LOutA, LOutB) then - begin - Fail('ChaCha7539 128B stream mismatch'); - end; -end; - -procedure TTestChaCha7539ProcessBlocks2.Test256ByteProcessBlocks4VsTwoProcessBlocks2; -var - LKey, LNonce, LIn, LOutA, LOutB: TBytes; - LParams: IParametersWithIV; - LA, LB: TChaCha7539Engine; - LIdx: Int32; -begin - LKey := DecodeHex('000102030405060708090A0B0C0D0E0F' + - '101112131415161718191A1B1C1D1E1F'); - LNonce := DecodeHex('00000000000000000000000A'); - LParams := TParametersWithIV.Create( - TKeyParameter.Create(LKey) as IKeyParameter, LNonce); - SetLength(LIn, 256); - for LIdx := 0 to 255 do - begin - LIn[LIdx] := Byte(LIdx); - end; - SetLength(LOutA, 256); - SetLength(LOutB, 256); - LA := TChaCha7539Engine.Create; - try - LA.Init(True, LParams); - LA.ProcessBlocks4(LIn, 0, LOutA, 0); - finally - LA.Free; - end; - LB := TChaCha7539Engine.Create; - try - LB.Init(True, LParams); - LB.ProcessBlocks2(LIn, 0, LOutB, 0); - LB.ProcessBlocks2(LIn, 128, LOutB, 128); - finally - LB.Free; - end; - if not AreEqual(LOutA, LOutB) then - begin - Fail('ChaCha7539 256B ProcessBlocks4 vs two ProcessBlocks2 mismatch'); - end; -end; - -procedure TTestChaCha7539ProcessBlocks2.TestProcessBytesVsReturnByte; -const - CLen = 300; -var - LKey, LNonce, LIn, LOutA, LOutB: TBytes; - LParams: IParametersWithIV; - LA, LB: TChaCha7539Engine; - LIdx: Int32; -begin - LKey := DecodeHex('000102030405060708090A0B0C0D0E0F' + - '101112131415161718191A1B1C1D1E1F'); - LNonce := DecodeHex('00000000000000000000000A'); - LParams := TParametersWithIV.Create( - TKeyParameter.Create(LKey) as IKeyParameter, LNonce); - SetLength(LIn, CLen); - for LIdx := 0 to CLen - 1 do - begin - LIn[LIdx] := Byte(LIdx * 3 + 17); - end; - SetLength(LOutA, CLen); - SetLength(LOutB, CLen); - LA := TChaCha7539Engine.Create; - try - LA.Init(True, LParams); - LA.ProcessBytes(LIn, 0, CLen, LOutA, 0); - finally - LA.Free; - end; - LB := TChaCha7539Engine.Create; - try - LB.Init(True, LParams); - for LIdx := 0 to CLen - 1 do - begin - LOutB[LIdx] := Byte(LB.ReturnByte(LIn[LIdx])); - end; - finally - LB.Free; - end; - if not AreEqual(LOutA, LOutB) then - begin - Fail('ChaCha7539 ProcessBytes vs ReturnByte stream mismatch'); - end; -end; - -initialization -{$IFDEF FPC} - RegisterTest(TTestChaCha7539ProcessBlocks2); -{$ELSE} - RegisterTest(TTestChaCha7539ProcessBlocks2.Suite); -{$ENDIF FPC} - -end. diff --git a/CryptoLib.Tests/src/Crypto/ChaCha7539Tests.pas b/CryptoLib.Tests/src/Crypto/ChaCha7539Tests.pas new file mode 100644 index 00000000..9d287684 --- /dev/null +++ b/CryptoLib.Tests/src/Crypto/ChaCha7539Tests.pas @@ -0,0 +1,84 @@ +{ *********************************************************************************** } +{ * CryptoLib Library * } +{ * Author - Ugochukwu Mmaduekwe * } +{ * Github Repository * } +{ * * } +{ * Distributed under the MIT software license, see the accompanying file LICENSE * } +{ * or visit http://www.opensource.org/licenses/mit-license.php. * } +{ * * } +{ * Acknowledgements: * } +{ * * } +{ * Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring * } +{ * the development of this library * } +{ * ******************************************************************************* * } + +(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *) + +unit ChaCha7539Tests; + +interface + +{$IFDEF FPC} +{$MODE DELPHI} +{$ENDIF FPC} + +uses +{$IFDEF FPC} + testregistry, +{$ELSE} + TestFramework, +{$ENDIF FPC} + ClpIStreamCipher, + ClpChaCha7539Engine, + StreamCipherTestBase; + +type + // RFC 7539 keystream is validated against fixed vectors through the AEAD suites; + // here the shared base covers the engine-agnostic properties (whole-vs-chunked, + // ProcessBytes-vs-ReturnByte, bulk-vs-single-block, SIMD-vs-scalar). + TTestChaCha7539 = class(TStreamCipherTestBase) + strict protected + function GetEngineFactory: TStreamCipherFactory; override; + function EngineLabel: String; override; + function KeySizeInBytes: Int32; override; + function NonceSizeInBytes: Int32; override; + end; + +implementation + +function CreateChaCha7539Engine: IStreamCipher; +begin + Result := TChaCha7539Engine.Create() as IStreamCipher; +end; + +{ TTestChaCha7539 } + +function TTestChaCha7539.GetEngineFactory: TStreamCipherFactory; +begin + Result := CreateChaCha7539Engine; +end; + +function TTestChaCha7539.EngineLabel: String; +begin + Result := 'ChaCha7539'; +end; + +function TTestChaCha7539.KeySizeInBytes: Int32; +begin + Result := 32; +end; + +function TTestChaCha7539.NonceSizeInBytes: Int32; +begin + Result := 12; +end; + +initialization + +{$IFDEF FPC} + RegisterTest(TTestChaCha7539); +{$ELSE} + RegisterTest(TTestChaCha7539.Suite); +{$ENDIF FPC} + +end. diff --git a/CryptoLib.Tests/src/Crypto/ChaChaTests.pas b/CryptoLib.Tests/src/Crypto/ChaChaTests.pas index 62675214..d020089c 100644 --- a/CryptoLib.Tests/src/Crypto/ChaChaTests.pas +++ b/CryptoLib.Tests/src/Crypto/ChaChaTests.pas @@ -32,12 +32,14 @@ interface {$ENDIF FPC} ClpChaChaEngine, ClpIChaChaEngine, + ClpIStreamCipher, ClpICipherParameters, ClpKeyParameter, ClpIKeyParameter, ClpParametersWithIV, ClpIParametersWithIV, ClpCryptoLibTypes, + StreamCipherTestBase, CryptoLibTestBase, ChaChaPoly1305Vectors; @@ -52,7 +54,12 @@ interface /// estreambench-20080905. /// /// - TTestChaCha = class(TCryptoLibAlgorithmTestCase) + TTestChaCha = class(TStreamCipherTestBase) + strict protected + function GetEngineFactory: TStreamCipherFactory; override; + function EngineLabel: String; override; + function KeySizeInBytes: Int32; override; + function NonceSizeInBytes: Int32; override; private var FZeroes: TBytes; @@ -79,8 +86,33 @@ TTestChaCha = class(TCryptoLibAlgorithmTestCase) implementation +function CreateChaChaEngine: IStreamCipher; +begin + Result := TChaChaEngine.Create() as IStreamCipher; +end; + { TTestChaCha } +function TTestChaCha.GetEngineFactory: TStreamCipherFactory; +begin + Result := CreateChaChaEngine; +end; + +function TTestChaCha.EngineLabel: String; +begin + Result := 'ChaCha20'; +end; + +function TTestChaCha.KeySizeInBytes: Int32; +begin + Result := 32; +end; + +function TTestChaCha.NonceSizeInBytes: Int32; +begin + Result := 8; +end; + function TTestChaCha.GetCheckpointHex(const ASet: TChaChaKeystreamSet; AByteOffset: Integer): string; var diff --git a/CryptoLib.Tests/src/Crypto/Salsa20Tests.pas b/CryptoLib.Tests/src/Crypto/Salsa20Tests.pas index f56c8752..0778cb09 100644 --- a/CryptoLib.Tests/src/Crypto/Salsa20Tests.pas +++ b/CryptoLib.Tests/src/Crypto/Salsa20Tests.pas @@ -32,17 +32,24 @@ interface {$ENDIF FPC} ClpSalsa20Engine, ClpISalsa20Engine, + ClpIStreamCipher, ClpICipherParameters, ClpKeyParameter, ClpIKeyParameter, ClpParametersWithIV, ClpIParametersWithIV, ClpCryptoLibTypes, + StreamCipherTestBase, CryptoLibTestBase; type - TTestSalsa20 = class(TCryptoLibAlgorithmTestCase) + TTestSalsa20 = class(TStreamCipherTestBase) + strict protected + function GetEngineFactory: TStreamCipherFactory; override; + function EngineLabel: String; override; + function KeySizeInBytes: Int32; override; + function NonceSizeInBytes: Int32; override; private var FZeroes: TBytes; @@ -68,14 +75,38 @@ TTestSalsa20 = class(TCryptoLibAlgorithmTestCase) procedure TestSalsa20Test1; procedure TestSalsa20Test2; procedure TestReInitBug; - procedure TestProcessBytesVsReturnByte; end; implementation +function CreateSalsa20Engine: IStreamCipher; +begin + Result := TSalsa20Engine.Create() as IStreamCipher; +end; + { TTestSalsa20 } +function TTestSalsa20.GetEngineFactory: TStreamCipherFactory; +begin + Result := CreateSalsa20Engine; +end; + +function TTestSalsa20.EngineLabel: String; +begin + Result := 'Salsa20'; +end; + +function TTestSalsa20.KeySizeInBytes: Int32; +begin + Result := 32; +end; + +function TTestSalsa20.NonceSizeInBytes: Int32; +begin + Result := 8; +end; + procedure TTestSalsa20.SetUp; begin inherited; @@ -354,42 +385,6 @@ procedure TTestSalsa20.TestReInitBug; end; end; -procedure TTestSalsa20.TestProcessBytesVsReturnByte; -const - CLen = 400; -var - LKey, LNonce, LIn, LOutA, LOutB: TBytes; - LParams: IParametersWithIV; - LA, LB: ISalsa20Engine; - LIdx: Int32; -begin - LKey := DecodeHex('000102030405060708090A0B0C0D0E0F' + - '101112131415161718191A1B1C1D1E1F'); - LNonce := DecodeHex('0000000000000000'); - LParams := TParametersWithIV.Create( - TKeyParameter.Create(LKey) as IKeyParameter, LNonce); - SetLength(LIn, CLen); - for LIdx := 0 to CLen - 1 do - begin - LIn[LIdx] := Byte(LIdx * 5 + 11); - end; - SetLength(LOutA, CLen); - SetLength(LOutB, CLen); - LA := TSalsa20Engine.Create(); - LA.Init(True, LParams); - LA.ProcessBytes(LIn, 0, CLen, LOutA, 0); - LB := TSalsa20Engine.Create(); - LB.Init(True, LParams); - for LIdx := 0 to CLen - 1 do - begin - LOutB[LIdx] := Byte(LB.ReturnByte(LIn[LIdx])); - end; - if not AreEqual(LOutA, LOutB) then - begin - Fail('Salsa20 ProcessBytes vs ReturnByte stream mismatch'); - end; -end; - initialization // Register any test cases with the test runner diff --git a/CryptoLib.Tests/src/Crypto/StreamCipherTestBase.pas b/CryptoLib.Tests/src/Crypto/StreamCipherTestBase.pas new file mode 100644 index 00000000..a92f6fdb --- /dev/null +++ b/CryptoLib.Tests/src/Crypto/StreamCipherTestBase.pas @@ -0,0 +1,213 @@ +{ *********************************************************************************** } +{ * CryptoLib Library * } +{ * Author - Ugochukwu Mmaduekwe * } +{ * Github Repository * } +{ * * } +{ * Distributed under the MIT software license, see the accompanying file LICENSE * } +{ * or visit http://www.opensource.org/licenses/mit-license.php. * } +{ * * } +{ * Acknowledgements: * } +{ * * } +{ * Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring * } +{ * the development of this library * } +{ * ******************************************************************************* * } + +(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *) + +unit StreamCipherTestBase; + +interface + +{$IFDEF FPC} +{$MODE DELPHI} +{$ENDIF FPC} + +uses + SysUtils, +{$IFDEF FPC} + fpcunit, +{$ELSE} + TestFramework, +{$ENDIF FPC} + ClpIStreamCipher, + ClpIBulkStreamCipher, + ClpICipherParameters, + ClpKeyParameter, + ClpIKeyParameter, + ClpParametersWithIV, + ClpIParametersWithIV, + ClpCryptoLibTypes, + CryptoLibTestBase; + +type + TStreamCipherFactory = function: IStreamCipher; + + /// + /// Base for the Salsa/ChaCha stream-cipher suites. A concrete suite supplies an + /// engine factory + label + key/nonce sizes; the reusable runners below cover the + /// engine-agnostic properties (whole-vs-chunked, ProcessBytes-vs-ReturnByte, + /// bulk-vs-single-block). Concrete suites add their own KAT vectors. + /// + TStreamCipherTestBase = class(TCryptoLibAlgorithmTestCase) + strict protected + function GetEngineFactory: TStreamCipherFactory; virtual; abstract; + function EngineLabel: String; virtual; abstract; + function KeySizeInBytes: Int32; virtual; abstract; + function NonceSizeInBytes: Int32; virtual; abstract; + + function SampleBytes(ALen, ASeed: Int32): TBytes; + function InitEngine(const ACreateEngine: TStreamCipherFactory; + const AKey, ANonce: TBytes): IStreamCipher; + + // Reusable property checks, each taking the factory + label (house pattern). + procedure RunWholeVsChunked(const ACreateEngine: TStreamCipherFactory; + const AEngineLabel: String); + procedure RunProcessBytesVsReturnByte(const ACreateEngine: TStreamCipherFactory; + const AEngineLabel: String); + procedure RunBulkBlocksVsSingleBlock(const ACreateEngine: TStreamCipherFactory; + const AEngineLabel: String); + published + procedure TestWholeVsChunked; + procedure TestProcessBytesVsReturnByte; + procedure TestBulkBlocksVsSingleBlock; + end; + +implementation + +{ TStreamCipherTestBase } + +function TStreamCipherTestBase.SampleBytes(ALen, ASeed: Int32): TBytes; +var + LI: Int32; +begin + System.SetLength(Result, ALen); + for LI := 0 to ALen - 1 do + Result[LI] := Byte((LI * ASeed + (ASeed shr 1)) and $FF); +end; + +function TStreamCipherTestBase.InitEngine( + const ACreateEngine: TStreamCipherFactory; const AKey, ANonce: TBytes): IStreamCipher; +begin + Result := ACreateEngine(); + Result.Init(True, TParametersWithIV.Create( + TKeyParameter.Create(AKey) as IKeyParameter, ANonce) as IParametersWithIV); +end; + +// Processing a buffer in one call must equal processing it in ragged chunks. +procedure TStreamCipherTestBase.RunWholeVsChunked( + const ACreateEngine: TStreamCipherFactory; const AEngineLabel: String); +const + LTotal = 1500; +var + LKey, LNonce, LIn, LWhole, LChunk: TBytes; + LEng: IStreamCipher; + LOff, LStep: Int32; +begin + LKey := SampleBytes(KeySizeInBytes, 7); + LNonce := SampleBytes(NonceSizeInBytes, 11); + LIn := SampleBytes(LTotal, 31); + System.SetLength(LWhole, LTotal); + System.SetLength(LChunk, LTotal); + + LEng := InitEngine(ACreateEngine, LKey, LNonce); + LEng.ProcessBytes(LIn, 0, LTotal, LWhole, 0); + + LEng := InitEngine(ACreateEngine, LKey, LNonce); + LOff := 0; + LStep := 1; + while LOff < LTotal do + begin + if LStep > (LTotal - LOff) then + LStep := LTotal - LOff; + LEng.ProcessBytes(LIn, LOff, LStep, LChunk, LOff); + LOff := LOff + LStep; + LStep := LStep + 7; // ragged, block-straddling chunk sizes + end; + + if not AreEqual(LWhole, LChunk) then + Fail(Format('%s: whole vs chunked ProcessBytes mismatch', [AEngineLabel])); +end; + +// ProcessBytes over the whole buffer must equal ReturnByte one byte at a time. +procedure TStreamCipherTestBase.RunProcessBytesVsReturnByte( + const ACreateEngine: TStreamCipherFactory; const AEngineLabel: String); +const + LTotal = 517; +var + LKey, LNonce, LIn, LBulk, LByByte: TBytes; + LEng: IStreamCipher; + LI: Int32; +begin + LKey := SampleBytes(KeySizeInBytes, 7); + LNonce := SampleBytes(NonceSizeInBytes, 11); + LIn := SampleBytes(LTotal, 31); + System.SetLength(LBulk, LTotal); + System.SetLength(LByByte, LTotal); + + LEng := InitEngine(ACreateEngine, LKey, LNonce); + LEng.ProcessBytes(LIn, 0, LTotal, LBulk, 0); + + LEng := InitEngine(ACreateEngine, LKey, LNonce); + for LI := 0 to LTotal - 1 do + LByByte[LI] := LEng.ReturnByte(LIn[LI]); + + if not AreEqual(LBulk, LByByte) then + Fail(Format('%s: ProcessBytes vs ReturnByte mismatch', [AEngineLabel])); +end; + +// IBulkStreamCipher.ProcessBlocks(N) must equal N single 64B block transforms. +procedure TStreamCipherTestBase.RunBulkBlocksVsSingleBlock( + const ACreateEngine: TStreamCipherFactory; const AEngineLabel: String); +const + LCounts: array [0 .. 9] of Int32 = (1, 2, 3, 4, 5, 7, 8, 9, 16, 33); +var + LKey, LNonce, LIn, LBulkOut, LRefOut: TBytes; + LBulk: IBulkStreamCipher; + LRef: IStreamCipher; + LCount, LLen, LOff: Int32; +begin + if not Supports(ACreateEngine(), IBulkStreamCipher) then + Exit; // engine has no bulk fast path; nothing to compare + + LKey := SampleBytes(KeySizeInBytes, 7); + LNonce := SampleBytes(NonceSizeInBytes, 11); + for LCount in LCounts do + begin + LLen := LCount * 64; + LIn := SampleBytes(LLen, 31); + System.SetLength(LBulkOut, LLen); + System.SetLength(LRefOut, LLen); + + LBulk := InitEngine(ACreateEngine, LKey, LNonce) as IBulkStreamCipher; + LBulk.ProcessBlocks(LIn, 0, LCount, LBulkOut, 0); + + LRef := InitEngine(ACreateEngine, LKey, LNonce); + LOff := 0; + while LOff < LLen do + begin + LRef.ProcessBytes(LIn, LOff, 64, LRefOut, LOff); + LOff := LOff + 64; + end; + + if not AreEqual(LBulkOut, LRefOut) then + Fail(Format('%s: ProcessBlocks(%d) vs single-block mismatch', + [AEngineLabel, LCount])); + end; +end; + +procedure TStreamCipherTestBase.TestWholeVsChunked; +begin + RunWholeVsChunked(GetEngineFactory(), EngineLabel); +end; + +procedure TStreamCipherTestBase.TestProcessBytesVsReturnByte; +begin + RunProcessBytesVsReturnByte(GetEngineFactory(), EngineLabel); +end; + +procedure TStreamCipherTestBase.TestBulkBlocksVsSingleBlock; +begin + RunBulkBlocksVsSingleBlock(GetEngineFactory(), EngineLabel); +end; + +end. diff --git a/CryptoLib.Tests/src/Crypto/XChaCha20Tests.pas b/CryptoLib.Tests/src/Crypto/XChaCha20Tests.pas index 3bf215d0..a5822d79 100644 --- a/CryptoLib.Tests/src/Crypto/XChaCha20Tests.pas +++ b/CryptoLib.Tests/src/Crypto/XChaCha20Tests.pas @@ -45,11 +45,17 @@ interface ClpSecureRandom, ClpISecureRandom, ClpCryptoLibTypes, + StreamCipherTestBase, CryptoLibTestBase, ChaChaPoly1305Vectors; type - TTestXChaCha20 = class(TCryptoLibAlgorithmTestCase) + TTestXChaCha20 = class(TStreamCipherTestBase) + strict protected + function GetEngineFactory: TStreamCipherFactory; override; + function EngineLabel: String; override; + function KeySizeInBytes: Int32; override; + function NonceSizeInBytes: Int32; override; published procedure TestAppendixA2_1KeystreamFirst288; procedure TestAppendixA3_2_1KeystreamFull304; @@ -61,7 +67,6 @@ TTestXChaCha20 = class(TCryptoLibAlgorithmTestCase) procedure TestHChaCha20Indirect; procedure TestDraftStreamVector; procedure TestRandomRoundTrip; - procedure TestChunkedProcessing; procedure TestRejectShortNonce64Bits; procedure TestRejectShortNonce96Bits; procedure TestRejectShortNonce23Bytes; @@ -70,8 +75,33 @@ TTestXChaCha20 = class(TCryptoLibAlgorithmTestCase) implementation +function CreateXChaCha20Engine: IStreamCipher; +begin + Result := TXChaCha20Engine.Create() as IStreamCipher; +end; + { TTestXChaCha20 } +function TTestXChaCha20.GetEngineFactory: TStreamCipherFactory; +begin + Result := CreateXChaCha20Engine; +end; + +function TTestXChaCha20.EngineLabel: String; +begin + Result := 'XChaCha20'; +end; + +function TTestXChaCha20.KeySizeInBytes: Int32; +begin + Result := 32; +end; + +function TTestXChaCha20.NonceSizeInBytes: Int32; +begin + Result := 24; +end; + procedure TTestXChaCha20.TestAppendixA2_1KeystreamFirst288; var LRow: TXChaChaStreamRow; @@ -411,52 +441,6 @@ procedure TTestXChaCha20.TestRandomRoundTrip; end; end; -procedure TTestXChaCha20.TestChunkedProcessing; -const - ChunkSizes: array[0..8] of Int32 = (1, 7, 32, 63, 64, 65, 127, 128, 129); -var - LKey, LNonce, LPlain, LWhole, LPiecewise: TCryptoLibByteArray; - LEng: IXChaCha20Engine; - LParams: IParametersWithIV; - LRandom: ISecureRandom; - LI, LChunk, LOff, LN: Int32; -begin - LKey := THexEncoder.Decode( - '808182838485868788898a8b8c8d8e8f' + - '909192939495969798999a9b9c9d9e9f'); - LNonce := THexEncoder.Decode( - '404142434445464748494a4b4c4d4e4f5051525354555657'); - System.SetLength(LPlain, 1024); - LRandom := TSecureRandom.Create; - LRandom.NextBytes(LPlain); - - System.SetLength(LWhole, System.Length(LPlain)); - LEng := TXChaCha20Engine.Create; - LParams := TParametersWithIV.Create(TKeyParameter.Create(LKey) as IKeyParameter, - LNonce); - LEng.Init(True, LParams); - LEng.ProcessBytes(LPlain, 0, System.Length(LPlain), LWhole, 0); - - for LI := Low(ChunkSizes) to High(ChunkSizes) do - begin - LChunk := ChunkSizes[LI]; - System.SetLength(LPiecewise, System.Length(LPlain)); - LEng := TXChaCha20Engine.Create; - LEng.Init(True, LParams); - LOff := 0; - while LOff < System.Length(LPlain) do - begin - LN := LChunk; - if LN > System.Length(LPlain) - LOff then - LN := System.Length(LPlain) - LOff; - LEng.ProcessBytes(LPlain, LOff, LN, LPiecewise, LOff); - System.Inc(LOff, LN); - end; - if not AreEqual(LWhole, LPiecewise) then - Fail(Format('chunked processing differs from bulk at chunk size %d', [LChunk])); - end; -end; - procedure TTestXChaCha20.TestRejectShortNonce23Bytes; var LKey, LNonce23: TCryptoLibByteArray; diff --git a/CryptoLib.Tests/src/Crypto/XSalsa20Tests.pas b/CryptoLib.Tests/src/Crypto/XSalsa20Tests.pas index edbdcbcc..56b17c7c 100644 --- a/CryptoLib.Tests/src/Crypto/XSalsa20Tests.pas +++ b/CryptoLib.Tests/src/Crypto/XSalsa20Tests.pas @@ -32,17 +32,24 @@ interface {$ENDIF FPC} ClpXSalsa20Engine, ClpIXSalsa20Engine, + ClpIStreamCipher, ClpKeyParameter, ClpIKeyParameter, ClpParametersWithIV, ClpIParametersWithIV, ClpCryptoLibTypes, + StreamCipherTestBase, CryptoLibTestBase; type - TTestXSalsa20 = class(TCryptoLibAlgorithmTestCase) + TTestXSalsa20 = class(TStreamCipherTestBase) + strict protected + function GetEngineFactory: TStreamCipherFactory; override; + function EngineLabel: String; override; + function KeySizeInBytes: Int32; override; + function NonceSizeInBytes: Int32; override; private var FTestVectors: TCryptoLibGenericArray; @@ -61,8 +68,33 @@ TTestXSalsa20 = class(TCryptoLibAlgorithmTestCase) implementation +function CreateXSalsa20Engine: IStreamCipher; +begin + Result := TXSalsa20Engine.Create() as IStreamCipher; +end; + { TTestXSalsa20 } +function TTestXSalsa20.GetEngineFactory: TStreamCipherFactory; +begin + Result := CreateXSalsa20Engine; +end; + +function TTestXSalsa20.EngineLabel: String; +begin + Result := 'XSalsa20'; +end; + +function TTestXSalsa20.KeySizeInBytes: Int32; +begin + Result := 32; +end; + +function TTestXSalsa20.NonceSizeInBytes: Int32; +begin + Result := 24; +end; + procedure TTestXSalsa20.DoXSalsa20Test(number: Int32; const ATestVectorParams: TCryptoLibStringArray); var diff --git a/CryptoLib/src/Crypto/Engines/ClpChaCha7539Engine.pas b/CryptoLib/src/Crypto/Engines/ClpChaCha7539Engine.pas index 2c04da98..d1e5e1f4 100644 --- a/CryptoLib/src/Crypto/Engines/ClpChaCha7539Engine.pas +++ b/CryptoLib/src/Crypto/Engines/ClpChaCha7539Engine.pas @@ -21,29 +21,21 @@ interface uses - SysUtils, - ClpCheck, ClpIStreamCipher, ClpIChaCha7539Engine, - ClpSalsa20Engine, ClpChaChaEngine, ClpPack, - ClpCryptoLibTypes, - ClpChaChaSimd, - ClpByteUtilities; + ClpCryptoLibTypes; resourcestring SInvalidKeySizeTwoFiftySix = '%s requires 256 bit key'; SCounterExceeded = 'attempt to increase counter past 2^32'; - SNotInitialised = '%s not initialized'; - SNotBlockAligned = '%s not in block-aligned state'; - SMaxByteExceeded = - '2^38 byte limit per IV would be exceeded; change IV'; - SInputBufferTooShort = 'input buffer too short'; - SOutputBufferTooShort = 'output buffer too short'; type - TChaCha7539Engine = class(TSalsa20Engine, IChaCha7539Engine, IStreamCipher) + /// + /// ChaCha20 per RFC 7539 (IETF): 96-bit nonce, 32-bit block counter (word 12). + /// + TChaCha7539Engine = class(TChaChaBaseEngine, IChaCha7539Engine, IStreamCipher) strict protected function GetAlgorithmName: String; override; @@ -52,36 +44,10 @@ TChaCha7539Engine = class(TSalsa20Engine, IChaCha7539Engine, IStreamCipher) procedure AdvanceCounter(); override; procedure ResetCounter(); override; procedure SetKey(const AKeyBytes, AIvBytes: TCryptoLibByteArray); override; - procedure GenerateKeyStream(const AOutput: TCryptoLibByteArray); override; - - strict private - procedure ImplProcessBlock(const AInBuf: TCryptoLibByteArray; AInOff: Int32; - const AOutBuf: TCryptoLibByteArray; AOutOff: Int32); inline; - // Two-block keystream body (SIMD-accelerated when available, else scalar) with - // no state validation or 2^38 byte-limit accounting - those belong to the - // callers (ProcessBlocks2, ProcessBlocks4), which do them exactly once. - procedure ProcessBlocks2Core(const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); public constructor Create(); - procedure DoFinal(const AInBuf: TCryptoLibByteArray; AInOff, AInLen: Int32; - const AOutBuf: TCryptoLibByteArray; AOutOff: Int32); - - procedure ProcessBytes(const AInBytes: TCryptoLibByteArray; - AInOff, ALen: Int32; const AOutBytes: TCryptoLibByteArray; - AOutOff: Int32); override; - - procedure ProcessBlock(const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); - - procedure ProcessBlocks2(const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); override; - - procedure ProcessBlocks4(const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); - end; implementation @@ -138,249 +104,4 @@ procedure TChaCha7539Engine.SetKey(const AKeyBytes, TPack.LE_To_UInt32(AIvBytes, 0, FEngineState, 13, 3); end; -procedure TChaCha7539Engine.GenerateKeyStream( - const AOutput: TCryptoLibByteArray); -begin - TChaChaEngine.ChaChaCore(FRounds, FEngineState, AOutput); -end; - -procedure TChaCha7539Engine.DoFinal(const AInBuf: TCryptoLibByteArray; - AInOff, AInLen: Int32; const AOutBuf: TCryptoLibByteArray; AOutOff: Int32); -var - LIdx, LQ: Int32; -begin - if (not FInitialised) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotInitialised, - [AlgorithmName]); - end; - if (FIndex <> 0) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotBlockAligned, - [AlgorithmName]); - end; - - TCheck.DataLength(AInBuf, AInOff, AInLen, SInputBufferTooShort); - TCheck.OutputLength(AOutBuf, AOutOff, AInLen, SOutputBufferTooShort); - - while (AInLen >= 256) do - begin - ProcessBlocks4(AInBuf, AInOff, AOutBuf, AOutOff); - AInOff := AInOff + 256; - AInLen := AInLen - 256; - AOutOff := AOutOff + 256; - end; - - while (AInLen >= 128) do - begin - ProcessBlocks2(AInBuf, AInOff, AOutBuf, AOutOff); - AInOff := AInOff + 128; - AInLen := AInLen - 128; - AOutOff := AOutOff + 128; - end; - - if (AInLen >= 64) then - begin - ImplProcessBlock(AInBuf, AInOff, AOutBuf, AOutOff); - AInOff := AInOff + 64; - AInLen := AInLen - 64; - AOutOff := AOutOff + 64; - end; - - if (AInLen > 0) then - begin - GenerateKeyStream(FKeyStream); - AdvanceCounter(); - - LQ := AInLen shr 3; - if LQ > 0 then - TByteUtilities.&Xor(LQ * 8, AInBuf, AInOff, FKeyStream, 0, AOutBuf, AOutOff); - for LIdx := (LQ * 8) to System.Pred(AInLen) do - begin - AOutBuf[AOutOff + LIdx] := Byte( - AInBuf[AInOff + LIdx] xor FKeyStream[LIdx]); - end; - end; - - FEngineState[12] := 0; -end; - -procedure TChaCha7539Engine.ProcessBytes(const AInBytes: TCryptoLibByteArray; - AInOff, ALen: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); -var - LIdx, LTake, LQ: Int32; - LInP, LOutP, LKeyP: PByte; -begin - if (not FInitialised) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt - (@SNotInitialised, [AlgorithmName]); - end; - - TCheck.DataLength(AInBytes, AInOff, ALen, SInputBufferTooShort); - TCheck.OutputLength(AOutBytes, AOutOff, ALen, SOutputBufferTooShort); - - if (LimitExceeded(UInt32(ALen))) then - begin - raise EMaxBytesExceededCryptoLibException.CreateRes(@SMaxByteExceeded); - end; - - while ALen > 0 do - begin - if (FIndex <> 0) then - begin - LTake := ALen; - if LTake > (64 - FIndex) then - begin - LTake := 64 - FIndex; - end; - for LIdx := 0 to System.Pred(LTake) do - begin - AOutBytes[AOutOff + LIdx] := Byte( - FKeyStream[FIndex + LIdx] xor AInBytes[AInOff + LIdx]); - end; - FIndex := (FIndex + LTake) and 63; - AInOff := AInOff + LTake; - AOutOff := AOutOff + LTake; - System.Dec(ALen, LTake); - continue; - end; - if (ALen >= 256) then - begin - ProcessBlocks4(AInBytes, AInOff, AOutBytes, AOutOff); - AInOff := AInOff + 256; - AOutOff := AOutOff + 256; - System.Dec(ALen, 256); - end - else if (ALen >= 128) then - begin - ProcessBlocks2(AInBytes, AInOff, AOutBytes, AOutOff); - AInOff := AInOff + 128; - AOutOff := AOutOff + 128; - System.Dec(ALen, 128); - end - else if (ALen >= 64) then - begin - ImplProcessBlock(AInBytes, AInOff, AOutBytes, AOutOff); - AInOff := AInOff + 64; - AOutOff := AOutOff + 64; - System.Dec(ALen, 64); - end - else - begin - GenerateKeyStream(FKeyStream); - AdvanceCounter(); - LTake := ALen; - LInP := PByte(AInBytes) + AInOff; - LOutP := PByte(AOutBytes) + AOutOff; - LKeyP := PByte(FKeyStream); - LQ := LTake shr 3; - if LQ > 0 then - TByteUtilities.&Xor(LQ * 8, LInP, LKeyP, LOutP); - for LIdx := (LQ * 8) to System.Pred(LTake) do - begin - LOutP[LIdx] := LInP[LIdx] xor LKeyP[LIdx]; - end; - FIndex := (FIndex + LTake) and 63; - AInOff := AInOff + LTake; - AOutOff := AOutOff + LTake; - System.Dec(ALen, LTake); - end; - end; -end; - -procedure TChaCha7539Engine.ProcessBlock(const AInBytes: TCryptoLibByteArray; - AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); -begin - if (not FInitialised) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotInitialised, - [AlgorithmName]); - end; - if (FIndex <> 0) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotBlockAligned, - [AlgorithmName]); - end; - if (LimitExceeded(UInt32(64))) then - begin - raise EMaxBytesExceededCryptoLibException.CreateRes(@SMaxByteExceeded); - end; - - ImplProcessBlock(AInBytes, AInOff, AOutBytes, AOutOff); -end; - -procedure TChaCha7539Engine.ProcessBlocks2(const AInBytes: TCryptoLibByteArray; - AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); -begin - if (not FInitialised) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotInitialised, - [AlgorithmName]); - end; - if (FIndex <> 0) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotBlockAligned, - [AlgorithmName]); - end; - if (LimitExceeded(UInt32(128))) then - begin - raise EMaxBytesExceededCryptoLibException.CreateRes(@SMaxByteExceeded); - end; - - ProcessBlocks2Core(AInBytes, AInOff, AOutBytes, AOutOff); -end; - -procedure TChaCha7539Engine.ProcessBlocks2Core(const AInBytes: TCryptoLibByteArray; - AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); -begin - if TChaChaSimd.TryProcessBlocks2(FRounds, PByte(@FEngineState[0]), - PByte(@AInBytes[AInOff]), PByte(@AOutBytes[AOutOff])) then - Exit; - - ImplProcessBlock(AInBytes, AInOff, AOutBytes, AOutOff); - ImplProcessBlock(AInBytes, AInOff + 64, AOutBytes, AOutOff + 64); -end; - -procedure TChaCha7539Engine.ProcessBlocks4(const AInBytes: TCryptoLibByteArray; - AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); -begin - if (not FInitialised) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotInitialised, - [AlgorithmName]); - end; - if (FIndex <> 0) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotBlockAligned, - [AlgorithmName]); - end; - if (LimitExceeded(UInt32(256))) then - begin - raise EMaxBytesExceededCryptoLibException.CreateRes(@SMaxByteExceeded); - end; - - if TChaChaSimd.TryProcessBlocks4(FRounds, PByte(@FEngineState[0]), - PByte(@AInBytes[AInOff]), PByte(@AOutBytes[AOutOff])) then - Exit; - - ProcessBlocks2Core(AInBytes, AInOff, AOutBytes, AOutOff); - ProcessBlocks2Core(AInBytes, AInOff + 128, AOutBytes, AOutOff + 128); -end; - -procedure TChaCha7539Engine.ImplProcessBlock( - const AInBuf: TCryptoLibByteArray; AInOff: Int32; - const AOutBuf: TCryptoLibByteArray; AOutOff: Int32); -var - LInP, LOutP, LKeyP: PByte; -begin - TChaChaEngine.ChaChaCore(FRounds, FEngineState, FKeyStream); - AdvanceCounter(); - - LInP := PByte(AInBuf) + AInOff; - LKeyP := PByte(FKeyStream); - LOutP := PByte(AOutBuf) + AOutOff; - TByteUtilities.&Xor(64, LInP, LKeyP, LOutP); -end; - end. diff --git a/CryptoLib/src/Crypto/Engines/ClpChaChaEngine.pas b/CryptoLib/src/Crypto/Engines/ClpChaChaEngine.pas index 9f26e81d..8832cc3d 100644 --- a/CryptoLib/src/Crypto/Engines/ClpChaChaEngine.pas +++ b/CryptoLib/src/Crypto/Engines/ClpChaChaEngine.pas @@ -22,11 +22,13 @@ interface uses SysUtils, + ClpCheck, ClpIStreamCipher, ClpIChaChaEngine, ClpSalsa20Engine, ClpPack, ClpChaChaSimd, + ClpByteUtilities, ClpCryptoLibTypes; resourcestring @@ -39,21 +41,84 @@ interface SHChaChaNonce128 = 'HChaCha20 nonce must be 128 bits'; SHChaChaOutNil = 'HChaCha20 output buffer cannot be nil'; SHChaChaOutSpace = 'HChaCha20 output buffer too short'; + SNotInitialised = '%s not initialized'; + SNotBlockAligned = '%s not in block-aligned state'; + SMaxByteExceeded = + '2^38 byte limit per IV would be exceeded; change IV'; + SInputBufferTooShort = 'input buffer too short'; + SOutputBufferTooShort = 'output buffer too short'; type + /// + /// Shared ChaCha core (block function + SIMD bulk ladder) for the IETF and DJB + /// engines; they differ only in counter width (CounterIs64Bit) and key/nonce layout. + /// + TChaChaBaseEngine = class(TSalsa20Engine) + + strict private + // Pointer-form, unvalidated inner helpers (1 / 2 / 4 / 8 blocks). + procedure ProcessBlockFast(AIn, AOut: PByte); + procedure ProcessBlocks2Fast(AIn, AOut: PByte); + procedure ProcessBlocks4Fast(AIn, AOut: PByte); + procedure ProcessBlocks8Fast(AIn, AOut: PByte); + + strict protected + // 8 -> 4 -> 2 -> 1 bulk ladder (widest kernel first). + function DoProcessBlocks(AIn, AOut: PByte; ABlockCount: Int32): Int32; override; + + // True for the DJB 64-bit counter (words 12-13); False (IETF). + function CounterIs64Bit: Boolean; virtual; + // Wide kernels broadcast word 13; for the 64-bit counter that holds only while + // word 12 does not wrap over the N-block span (else the caller degrades a tier). + function WideBlocksSafe(ABlocks: Int32): Boolean; inline; + + procedure GenerateKeyStream(const AOutput: TCryptoLibByteArray); override; + + public + procedure DoFinal(const AInBuf: TCryptoLibByteArray; AInOff, AInLen: Int32; + const AOutBuf: TCryptoLibByteArray; AOutOff: Int32); + + procedure ProcessBytes(const AInBytes: TCryptoLibByteArray; + AInOff, ALen: Int32; const AOutBytes: TCryptoLibByteArray; + AOutOff: Int32); override; + + procedure ProcessBlock(const AInBytes: TCryptoLibByteArray; AInOff: Int32; + const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); + + procedure ProcessBlocks2(const AInBytes: TCryptoLibByteArray; AInOff: Int32; + const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); override; + + procedure ProcessBlocks4(const AInBytes: TCryptoLibByteArray; AInOff: Int32; + const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); + + procedure ProcessBlocks8(const AInBytes: TCryptoLibByteArray; AInOff: Int32; + const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); + + class procedure ChaChaCore(ARounds: Int32; + const AInput: TCryptoLibUInt32Array; + const AOutput: TCryptoLibByteArray); static; + + /// + /// HChaCha20 subkey derivation (draft-irtf-cfrg-xchacha). Writes 32 bytes to ASubKeyOut at ASubKeyOutOff. + /// + class procedure HChaCha20(const AKey256, ANonce128: TCryptoLibByteArray; + const ASubKeyOut: TCryptoLibByteArray; ASubKeyOutOff: Int32); static; + + end; + /// /// Implementation of Daniel J. Bernstein's ChaCha stream cipher. /// - TChaChaEngine = class(TSalsa20Engine, IChaChaEngine, IStreamCipher) + TChaChaEngine = class(TChaChaBaseEngine, IChaChaEngine, IStreamCipher) strict protected function GetAlgorithmName: String; override; + function CounterIs64Bit: Boolean; override; procedure AdvanceCounter(); override; procedure ResetCounter(); override; procedure SetKey(const AKeyBytes, AIvBytes: TCryptoLibByteArray); override; - procedure GenerateKeyStream(const AOutput: TCryptoLibByteArray); override; public /// @@ -66,44 +131,346 @@ TChaChaEngine = class(TSalsa20Engine, IChaChaEngine, IStreamCipher) /// the number of rounds (must be an even number). constructor Create(ARounds: Int32); overload; - procedure ProcessBlocks2(const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); override; + end; - class procedure ChaChaCore(ARounds: Int32; - const AInput: TCryptoLibUInt32Array; - const AOutput: TCryptoLibByteArray); static; +implementation - /// - /// HChaCha20 subkey derivation (draft-irtf-cfrg-xchacha). Writes 32 bytes to ASubKeyOut at ASubKeyOutOff. - /// - class procedure HChaCha20(const AKey256, ANonce128: TCryptoLibByteArray; - const ASubKeyOut: TCryptoLibByteArray; ASubKeyOutOff: Int32); static; +{ TChaChaBaseEngine } +function TChaChaBaseEngine.CounterIs64Bit: Boolean; +begin + Result := False; +end; + +function TChaChaBaseEngine.WideBlocksSafe(ABlocks: Int32): Boolean; +begin + Result := (not CounterIs64Bit) or + (FEngineState[12] <= (UInt32($FFFFFFFF) - UInt32(ABlocks - 1))); +end; + +procedure TChaChaBaseEngine.GenerateKeyStream(const AOutput: TCryptoLibByteArray); +begin + ChaChaCore(FRounds, FEngineState, AOutput); +end; + +procedure TChaChaBaseEngine.DoFinal(const AInBuf: TCryptoLibByteArray; + AInOff, AInLen: Int32; const AOutBuf: TCryptoLibByteArray; AOutOff: Int32); +var + LIdx, LQ: Int32; +begin + if (not FInitialised) then + begin + raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotInitialised, + [AlgorithmName]); + end; + if (FIndex <> 0) then + begin + raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotBlockAligned, + [AlgorithmName]); end; -implementation + TCheck.DataLength(AInBuf, AInOff, AInLen, SInputBufferTooShort); + TCheck.OutputLength(AOutBuf, AOutOff, AInLen, SOutputBufferTooShort); -{ TChaChaEngine } + while (AInLen >= 512) do + begin + ProcessBlocks8(AInBuf, AInOff, AOutBuf, AOutOff); + AInOff := AInOff + 512; + AInLen := AInLen - 512; + AOutOff := AOutOff + 512; + end; + + while (AInLen >= 256) do + begin + ProcessBlocks4(AInBuf, AInOff, AOutBuf, AOutOff); + AInOff := AInOff + 256; + AInLen := AInLen - 256; + AOutOff := AOutOff + 256; + end; -procedure TChaChaEngine.ProcessBlocks2( - const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); + while (AInLen >= 128) do + begin + ProcessBlocks2(AInBuf, AInOff, AOutBuf, AOutOff); + AInOff := AInOff + 128; + AInLen := AInLen - 128; + AOutOff := AOutOff + 128; + end; + + if (AInLen >= 64) then + begin + ImplProcessBlock(AInBuf, AInOff, AOutBuf, AOutOff); + AInOff := AInOff + 64; + AInLen := AInLen - 64; + AOutOff := AOutOff + 64; + end; + + if (AInLen > 0) then + begin + GenerateKeyStream(FKeyStream); + AdvanceCounter(); + + LQ := AInLen shr 3; + if LQ > 0 then + TByteUtilities.&Xor(LQ * 8, AInBuf, AInOff, FKeyStream, 0, AOutBuf, AOutOff); + for LIdx := (LQ * 8) to System.Pred(AInLen) do + begin + AOutBuf[AOutOff + LIdx] := Byte( + AInBuf[AInOff + LIdx] xor FKeyStream[LIdx]); + end; + end; + + ResetCounter(); +end; + +procedure TChaChaBaseEngine.ProcessBytes(const AInBytes: TCryptoLibByteArray; + AInOff, ALen: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); +var + LIdx, LTake, LQ: Int32; + LInP, LOutP, LKeyP: PByte; +begin + if (not FInitialised) then + begin + raise EInvalidOperationCryptoLibException.CreateResFmt + (@SNotInitialised, [AlgorithmName]); + end; + + TCheck.DataLength(AInBytes, AInOff, ALen, SInputBufferTooShort); + TCheck.OutputLength(AOutBytes, AOutOff, ALen, SOutputBufferTooShort); + + if (LimitExceeded(UInt32(ALen))) then + begin + raise EMaxBytesExceededCryptoLibException.CreateRes(@SMaxByteExceeded); + end; + + while ALen > 0 do + begin + if (FIndex <> 0) then + begin + LTake := ALen; + if LTake > (64 - FIndex) then + begin + LTake := 64 - FIndex; + end; + for LIdx := 0 to System.Pred(LTake) do + begin + AOutBytes[AOutOff + LIdx] := Byte( + FKeyStream[FIndex + LIdx] xor AInBytes[AInOff + LIdx]); + end; + FIndex := (FIndex + LTake) and 63; + AInOff := AInOff + LTake; + AOutOff := AOutOff + LTake; + System.Dec(ALen, LTake); + continue; + end; + if (ALen >= 512) then + begin + ProcessBlocks8(AInBytes, AInOff, AOutBytes, AOutOff); + AInOff := AInOff + 512; + AOutOff := AOutOff + 512; + System.Dec(ALen, 512); + end + else if (ALen >= 256) then + begin + ProcessBlocks4(AInBytes, AInOff, AOutBytes, AOutOff); + AInOff := AInOff + 256; + AOutOff := AOutOff + 256; + System.Dec(ALen, 256); + end + else if (ALen >= 128) then + begin + ProcessBlocks2(AInBytes, AInOff, AOutBytes, AOutOff); + AInOff := AInOff + 128; + AOutOff := AOutOff + 128; + System.Dec(ALen, 128); + end + else if (ALen >= 64) then + begin + ImplProcessBlock(AInBytes, AInOff, AOutBytes, AOutOff); + AInOff := AInOff + 64; + AOutOff := AOutOff + 64; + System.Dec(ALen, 64); + end + else + begin + GenerateKeyStream(FKeyStream); + AdvanceCounter(); + LTake := ALen; + LInP := PByte(AInBytes) + AInOff; + LOutP := PByte(AOutBytes) + AOutOff; + LKeyP := PByte(FKeyStream); + LQ := LTake shr 3; + if LQ > 0 then + TByteUtilities.&Xor(LQ * 8, LInP, LKeyP, LOutP); + for LIdx := (LQ * 8) to System.Pred(LTake) do + begin + LOutP[LIdx] := LInP[LIdx] xor LKeyP[LIdx]; + end; + FIndex := (FIndex + LTake) and 63; + AInOff := AInOff + LTake; + AOutOff := AOutOff + LTake; + System.Dec(ALen, LTake); + end; + end; +end; + +procedure TChaChaBaseEngine.ProcessBlock(const AInBytes: TCryptoLibByteArray; + AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); begin - AssertInitialisedAndBlockAligned; + if (not FInitialised) then + begin + raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotInitialised, + [AlgorithmName]); + end; + if (FIndex <> 0) then + begin + raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotBlockAligned, + [AlgorithmName]); + end; + if (LimitExceeded(UInt32(64))) then + begin + raise EMaxBytesExceededCryptoLibException.CreateRes(@SMaxByteExceeded); + end; + ImplProcessBlock(AInBytes, AInOff, AOutBytes, AOutOff); - ImplProcessBlock(AInBytes, AInOff + 64, AOutBytes, AOutOff + 64); end; -procedure TChaChaEngine.AdvanceCounter; +procedure TChaChaBaseEngine.ProcessBlocks2(const AInBytes: TCryptoLibByteArray; + AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); begin - System.Inc(FEngineState[12]); - if (FEngineState[12] = 0) then + if (not FInitialised) then begin - System.Inc(FEngineState[13]); + raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotInitialised, + [AlgorithmName]); + end; + if (FIndex <> 0) then + begin + raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotBlockAligned, + [AlgorithmName]); end; + if (LimitExceeded(UInt32(128))) then + begin + raise EMaxBytesExceededCryptoLibException.CreateRes(@SMaxByteExceeded); + end; + + ProcessBlocks2Fast(PByte(@AInBytes[AInOff]), PByte(@AOutBytes[AOutOff])); end; -class procedure TChaChaEngine.ChaChaCore(ARounds: Int32; +procedure TChaChaBaseEngine.ProcessBlockFast(AIn, AOut: PByte); +begin + ChaChaCore(FRounds, FEngineState, FKeyStream); + AdvanceCounter(); + TByteUtilities.&Xor(64, AIn, PByte(FKeyStream), AOut); +end; + +procedure TChaChaBaseEngine.ProcessBlocks2Fast(AIn, AOut: PByte); +begin + if TChaChaSimd.TryProcessBlocks2(FRounds, PByte(@FEngineState[0]), + AIn, AOut, CounterIs64Bit) then + Exit; + + ProcessBlockFast(AIn, AOut); + ProcessBlockFast(AIn + 64, AOut + 64); +end; + +procedure TChaChaBaseEngine.ProcessBlocks4Fast(AIn, AOut: PByte); +begin + if WideBlocksSafe(4) then + if TChaChaSimd.TryProcessBlocks4(FRounds, PByte(@FEngineState[0]), + AIn, AOut, CounterIs64Bit) then + Exit; + + ProcessBlocks2Fast(AIn, AOut); + ProcessBlocks2Fast(AIn + 128, AOut + 128); +end; + +procedure TChaChaBaseEngine.ProcessBlocks8Fast(AIn, AOut: PByte); +begin + if WideBlocksSafe(8) then + if TChaChaSimd.TryProcessBlocks8(FRounds, PByte(@FEngineState[0]), + AIn, AOut, CounterIs64Bit) then + Exit; + + ProcessBlocks4Fast(AIn, AOut); + ProcessBlocks4Fast(AIn + 256, AOut + 256); +end; + +function TChaChaBaseEngine.DoProcessBlocks(AIn, AOut: PByte; + ABlockCount: Int32): Int32; +begin + Result := ABlockCount * 64; + while ABlockCount >= 8 do + begin + ProcessBlocks8Fast(AIn, AOut); + AIn := AIn + 512; + AOut := AOut + 512; + System.Dec(ABlockCount, 8); + end; + if ABlockCount >= 4 then + begin + ProcessBlocks4Fast(AIn, AOut); + AIn := AIn + 256; + AOut := AOut + 256; + System.Dec(ABlockCount, 4); + end; + if ABlockCount >= 2 then + begin + ProcessBlocks2Fast(AIn, AOut); + AIn := AIn + 128; + AOut := AOut + 128; + System.Dec(ABlockCount, 2); + end; + while ABlockCount >= 1 do + begin + ProcessBlockFast(AIn, AOut); + AIn := AIn + 64; + AOut := AOut + 64; + System.Dec(ABlockCount); + end; +end; + +procedure TChaChaBaseEngine.ProcessBlocks4(const AInBytes: TCryptoLibByteArray; + AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); +begin + if (not FInitialised) then + begin + raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotInitialised, + [AlgorithmName]); + end; + if (FIndex <> 0) then + begin + raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotBlockAligned, + [AlgorithmName]); + end; + if (LimitExceeded(UInt32(256))) then + begin + raise EMaxBytesExceededCryptoLibException.CreateRes(@SMaxByteExceeded); + end; + + ProcessBlocks4Fast(PByte(@AInBytes[AInOff]), PByte(@AOutBytes[AOutOff])); +end; + +procedure TChaChaBaseEngine.ProcessBlocks8(const AInBytes: TCryptoLibByteArray; + AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); +begin + if (not FInitialised) then + begin + raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotInitialised, + [AlgorithmName]); + end; + if (FIndex <> 0) then + begin + raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotBlockAligned, + [AlgorithmName]); + end; + if (LimitExceeded(UInt32(512))) then + begin + raise EMaxBytesExceededCryptoLibException.CreateRes(@SMaxByteExceeded); + end; + + ProcessBlocks8Fast(PByte(@AInBytes[AInOff]), PByte(@AOutBytes[AOutOff])); +end; + +class procedure TChaChaBaseEngine.ChaChaCore(ARounds: Int32; const AInput: TCryptoLibUInt32Array; const AOutput: TCryptoLibByteArray); var LX00, LX01, LX02, LX03, LX04, LX05, LX06, LX07, LX08, LX09, LX10, LX11, LX12, LX13, LX14, @@ -239,54 +606,7 @@ class procedure TChaChaEngine.ChaChaCore(ARounds: Int32; end; -constructor TChaChaEngine.Create; -begin - Inherited Create(); -end; - -constructor TChaChaEngine.Create(ARounds: Int32); -begin - Inherited Create(ARounds); -end; - -procedure TChaChaEngine.GenerateKeyStream(const AOutput: TCryptoLibByteArray); -begin - ChaChaCore(FRounds, FEngineState, AOutput); -end; - -function TChaChaEngine.GetAlgorithmName: String; -begin - Result := Format('ChaCha%d', [FRounds]); -end; - -procedure TChaChaEngine.ResetCounter; -begin - FEngineState[12] := 0; - FEngineState[13] := 0; -end; - -procedure TChaChaEngine.SetKey(const AKeyBytes, AIvBytes: TCryptoLibByteArray); -begin - if (AKeyBytes <> nil) then - begin - if not(System.Length(AKeyBytes) in [16, 32]) then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SInvalidKeySize, - [AlgorithmName]); - end; - - PackTauOrSigma(System.Length(AKeyBytes), FEngineState); - - // Key - TPack.LE_To_UInt32(AKeyBytes, 0, FEngineState, 4, 4); - TPack.LE_To_UInt32(AKeyBytes, System.Length(AKeyBytes) - 16, FEngineState, 8, 4); - end; - - // IV - TPack.LE_To_UInt32(AIvBytes, 0, FEngineState, 14, 2); -end; - -class procedure TChaChaEngine.HChaCha20(const AKey256, ANonce128: TCryptoLibByteArray; +class procedure TChaChaBaseEngine.HChaCha20(const AKey256, ANonce128: TCryptoLibByteArray; const ASubKeyOut: TCryptoLibByteArray; ASubKeyOutOff: Int32); var LState: TCryptoLibUInt32Array; @@ -335,4 +655,62 @@ class procedure TChaChaEngine.HChaCha20(const AKey256, ANonce128: TCryptoLibByte TPack.UInt32_To_LE(TPack.LE_To_UInt32(LOut, 60) - LState[15], ASubKeyOut, ASubKeyOutOff + 28); end; +{ TChaChaEngine } + +constructor TChaChaEngine.Create; +begin + Inherited Create(); +end; + +constructor TChaChaEngine.Create(ARounds: Int32); +begin + Inherited Create(ARounds); +end; + +function TChaChaEngine.CounterIs64Bit: Boolean; +begin + Result := True; +end; + +procedure TChaChaEngine.AdvanceCounter; +begin + System.Inc(FEngineState[12]); + if (FEngineState[12] = 0) then + begin + System.Inc(FEngineState[13]); + end; +end; + +function TChaChaEngine.GetAlgorithmName: String; +begin + Result := Format('ChaCha%d', [FRounds]); +end; + +procedure TChaChaEngine.ResetCounter; +begin + FEngineState[12] := 0; + FEngineState[13] := 0; +end; + +procedure TChaChaEngine.SetKey(const AKeyBytes, AIvBytes: TCryptoLibByteArray); +begin + if (AKeyBytes <> nil) then + begin + if not(System.Length(AKeyBytes) in [16, 32]) then + begin + raise EArgumentCryptoLibException.CreateResFmt(@SInvalidKeySize, + [AlgorithmName]); + end; + + PackTauOrSigma(System.Length(AKeyBytes), FEngineState); + + // Key + TPack.LE_To_UInt32(AKeyBytes, 0, FEngineState, 4, 4); + TPack.LE_To_UInt32(AKeyBytes, System.Length(AKeyBytes) - 16, FEngineState, 8, 4); + end; + + // IV + TPack.LE_To_UInt32(AIvBytes, 0, FEngineState, 14, 2); +end; + end. diff --git a/CryptoLib/src/Crypto/Engines/ClpChaChaSimd.pas b/CryptoLib/src/Crypto/Engines/ClpChaChaSimd.pas index 1100839b..bf10519e 100644 --- a/CryptoLib/src/Crypto/Engines/ClpChaChaSimd.pas +++ b/CryptoLib/src/Crypto/Engines/ClpChaChaSimd.pas @@ -39,10 +39,13 @@ TChaChaSimd = class sealed public /// Single-block ChaCha core (ChaCha20 keystream block). class function TryCore(ARounds: Int32; AInput, AOut: PByte): Boolean; static; - /// Two-block ChaCha7539 keystream (128 bytes). - class function TryProcessBlocks2(ARounds: Int32; AState, AIn, AOut: PByte): Boolean; static; - /// Four-block ChaCha7539 keystream (256 bytes). - class function TryProcessBlocks4(ARounds: Int32; AState, AIn, AOut: PByte): Boolean; static; + /// Two-block ChaCha keystream (128 bytes). ACtr64 = DJB 64-bit + /// counter (no SIMD 2-block body; returns False). + class function TryProcessBlocks2(ARounds: Int32; AState, AIn, AOut: PByte; ACtr64: Boolean = False): Boolean; static; + /// Four-block ChaCha keystream (256 bytes). ACtr64 = DJB variant. + class function TryProcessBlocks4(ARounds: Int32; AState, AIn, AOut: PByte; ACtr64: Boolean = False): Boolean; static; + /// Eight-block ChaCha keystream (512 bytes). ACtr64 = DJB variant. + class function TryProcessBlocks8(ARounds: Int32; AState, AIn, AOut: PByte; ACtr64: Boolean = False): Boolean; static; end; implementation @@ -58,19 +61,28 @@ class function TChaChaSimd.TryCore(ARounds: Int32; AInput, AOut: PByte): Boolean {$IFEND} end; -class function TChaChaSimd.TryProcessBlocks2(ARounds: Int32; AState, AIn, AOut: PByte): Boolean; +class function TChaChaSimd.TryProcessBlocks2(ARounds: Int32; AState, AIn, AOut: PByte; ACtr64: Boolean): Boolean; begin {$IF DEFINED(CRYPTOLIB_X86_SIMD)} - Result := TChaChaX86Backend.TryProcessBlocks2(ARounds, AState, AIn, AOut); + Result := TChaChaX86Backend.TryProcessBlocks2(ARounds, AState, AIn, AOut, ACtr64); {$ELSE} Result := False; {$IFEND} end; -class function TChaChaSimd.TryProcessBlocks4(ARounds: Int32; AState, AIn, AOut: PByte): Boolean; +class function TChaChaSimd.TryProcessBlocks4(ARounds: Int32; AState, AIn, AOut: PByte; ACtr64: Boolean): Boolean; begin {$IF DEFINED(CRYPTOLIB_X86_SIMD)} - Result := TChaChaX86Backend.TryProcessBlocks4(ARounds, AState, AIn, AOut); + Result := TChaChaX86Backend.TryProcessBlocks4(ARounds, AState, AIn, AOut, ACtr64); +{$ELSE} + Result := False; +{$IFEND} +end; + +class function TChaChaSimd.TryProcessBlocks8(ARounds: Int32; AState, AIn, AOut: PByte; ACtr64: Boolean): Boolean; +begin +{$IF DEFINED(CRYPTOLIB_X86_SIMD)} + Result := TChaChaX86Backend.TryProcessBlocks8(ARounds, AState, AIn, AOut, ACtr64); {$ELSE} Result := False; {$IFEND} diff --git a/CryptoLib/src/Crypto/Engines/ClpChaChaX86Backend.pas b/CryptoLib/src/Crypto/Engines/ClpChaChaX86Backend.pas index 67e98368..04f13d17 100644 --- a/CryptoLib/src/Crypto/Engines/ClpChaChaX86Backend.pas +++ b/CryptoLib/src/Crypto/Engines/ClpChaChaX86Backend.pas @@ -41,10 +41,16 @@ TChaChaX86Backend = class sealed public /// SIMD single-block ChaCha core (ChaCha20 keystream block). class function TryCore(ARounds: Int32; AInput, AOut: PByte): Boolean; static; - /// SIMD two-block ChaCha7539 keystream (128 bytes). - class function TryProcessBlocks2(ARounds: Int32; AState, AIn, AOut: PByte): Boolean; static; - /// AVX2 four-block ChaCha7539 keystream (256 bytes). - class function TryProcessBlocks4(ARounds: Int32; AState, AIn, AOut: PByte): Boolean; static; + /// SIMD two-block ChaCha keystream (128 bytes). ACtr64 selects the + /// 64-bit-counter (DJB) variant; no SIMD 2-block kernel exists for it, so it + /// returns False and the caller runs its scalar path. + class function TryProcessBlocks2(ARounds: Int32; AState, AIn, AOut: PByte; ACtr64: Boolean = False): Boolean; static; + /// Four-block ChaCha keystream (256 bytes). ACtr64 selects the DJB + /// 64-bit-counter kernel. + class function TryProcessBlocks4(ARounds: Int32; AState, AIn, AOut: PByte; ACtr64: Boolean = False): Boolean; static; + /// AVX2 eight-block ChaCha keystream (512 bytes). ACtr64 selects the + /// DJB 64-bit-counter kernel. + class function TryProcessBlocks8(ARounds: Int32; AState, AIn, AOut: PByte; ACtr64: Boolean = False): Boolean; static; end; implementation @@ -77,27 +83,79 @@ procedure ChaCha7539ProcessBlocks2Sse2(ARounds: Int32; AState, AIn, AOut: PByte) {$ENDIF} end; -procedure ChaCha7539ProcessBlocks2Avx2(ARounds: Int32; AState, AIn, AOut: PByte); +procedure ChaCha7539ProcessBlocks4Sse2(ARounds: Int32; AState, AIn, AOut: PByte); {$IFDEF CRYPTOLIB_X86_64_ASM} {$I ..\..\Include\Simd\Common\ClpSimdProc4Begin_x86_64.inc} -{$I ..\..\Include\Simd\ChaCha\ChaCha7539ProcessBlocks2Avx2_x86_64.inc} +{$I ..\..\Include\Simd\ChaCha\ChaCha7539Blocks4Sse2_x86_64.inc} {$ENDIF} {$IFDEF CRYPTOLIB_I386_ASM} {$I ..\..\Include\Simd\Common\ClpSimdProc4Begin_i386.inc} -{$I ..\..\Include\Simd\ChaCha\ChaCha7539ProcessBlocks2Avx2_i386.inc} +{$I ..\..\Include\Simd\ChaCha\ChaCha7539Blocks4Sse2_i386.inc} {$ENDIF} end; -procedure ChaCha7539ProcessBlocks4Avx2(ARounds: Int32; AState, AIn, AOut: PByte); +procedure ChaCha7539ProcessBlocks4Ssse3(ARounds: Int32; AState, AIn, AOut: PByte); {$IFDEF CRYPTOLIB_X86_64_ASM} {$I ..\..\Include\Simd\Common\ClpSimdProc4Begin_x86_64.inc} -{$I ..\..\Include\Simd\ChaCha\ChaCha7539ProcessBlocks4Avx2_x86_64.inc} +{$I ..\..\Include\Simd\ChaCha\ChaCha7539Blocks4Ssse3_x86_64.inc} {$ENDIF} {$IFDEF CRYPTOLIB_I386_ASM} {$I ..\..\Include\Simd\Common\ClpSimdProc4Begin_i386.inc} -{$I ..\..\Include\Simd\ChaCha\ChaCha7539ProcessBlocks4Avx2_i386.inc} +{$I ..\..\Include\Simd\ChaCha\ChaCha7539Blocks4Ssse3_i386.inc} {$ENDIF} end; + +// AVX2 8-way (512B): x86_64 only (needs 16 ymm; i386 has 8, so it falls back to +// two 256B ProcessBlocks4 in the engine). +{$IFDEF CRYPTOLIB_X86_64_ASM} +procedure ChaCha7539ProcessBlocks8Avx2(ARounds: Int32; AState, AIn, AOut: PByte); +{$I ..\..\Include\Simd\Common\ClpSimdProc4Begin_x86_64.inc} +{$I ..\..\Include\Simd\ChaCha\ChaCha7539Blocks8Avx2_x86_64.inc} +end; +{$ENDIF} + +// DJB ChaCha (64-bit counter, words 12-13): the vertical kernels are identical to +// the 7539 ones except the counter advance carries into word 13, which the shared +// includes emit under CHACHA_CTR64. Callers guard against a low-word wrap across the +// lanes before invoking these (see the engine's WideBlocksSafe). +procedure ChaChaProcessBlocks4Sse2(ARounds: Int32; AState, AIn, AOut: PByte); +{$IFDEF CRYPTOLIB_X86_64_ASM} +{$I ..\..\Include\Simd\Common\ClpSimdProc4Begin_x86_64.inc} +{$DEFINE CHACHA_CTR64} +{$I ..\..\Include\Simd\ChaCha\ChaCha7539Blocks4Sse2_x86_64.inc} +{$UNDEF CHACHA_CTR64} +{$ENDIF} +{$IFDEF CRYPTOLIB_I386_ASM} +{$I ..\..\Include\Simd\Common\ClpSimdProc4Begin_i386.inc} +{$DEFINE CHACHA_CTR64} +{$I ..\..\Include\Simd\ChaCha\ChaCha7539Blocks4Sse2_i386.inc} +{$UNDEF CHACHA_CTR64} +{$ENDIF} +end; + +procedure ChaChaProcessBlocks4Ssse3(ARounds: Int32; AState, AIn, AOut: PByte); +{$IFDEF CRYPTOLIB_X86_64_ASM} +{$I ..\..\Include\Simd\Common\ClpSimdProc4Begin_x86_64.inc} +{$DEFINE CHACHA_CTR64} +{$I ..\..\Include\Simd\ChaCha\ChaCha7539Blocks4Ssse3_x86_64.inc} +{$UNDEF CHACHA_CTR64} +{$ENDIF} +{$IFDEF CRYPTOLIB_I386_ASM} +{$I ..\..\Include\Simd\Common\ClpSimdProc4Begin_i386.inc} +{$DEFINE CHACHA_CTR64} +{$I ..\..\Include\Simd\ChaCha\ChaCha7539Blocks4Ssse3_i386.inc} +{$UNDEF CHACHA_CTR64} +{$ENDIF} +end; + +{$IFDEF CRYPTOLIB_X86_64_ASM} +procedure ChaChaProcessBlocks8Avx2(ARounds: Int32; AState, AIn, AOut: PByte); +{$I ..\..\Include\Simd\Common\ClpSimdProc4Begin_x86_64.inc} +{$DEFINE CHACHA_CTR64} +{$I ..\..\Include\Simd\ChaCha\ChaCha7539Blocks8Avx2_x86_64.inc} +{$UNDEF CHACHA_CTR64} +end; +{$ENDIF} {$ENDIF CRYPTOLIB_X86_SIMD} { TChaChaX86Backend } @@ -116,18 +174,45 @@ class function TChaChaX86Backend.TryCore(ARounds: Int32; AInput, AOut: PByte): B Result := False; end; -class function TChaChaX86Backend.TryProcessBlocks2(ARounds: Int32; AState, AIn, AOut: PByte): Boolean; +class function TChaChaX86Backend.TryProcessBlocks2(ARounds: Int32; AState, AIn, AOut: PByte; ACtr64: Boolean): Boolean; begin {$IFDEF CRYPTOLIB_X86_SIMD} - case TCpuFeatures.X86.SelectSlot([TX86SimdLevel.AVX2, TX86SimdLevel.SSE2]) of - TX86SimdLevel.AVX2: + // 2-block (128B) tier: AVX2 adds nothing at this width, so the SSE2 body serves + // every SIMD CPU (the vertical 4-way/8-way kernels handle the larger tiers). The + // 2-block kernel is 7539-only (32-bit counter with raise-on-wrap), so DJB + // (ACtr64) has no SIMD body here and runs scalar. + if not ACtr64 then + case TCpuFeatures.X86.SelectSlot([TX86SimdLevel.SSE2]) of + TX86SimdLevel.SSE2: + begin + ChaCha7539ProcessBlocks2Sse2(ARounds, AState, AIn, AOut); + Exit(True); + end; + end; +{$ENDIF} + Result := False; +end; + +class function TChaChaX86Backend.TryProcessBlocks4(ARounds: Int32; AState, AIn, AOut: PByte; ACtr64: Boolean): Boolean; +begin +{$IFDEF CRYPTOLIB_X86_SIMD} + // 4-block (256B) tier: AVX2 gives no extra lanes at 4-way, and AVX2 CPUs run the + // 8-way kernel for the bulk (512B) tier, so SSSE3/SSE2 cover every CPU here. + case TCpuFeatures.X86.SelectSlot([TX86SimdLevel.SSSE3, TX86SimdLevel.SSE2]) of + TX86SimdLevel.SSSE3: begin - ChaCha7539ProcessBlocks2Avx2(ARounds, AState, AIn, AOut); + if ACtr64 then + ChaChaProcessBlocks4Ssse3(ARounds, AState, AIn, AOut) + else + ChaCha7539ProcessBlocks4Ssse3(ARounds, AState, AIn, AOut); Exit(True); end; TX86SimdLevel.SSE2: begin - ChaCha7539ProcessBlocks2Sse2(ARounds, AState, AIn, AOut); + if ACtr64 then + ChaChaProcessBlocks4Sse2(ARounds, AState, AIn, AOut) + else + ChaCha7539ProcessBlocks4Sse2(ARounds, AState, AIn, AOut); Exit(True); end; end; @@ -135,13 +220,16 @@ class function TChaChaX86Backend.TryProcessBlocks2(ARounds: Int32; AState, AIn, Result := False; end; -class function TChaChaX86Backend.TryProcessBlocks4(ARounds: Int32; AState, AIn, AOut: PByte): Boolean; +class function TChaChaX86Backend.TryProcessBlocks8(ARounds: Int32; AState, AIn, AOut: PByte; ACtr64: Boolean): Boolean; begin -{$IFDEF CRYPTOLIB_X86_SIMD} +{$IFDEF CRYPTOLIB_X86_64_ASM} case TCpuFeatures.X86.SelectSlot([TX86SimdLevel.AVX2]) of TX86SimdLevel.AVX2: begin - ChaCha7539ProcessBlocks4Avx2(ARounds, AState, AIn, AOut); + if ACtr64 then + ChaChaProcessBlocks8Avx2(ARounds, AState, AIn, AOut) + else + ChaCha7539ProcessBlocks8Avx2(ARounds, AState, AIn, AOut); Exit(True); end; end; diff --git a/CryptoLib/src/Crypto/Engines/ClpSalsa20Engine.pas b/CryptoLib/src/Crypto/Engines/ClpSalsa20Engine.pas index 222e579d..b0a1f402 100644 --- a/CryptoLib/src/Crypto/Engines/ClpSalsa20Engine.pas +++ b/CryptoLib/src/Crypto/Engines/ClpSalsa20Engine.pas @@ -25,6 +25,7 @@ interface ClpBitOperations, ClpCheck, ClpIStreamCipher, + ClpIBulkStreamCipher, ClpISalsa20Engine, ClpIKeyParameter, ClpICipherParameters, @@ -56,7 +57,8 @@ interface /// /// Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005 /// - TSalsa20Engine = class(TInterfacedObject, ISalsa20Engine, IStreamCipher) + TSalsa20Engine = class(TInterfacedObject, ISalsa20Engine, IStreamCipher, + IBulkStreamCipher) strict private const @@ -72,6 +74,10 @@ TSalsa20Engine = class(TInterfacedObject, ISalsa20Engine, IStreamCipher) class procedure QuarterRound(var A, B, C, D: UInt32); static; inline; + // Pointer-form, unvalidated inner helpers (1 / 2 blocks). + procedure ProcessBlockFast(AIn, AOut: PByte); + procedure ProcessBlocks2Fast(AIn, AOut: PByte); + strict protected var FIndex: Int32; @@ -97,6 +103,9 @@ TSalsa20Engine = class(TInterfacedObject, ISalsa20Engine, IStreamCipher) procedure ImplProcessBlock(const AInBytes: TCryptoLibByteArray; AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); inline; + // 2 -> 1 bulk ladder; the ChaCha engine overrides with 8 -> 4 -> 2 -> 1. + function DoProcessBlocks(AIn, AOut: PByte; ABlockCount: Int32): Int32; virtual; + /// /// Rotate left /// @@ -133,6 +142,12 @@ TSalsa20Engine = class(TInterfacedObject, ISalsa20Engine, IStreamCipher) procedure ProcessBlocks2(const AInBytes: TCryptoLibByteArray; AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); virtual; + // IBulkStreamCipher: bulk keystream over whole 64B blocks; engine owns the ladder. + function ProcessBlocks(const AInBuf: TCryptoLibByteArray; + AInOff, ABlockCount: Int32; const AOutBuf: TCryptoLibByteArray; + AOutOff: Int32): Int32; overload; + function ProcessBlocks(AInput, AOutput: PByte; ABlockCount: Int32): Int32; overload; + procedure ProcessBytes(const AInBytes: TCryptoLibByteArray; AInOff, ALen: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); virtual; @@ -319,13 +334,80 @@ procedure TSalsa20Engine.ProcessBlocks2( const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); begin AssertInitialisedAndBlockAligned; + ProcessBlocks2Fast(PByte(@AInBytes[AInOff]), PByte(@AOutBytes[AOutOff])); +end; + +procedure TSalsa20Engine.ProcessBlockFast(AIn, AOut: PByte); +begin + GenerateKeyStream(FKeyStream); + AdvanceCounter(); + TByteUtilities.&Xor(64, AIn, PByte(FKeyStream), AOut); +end; +procedure TSalsa20Engine.ProcessBlocks2Fast(AIn, AOut: PByte); +begin if TSalsaSimd.TryProcessBlocks2(FRounds, PByte(@FEngineState[0]), - PByte(@AInBytes[AInOff]), PByte(@AOutBytes[AOutOff])) then + AIn, AOut) then Exit; - ImplProcessBlock(AInBytes, AInOff, AOutBytes, AOutOff); - ImplProcessBlock(AInBytes, AInOff + 64, AOutBytes, AOutOff + 64); + ProcessBlockFast(AIn, AOut); + ProcessBlockFast(AIn + 64, AOut + 64); +end; + +function TSalsa20Engine.DoProcessBlocks(AIn, AOut: PByte; + ABlockCount: Int32): Int32; +begin + Result := ABlockCount * 64; + while ABlockCount >= 2 do + begin + ProcessBlocks2Fast(AIn, AOut); + AIn := AIn + 128; + AOut := AOut + 128; + System.Dec(ABlockCount, 2); + end; + while ABlockCount >= 1 do + begin + ProcessBlockFast(AIn, AOut); + AIn := AIn + 64; + AOut := AOut + 64; + System.Dec(ABlockCount); + end; +end; + +function TSalsa20Engine.ProcessBlocks(const AInBuf: TCryptoLibByteArray; + AInOff, ABlockCount: Int32; const AOutBuf: TCryptoLibByteArray; + AOutOff: Int32): Int32; +begin + AssertInitialisedAndBlockAligned; + if (ABlockCount <= 0) then + begin + Result := 0; + Exit; + end; + if (LimitExceeded(UInt32(ABlockCount) * 64)) then + begin + raise EMaxBytesExceededCryptoLibException.CreateRes(@SMaxByteExceeded); + end; + + Result := DoProcessBlocks(PByte(@AInBuf[AInOff]), PByte(@AOutBuf[AOutOff]), + ABlockCount); +end; + +function TSalsa20Engine.ProcessBlocks(AInput, AOutput: PByte; + ABlockCount: Int32): Int32; +begin + AssertInitialisedAndBlockAligned; + if (ABlockCount <= 0) then + begin + Result := 0; + Exit; + end; + if (LimitExceeded(UInt32(ABlockCount) * 64)) then + begin + raise EMaxBytesExceededCryptoLibException.CreateRes(@SMaxByteExceeded); + end; + + Result := DoProcessBlocks(AInput, AOutput, ABlockCount); end; class procedure TSalsa20Engine.PackTauOrSigma(AKeyLength: Int32; diff --git a/CryptoLib/src/Crypto/Modes/ClpChaCha20Poly1305.pas b/CryptoLib/src/Crypto/Modes/ClpChaCha20Poly1305.pas index d875d4c5..e271fa51 100644 --- a/CryptoLib/src/Crypto/Modes/ClpChaCha20Poly1305.pas +++ b/CryptoLib/src/Crypto/Modes/ClpChaCha20Poly1305.pas @@ -28,6 +28,7 @@ interface ClpICipherParameters, ClpIKeyParameter, ClpCipherModeParameterUtilities, + ClpIBulkStreamCipher, ClpIChaCha7539Engine, ClpChaCha7539Engine, ClpPoly1305, @@ -107,6 +108,9 @@ TChaCha20Poly1305 = class(TInterfacedObject, IChaCha20Poly1305, IAeadCipher) var FChaCha20: IChaCha7539Engine; + // The cipher engine's bulk stream interface when it exposes one (resolved once); + // enables the 512B/8-way tier. nil => the narrower per-tier path is used. + FBulkChaCha: IBulkStreamCipher; FNonceBytes: Int32; FPoly1305: IMac; @@ -134,6 +138,10 @@ TChaCha20Poly1305 = class(TInterfacedObject, IChaCha20Poly1305, IAeadCipher) const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); procedure ProcessBlocks4(const AInBytes: TCryptoLibByteArray; AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); + // 8-block (512B) tier via the engine's bulk stream interface; keeps the same + // running data-count bookkeeping as the narrower tiers. + procedure ProcessBlocks8(const AInBytes: TCryptoLibByteArray; AInOff: Int32; + const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); procedure ProcessData(const AInBytes: TCryptoLibByteArray; AInOff, AInLen: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); procedure Reset(AClearMac, AResetCipher: Boolean); overload; @@ -202,6 +210,8 @@ constructor TChaCha20Poly1305.Create(const APoly1305: IMac; FPoly1305 := APoly1305; FChaCha20 := AEngine; + if not Supports(FChaCha20, IBulkStreamCipher, FBulkChaCha) then + FBulkChaCha := nil; FNonceBytes := ANonceBytes; System.SetLength(FKey, KeySize); @@ -451,6 +461,17 @@ function TChaCha20Poly1305.ProcessBytes(const AInput: TCryptoLibByteArray; AInOff := AInOff + LAvailable; LResultLen := LResultLen + BufSize; + if (FBulkChaCha <> nil) then + begin + while (AInOff <= LInLimit2 - (BufSize * 6)) do + begin + FPoly1305.BlockUpdate(AInput, AInOff, BufSize * 8); + ProcessBlocks8(AInput, AInOff, AOutput, AOutOff + LResultLen); + AInOff := AInOff + BufSize * 8; + LResultLen := LResultLen + BufSize * 8; + end; + end; + while (AInOff <= LInLimit2 - (BufSize * 2)) do begin FPoly1305.BlockUpdate(AInput, AInOff, BufSize * 4); @@ -500,6 +521,16 @@ function TChaCha20Poly1305.ProcessBytes(const AInput: TCryptoLibByteArray; LResultLen := BufSize; end; + if (FBulkChaCha <> nil) then + begin + while (AInOff <= LInLimit2 - (BufSize * 6)) do + begin + ProcessBlocks8(AInput, AInOff, AOutput, AOutOff + LResultLen); + AInOff := AInOff + BufSize * 8; + LResultLen := LResultLen + BufSize * 8; + end; + end; + while (AInOff <= LInLimit2 - (BufSize * 2)) do begin ProcessBlocks4(AInput, AInOff, AOutput, AOutOff + LResultLen); @@ -721,6 +752,16 @@ procedure TChaCha20Poly1305.ProcessBlocks4(const AInBytes: TCryptoLibByteArray; FDataCount := IncrementCount(FDataCount, 256, DataLimit); end; +procedure TChaCha20Poly1305.ProcessBlocks8(const AInBytes: TCryptoLibByteArray; + AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); +begin + TCheck.OutputLength(AOutBytes, AOutOff, 512, SOutputBufferTooShort); + + FBulkChaCha.ProcessBlocks(AInBytes, AInOff, 8, AOutBytes, AOutOff); + + FDataCount := IncrementCount(FDataCount, 512, DataLimit); +end; + procedure TChaCha20Poly1305.ProcessData(const AInBytes: TCryptoLibByteArray; AInOff, AInLen: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); begin diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Sse2_i386.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Sse2_i386.inc new file mode 100644 index 00000000..a5031baf --- /dev/null +++ b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Sse2_i386.inc @@ -0,0 +1,531 @@ +// ChaCha7539 (IETF) 4-way (256B) SSE2 keystream kernel, vertical layout (i386). +// ------------------------------------------------------------------- +// +// Four 64-byte ChaCha20 blocks, state words held vertically (one block per +// xmm lane). i386 has only 8 xmm, so the 16 state words live in a stack frame; +// each quarter-round loads its 4 words into xmm0-3 (temp xmm4). +// rot16/rot8 use shift+or; rot12/rot7 use shift+or. +// +// On entry (after ClpSimdProc4Begin_i386.inc): +// ebx = ARounds, esi = AState (16 UInt32), edi = AIn, eax = AOut. +// +// On exit: +// AState word-12 counter (byte 48) advanced by 4; the keystream is xored +// with AIn into AOut (256 bytes). +// +// punpck* / pshufb are db-encoded for broad assembler compatibility. + sub esp, 528 + mov dword ptr [esp + 512], 0 + mov dword ptr [esp + 516], 1 + mov dword ptr [esp + 520], 2 + mov dword ptr [esp + 524], 3 + movd xmm0, [esi] + pshufd xmm0, xmm0, $00 + movdqu [esp], xmm0 + movdqu [esp + 256], xmm0 + movd xmm0, [esi + 4] + pshufd xmm0, xmm0, $00 + movdqu [esp + 16], xmm0 + movdqu [esp + 272], xmm0 + movd xmm0, [esi + 8] + pshufd xmm0, xmm0, $00 + movdqu [esp + 32], xmm0 + movdqu [esp + 288], xmm0 + movd xmm0, [esi + 12] + pshufd xmm0, xmm0, $00 + movdqu [esp + 48], xmm0 + movdqu [esp + 304], xmm0 + movd xmm0, [esi + 16] + pshufd xmm0, xmm0, $00 + movdqu [esp + 64], xmm0 + movdqu [esp + 320], xmm0 + movd xmm0, [esi + 20] + pshufd xmm0, xmm0, $00 + movdqu [esp + 80], xmm0 + movdqu [esp + 336], xmm0 + movd xmm0, [esi + 24] + pshufd xmm0, xmm0, $00 + movdqu [esp + 96], xmm0 + movdqu [esp + 352], xmm0 + movd xmm0, [esi + 28] + pshufd xmm0, xmm0, $00 + movdqu [esp + 112], xmm0 + movdqu [esp + 368], xmm0 + movd xmm0, [esi + 32] + pshufd xmm0, xmm0, $00 + movdqu [esp + 128], xmm0 + movdqu [esp + 384], xmm0 + movd xmm0, [esi + 36] + pshufd xmm0, xmm0, $00 + movdqu [esp + 144], xmm0 + movdqu [esp + 400], xmm0 + movd xmm0, [esi + 40] + pshufd xmm0, xmm0, $00 + movdqu [esp + 160], xmm0 + movdqu [esp + 416], xmm0 + movd xmm0, [esi + 44] + pshufd xmm0, xmm0, $00 + movdqu [esp + 176], xmm0 + movdqu [esp + 432], xmm0 + movd xmm0, [esi + 48] + pshufd xmm0, xmm0, $00 + movdqu xmm1, [esp + 512] + paddd xmm0, xmm1 + movdqu [esp + 192], xmm0 + movdqu [esp + 448], xmm0 + movd xmm0, [esi + 52] + pshufd xmm0, xmm0, $00 + movdqu [esp + 208], xmm0 + movdqu [esp + 464], xmm0 + movd xmm0, [esi + 56] + pshufd xmm0, xmm0, $00 + movdqu [esp + 224], xmm0 + movdqu [esp + 480], xmm0 + movd xmm0, [esi + 60] + pshufd xmm0, xmm0, $00 + movdqu [esp + 240], xmm0 + movdqu [esp + 496], xmm0 +@@c7539_sse2_round: + movdqu xmm0, [esp] + movdqu xmm1, [esp + 64] + movdqu xmm2, [esp + 128] + movdqu xmm3, [esp + 192] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 16 + psrld xmm4, 16 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 8 + psrld xmm4, 24 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp], xmm0 + movdqu [esp + 64], xmm1 + movdqu [esp + 128], xmm2 + movdqu [esp + 192], xmm3 + movdqu xmm0, [esp + 16] + movdqu xmm1, [esp + 80] + movdqu xmm2, [esp + 144] + movdqu xmm3, [esp + 208] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 16 + psrld xmm4, 16 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 8 + psrld xmm4, 24 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp + 16], xmm0 + movdqu [esp + 80], xmm1 + movdqu [esp + 144], xmm2 + movdqu [esp + 208], xmm3 + movdqu xmm0, [esp + 32] + movdqu xmm1, [esp + 96] + movdqu xmm2, [esp + 160] + movdqu xmm3, [esp + 224] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 16 + psrld xmm4, 16 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 8 + psrld xmm4, 24 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp + 32], xmm0 + movdqu [esp + 96], xmm1 + movdqu [esp + 160], xmm2 + movdqu [esp + 224], xmm3 + movdqu xmm0, [esp + 48] + movdqu xmm1, [esp + 112] + movdqu xmm2, [esp + 176] + movdqu xmm3, [esp + 240] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 16 + psrld xmm4, 16 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 8 + psrld xmm4, 24 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp + 48], xmm0 + movdqu [esp + 112], xmm1 + movdqu [esp + 176], xmm2 + movdqu [esp + 240], xmm3 + movdqu xmm0, [esp] + movdqu xmm1, [esp + 80] + movdqu xmm2, [esp + 160] + movdqu xmm3, [esp + 240] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 16 + psrld xmm4, 16 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 8 + psrld xmm4, 24 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp], xmm0 + movdqu [esp + 80], xmm1 + movdqu [esp + 160], xmm2 + movdqu [esp + 240], xmm3 + movdqu xmm0, [esp + 16] + movdqu xmm1, [esp + 96] + movdqu xmm2, [esp + 176] + movdqu xmm3, [esp + 192] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 16 + psrld xmm4, 16 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 8 + psrld xmm4, 24 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp + 16], xmm0 + movdqu [esp + 96], xmm1 + movdqu [esp + 176], xmm2 + movdqu [esp + 192], xmm3 + movdqu xmm0, [esp + 32] + movdqu xmm1, [esp + 112] + movdqu xmm2, [esp + 128] + movdqu xmm3, [esp + 208] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 16 + psrld xmm4, 16 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 8 + psrld xmm4, 24 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp + 32], xmm0 + movdqu [esp + 112], xmm1 + movdqu [esp + 128], xmm2 + movdqu [esp + 208], xmm3 + movdqu xmm0, [esp + 48] + movdqu xmm1, [esp + 64] + movdqu xmm2, [esp + 144] + movdqu xmm3, [esp + 224] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 16 + psrld xmm4, 16 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + movdqa xmm4, xmm3 + pslld xmm3, 8 + psrld xmm4, 24 + por xmm3, xmm4 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp + 48], xmm0 + movdqu [esp + 64], xmm1 + movdqu [esp + 144], xmm2 + movdqu [esp + 224], xmm3 + sub ebx, 2 + jg @@c7539_sse2_round + movdqu xmm0, [esp] + movdqu xmm1, [esp + 256] + paddd xmm0, xmm1 + movdqu [esp], xmm0 + movdqu xmm0, [esp + 16] + movdqu xmm1, [esp + 272] + paddd xmm0, xmm1 + movdqu [esp + 16], xmm0 + movdqu xmm0, [esp + 32] + movdqu xmm1, [esp + 288] + paddd xmm0, xmm1 + movdqu [esp + 32], xmm0 + movdqu xmm0, [esp + 48] + movdqu xmm1, [esp + 304] + paddd xmm0, xmm1 + movdqu [esp + 48], xmm0 + movdqu xmm0, [esp + 64] + movdqu xmm1, [esp + 320] + paddd xmm0, xmm1 + movdqu [esp + 64], xmm0 + movdqu xmm0, [esp + 80] + movdqu xmm1, [esp + 336] + paddd xmm0, xmm1 + movdqu [esp + 80], xmm0 + movdqu xmm0, [esp + 96] + movdqu xmm1, [esp + 352] + paddd xmm0, xmm1 + movdqu [esp + 96], xmm0 + movdqu xmm0, [esp + 112] + movdqu xmm1, [esp + 368] + paddd xmm0, xmm1 + movdqu [esp + 112], xmm0 + movdqu xmm0, [esp + 128] + movdqu xmm1, [esp + 384] + paddd xmm0, xmm1 + movdqu [esp + 128], xmm0 + movdqu xmm0, [esp + 144] + movdqu xmm1, [esp + 400] + paddd xmm0, xmm1 + movdqu [esp + 144], xmm0 + movdqu xmm0, [esp + 160] + movdqu xmm1, [esp + 416] + paddd xmm0, xmm1 + movdqu [esp + 160], xmm0 + movdqu xmm0, [esp + 176] + movdqu xmm1, [esp + 432] + paddd xmm0, xmm1 + movdqu [esp + 176], xmm0 + movdqu xmm0, [esp + 192] + movdqu xmm1, [esp + 448] + paddd xmm0, xmm1 + movdqu [esp + 192], xmm0 + movdqu xmm0, [esp + 208] + movdqu xmm1, [esp + 464] + paddd xmm0, xmm1 + movdqu [esp + 208], xmm0 + movdqu xmm0, [esp + 224] + movdqu xmm1, [esp + 480] + paddd xmm0, xmm1 + movdqu [esp + 224], xmm0 + movdqu xmm0, [esp + 240] + movdqu xmm1, [esp + 496] + paddd xmm0, xmm1 + movdqu [esp + 240], xmm0 + add dword ptr [esi + 48], 4 +{$IFDEF CHACHA_CTR64} + adc dword ptr [esi + 52], 0 +{$ENDIF} + movdqu xmm0, [esp] + movdqu xmm1, [esp + 16] + movdqu xmm2, [esp + 32] + movdqu xmm3, [esp + 48] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm5, [edi] + pxor xmm0, xmm5 + movdqu [eax], xmm0 + movdqu xmm5, [edi + 64] + pxor xmm1, xmm5 + movdqu [eax + 64], xmm1 + movdqu xmm5, [edi + 128] + pxor xmm4, xmm5 + movdqu [eax + 128], xmm4 + movdqu xmm5, [edi + 192] + pxor xmm3, xmm5 + movdqu [eax + 192], xmm3 + movdqu xmm0, [esp + 64] + movdqu xmm1, [esp + 80] + movdqu xmm2, [esp + 96] + movdqu xmm3, [esp + 112] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm5, [edi + 16] + pxor xmm0, xmm5 + movdqu [eax + 16], xmm0 + movdqu xmm5, [edi + 80] + pxor xmm1, xmm5 + movdqu [eax + 80], xmm1 + movdqu xmm5, [edi + 144] + pxor xmm4, xmm5 + movdqu [eax + 144], xmm4 + movdqu xmm5, [edi + 208] + pxor xmm3, xmm5 + movdqu [eax + 208], xmm3 + movdqu xmm0, [esp + 128] + movdqu xmm1, [esp + 144] + movdqu xmm2, [esp + 160] + movdqu xmm3, [esp + 176] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm5, [edi + 32] + pxor xmm0, xmm5 + movdqu [eax + 32], xmm0 + movdqu xmm5, [edi + 96] + pxor xmm1, xmm5 + movdqu [eax + 96], xmm1 + movdqu xmm5, [edi + 160] + pxor xmm4, xmm5 + movdqu [eax + 160], xmm4 + movdqu xmm5, [edi + 224] + pxor xmm3, xmm5 + movdqu [eax + 224], xmm3 + movdqu xmm0, [esp + 192] + movdqu xmm1, [esp + 208] + movdqu xmm2, [esp + 224] + movdqu xmm3, [esp + 240] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm5, [edi + 48] + pxor xmm0, xmm5 + movdqu [eax + 48], xmm0 + movdqu xmm5, [edi + 112] + pxor xmm1, xmm5 + movdqu [eax + 112], xmm1 + movdqu xmm5, [edi + 176] + pxor xmm4, xmm5 + movdqu [eax + 176], xmm4 + movdqu xmm5, [edi + 240] + pxor xmm3, xmm5 + movdqu [eax + 240], xmm3 + add esp, 528 + pop edi + pop esi + pop ebx + diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Sse2_x86_64.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Sse2_x86_64.inc new file mode 100644 index 00000000..080a9a32 --- /dev/null +++ b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Sse2_x86_64.inc @@ -0,0 +1,460 @@ +// ChaCha7539 (IETF) 4-way (256B) SSE2 keystream kernel, vertical layout (x86-64). +// ------------------------------------------------------------------- +// +// Four 64-byte ChaCha20 blocks, state words held vertically (one block per +// xmm lane): xmm0-3 = words a (0-3), xmm4-7 = words b (4-7), xmm12-15 = words +// d (12-15). Words c (8-11) live in a stack slot; xmm8-9 are scratch. +// rot16/rot8 use shift+or; rot12/rot7 use shift+or. +// +// On entry (after ClpSimdProc4Begin_x86_64.inc): +// rcx = ARounds, rdx = AState (16 UInt32), r8 = AIn, r9 = AOut. +// +// On exit: +// AState word-12 counter (byte 48) advanced by 4; the keystream is xored +// with AIn into AOut (256 bytes). +// +// Ops touching the extended xmm8-15 registers are db-encoded for broad +// assembler compatibility. + mov r10, rcx +{$I ..\..\Include\Simd\Common\ClpSimdNonVolatileSave_x86_64.inc} + sub rsp, 336 + mov dword ptr [rsp + 320], 0 + mov dword ptr [rsp + 324], 1 + mov dword ptr [rsp + 328], 2 + mov dword ptr [rsp + 332], 3 + movd xmm0, [rdx] + pshufd xmm0, xmm0, $00 + movdqu [rsp + 64], xmm0 + movd xmm1, [rdx + 4] + pshufd xmm1, xmm1, $00 + movdqu [rsp + 80], xmm1 + movd xmm2, [rdx + 8] + pshufd xmm2, xmm2, $00 + movdqu [rsp + 96], xmm2 + movd xmm3, [rdx + 12] + pshufd xmm3, xmm3, $00 + movdqu [rsp + 112], xmm3 + movd xmm4, [rdx + 16] + pshufd xmm4, xmm4, $00 + movdqu [rsp + 128], xmm4 + movd xmm5, [rdx + 20] + pshufd xmm5, xmm5, $00 + movdqu [rsp + 144], xmm5 + movd xmm6, [rdx + 24] + pshufd xmm6, xmm6, $00 + movdqu [rsp + 160], xmm6 + movd xmm7, [rdx + 28] + pshufd xmm7, xmm7, $00 + movdqu [rsp + 176], xmm7 + movd xmm8, [rdx + 32] + db $66, $45, $0F, $70, $C0, $00 // pshufd xmm8, xmm8, $00 + movdqu [rsp], xmm8 + movdqu [rsp + 192], xmm8 + movd xmm8, [rdx + 36] + db $66, $45, $0F, $70, $C0, $00 // pshufd xmm8, xmm8, $00 + movdqu [rsp + 16], xmm8 + movdqu [rsp + 208], xmm8 + movd xmm8, [rdx + 40] + db $66, $45, $0F, $70, $C0, $00 // pshufd xmm8, xmm8, $00 + movdqu [rsp + 32], xmm8 + movdqu [rsp + 224], xmm8 + movd xmm8, [rdx + 44] + db $66, $45, $0F, $70, $C0, $00 // pshufd xmm8, xmm8, $00 + movdqu [rsp + 48], xmm8 + movdqu [rsp + 240], xmm8 + movd xmm12, [rdx + 48] + db $66, $45, $0F, $70, $E4, $00 // pshufd xmm12, xmm12, $00 + movdqu xmm8, [rsp + 320] + db $66, $45, $0F, $FE, $E0 // paddd xmm12, xmm8 + movdqu [rsp + 256], xmm12 + movd xmm13, [rdx + 52] + db $66, $45, $0F, $70, $ED, $00 // pshufd xmm13, xmm13, $00 + movdqu [rsp + 272], xmm13 + movd xmm14, [rdx + 56] + db $66, $45, $0F, $70, $F6, $00 // pshufd xmm14, xmm14, $00 + movdqu [rsp + 288], xmm14 + movd xmm15, [rdx + 60] + db $66, $45, $0F, $70, $FF, $00 // pshufd xmm15, xmm15, $00 + movdqu [rsp + 304], xmm15 +@@c7539_sse2_round: + movdqu xmm8, [rsp] + paddd xmm0, xmm4 + db $66, $44, $0F, $EF, $E0 // pxor xmm12, xmm0 + db $66, $45, $0F, $6F, $CC // movdqa xmm9, xmm12 + db $66, $41, $0F, $72, $F4, $10 // pslld xmm12, 16 + db $66, $41, $0F, $72, $D1, $10 // psrld xmm9, 16 + db $66, $45, $0F, $EB, $E1 // por xmm12, xmm9 + db $66, $45, $0F, $FE, $C4 // paddd xmm8, xmm12 + db $66, $41, $0F, $EF, $E0 // pxor xmm4, xmm8 + db $66, $44, $0F, $6F, $CC // movdqa xmm9, xmm4 + pslld xmm4, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $E1 // por xmm4, xmm9 + paddd xmm0, xmm4 + db $66, $44, $0F, $EF, $E0 // pxor xmm12, xmm0 + db $66, $45, $0F, $6F, $CC // movdqa xmm9, xmm12 + db $66, $41, $0F, $72, $F4, $08 // pslld xmm12, 8 + db $66, $41, $0F, $72, $D1, $18 // psrld xmm9, 24 + db $66, $45, $0F, $EB, $E1 // por xmm12, xmm9 + db $66, $45, $0F, $FE, $C4 // paddd xmm8, xmm12 + db $66, $41, $0F, $EF, $E0 // pxor xmm4, xmm8 + db $66, $44, $0F, $6F, $CC // movdqa xmm9, xmm4 + pslld xmm4, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $E1 // por xmm4, xmm9 + movdqu [rsp], xmm8 + movdqu xmm8, [rsp + 16] + paddd xmm1, xmm5 + db $66, $44, $0F, $EF, $E9 // pxor xmm13, xmm1 + db $66, $45, $0F, $6F, $CD // movdqa xmm9, xmm13 + db $66, $41, $0F, $72, $F5, $10 // pslld xmm13, 16 + db $66, $41, $0F, $72, $D1, $10 // psrld xmm9, 16 + db $66, $45, $0F, $EB, $E9 // por xmm13, xmm9 + db $66, $45, $0F, $FE, $C5 // paddd xmm8, xmm13 + db $66, $41, $0F, $EF, $E8 // pxor xmm5, xmm8 + db $66, $44, $0F, $6F, $CD // movdqa xmm9, xmm5 + pslld xmm5, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $E9 // por xmm5, xmm9 + paddd xmm1, xmm5 + db $66, $44, $0F, $EF, $E9 // pxor xmm13, xmm1 + db $66, $45, $0F, $6F, $CD // movdqa xmm9, xmm13 + db $66, $41, $0F, $72, $F5, $08 // pslld xmm13, 8 + db $66, $41, $0F, $72, $D1, $18 // psrld xmm9, 24 + db $66, $45, $0F, $EB, $E9 // por xmm13, xmm9 + db $66, $45, $0F, $FE, $C5 // paddd xmm8, xmm13 + db $66, $41, $0F, $EF, $E8 // pxor xmm5, xmm8 + db $66, $44, $0F, $6F, $CD // movdqa xmm9, xmm5 + pslld xmm5, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $E9 // por xmm5, xmm9 + movdqu [rsp + 16], xmm8 + movdqu xmm8, [rsp + 32] + paddd xmm2, xmm6 + db $66, $44, $0F, $EF, $F2 // pxor xmm14, xmm2 + db $66, $45, $0F, $6F, $CE // movdqa xmm9, xmm14 + db $66, $41, $0F, $72, $F6, $10 // pslld xmm14, 16 + db $66, $41, $0F, $72, $D1, $10 // psrld xmm9, 16 + db $66, $45, $0F, $EB, $F1 // por xmm14, xmm9 + db $66, $45, $0F, $FE, $C6 // paddd xmm8, xmm14 + db $66, $41, $0F, $EF, $F0 // pxor xmm6, xmm8 + db $66, $44, $0F, $6F, $CE // movdqa xmm9, xmm6 + pslld xmm6, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $F1 // por xmm6, xmm9 + paddd xmm2, xmm6 + db $66, $44, $0F, $EF, $F2 // pxor xmm14, xmm2 + db $66, $45, $0F, $6F, $CE // movdqa xmm9, xmm14 + db $66, $41, $0F, $72, $F6, $08 // pslld xmm14, 8 + db $66, $41, $0F, $72, $D1, $18 // psrld xmm9, 24 + db $66, $45, $0F, $EB, $F1 // por xmm14, xmm9 + db $66, $45, $0F, $FE, $C6 // paddd xmm8, xmm14 + db $66, $41, $0F, $EF, $F0 // pxor xmm6, xmm8 + db $66, $44, $0F, $6F, $CE // movdqa xmm9, xmm6 + pslld xmm6, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $F1 // por xmm6, xmm9 + movdqu [rsp + 32], xmm8 + movdqu xmm8, [rsp + 48] + paddd xmm3, xmm7 + db $66, $44, $0F, $EF, $FB // pxor xmm15, xmm3 + db $66, $45, $0F, $6F, $CF // movdqa xmm9, xmm15 + db $66, $41, $0F, $72, $F7, $10 // pslld xmm15, 16 + db $66, $41, $0F, $72, $D1, $10 // psrld xmm9, 16 + db $66, $45, $0F, $EB, $F9 // por xmm15, xmm9 + db $66, $45, $0F, $FE, $C7 // paddd xmm8, xmm15 + db $66, $41, $0F, $EF, $F8 // pxor xmm7, xmm8 + db $66, $44, $0F, $6F, $CF // movdqa xmm9, xmm7 + pslld xmm7, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $F9 // por xmm7, xmm9 + paddd xmm3, xmm7 + db $66, $44, $0F, $EF, $FB // pxor xmm15, xmm3 + db $66, $45, $0F, $6F, $CF // movdqa xmm9, xmm15 + db $66, $41, $0F, $72, $F7, $08 // pslld xmm15, 8 + db $66, $41, $0F, $72, $D1, $18 // psrld xmm9, 24 + db $66, $45, $0F, $EB, $F9 // por xmm15, xmm9 + db $66, $45, $0F, $FE, $C7 // paddd xmm8, xmm15 + db $66, $41, $0F, $EF, $F8 // pxor xmm7, xmm8 + db $66, $44, $0F, $6F, $CF // movdqa xmm9, xmm7 + pslld xmm7, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $F9 // por xmm7, xmm9 + movdqu [rsp + 48], xmm8 + movdqu xmm8, [rsp + 32] + paddd xmm0, xmm5 + db $66, $44, $0F, $EF, $F8 // pxor xmm15, xmm0 + db $66, $45, $0F, $6F, $CF // movdqa xmm9, xmm15 + db $66, $41, $0F, $72, $F7, $10 // pslld xmm15, 16 + db $66, $41, $0F, $72, $D1, $10 // psrld xmm9, 16 + db $66, $45, $0F, $EB, $F9 // por xmm15, xmm9 + db $66, $45, $0F, $FE, $C7 // paddd xmm8, xmm15 + db $66, $41, $0F, $EF, $E8 // pxor xmm5, xmm8 + db $66, $44, $0F, $6F, $CD // movdqa xmm9, xmm5 + pslld xmm5, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $E9 // por xmm5, xmm9 + paddd xmm0, xmm5 + db $66, $44, $0F, $EF, $F8 // pxor xmm15, xmm0 + db $66, $45, $0F, $6F, $CF // movdqa xmm9, xmm15 + db $66, $41, $0F, $72, $F7, $08 // pslld xmm15, 8 + db $66, $41, $0F, $72, $D1, $18 // psrld xmm9, 24 + db $66, $45, $0F, $EB, $F9 // por xmm15, xmm9 + db $66, $45, $0F, $FE, $C7 // paddd xmm8, xmm15 + db $66, $41, $0F, $EF, $E8 // pxor xmm5, xmm8 + db $66, $44, $0F, $6F, $CD // movdqa xmm9, xmm5 + pslld xmm5, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $E9 // por xmm5, xmm9 + movdqu [rsp + 32], xmm8 + movdqu xmm8, [rsp + 48] + paddd xmm1, xmm6 + db $66, $44, $0F, $EF, $E1 // pxor xmm12, xmm1 + db $66, $45, $0F, $6F, $CC // movdqa xmm9, xmm12 + db $66, $41, $0F, $72, $F4, $10 // pslld xmm12, 16 + db $66, $41, $0F, $72, $D1, $10 // psrld xmm9, 16 + db $66, $45, $0F, $EB, $E1 // por xmm12, xmm9 + db $66, $45, $0F, $FE, $C4 // paddd xmm8, xmm12 + db $66, $41, $0F, $EF, $F0 // pxor xmm6, xmm8 + db $66, $44, $0F, $6F, $CE // movdqa xmm9, xmm6 + pslld xmm6, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $F1 // por xmm6, xmm9 + paddd xmm1, xmm6 + db $66, $44, $0F, $EF, $E1 // pxor xmm12, xmm1 + db $66, $45, $0F, $6F, $CC // movdqa xmm9, xmm12 + db $66, $41, $0F, $72, $F4, $08 // pslld xmm12, 8 + db $66, $41, $0F, $72, $D1, $18 // psrld xmm9, 24 + db $66, $45, $0F, $EB, $E1 // por xmm12, xmm9 + db $66, $45, $0F, $FE, $C4 // paddd xmm8, xmm12 + db $66, $41, $0F, $EF, $F0 // pxor xmm6, xmm8 + db $66, $44, $0F, $6F, $CE // movdqa xmm9, xmm6 + pslld xmm6, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $F1 // por xmm6, xmm9 + movdqu [rsp + 48], xmm8 + movdqu xmm8, [rsp] + paddd xmm2, xmm7 + db $66, $44, $0F, $EF, $EA // pxor xmm13, xmm2 + db $66, $45, $0F, $6F, $CD // movdqa xmm9, xmm13 + db $66, $41, $0F, $72, $F5, $10 // pslld xmm13, 16 + db $66, $41, $0F, $72, $D1, $10 // psrld xmm9, 16 + db $66, $45, $0F, $EB, $E9 // por xmm13, xmm9 + db $66, $45, $0F, $FE, $C5 // paddd xmm8, xmm13 + db $66, $41, $0F, $EF, $F8 // pxor xmm7, xmm8 + db $66, $44, $0F, $6F, $CF // movdqa xmm9, xmm7 + pslld xmm7, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $F9 // por xmm7, xmm9 + paddd xmm2, xmm7 + db $66, $44, $0F, $EF, $EA // pxor xmm13, xmm2 + db $66, $45, $0F, $6F, $CD // movdqa xmm9, xmm13 + db $66, $41, $0F, $72, $F5, $08 // pslld xmm13, 8 + db $66, $41, $0F, $72, $D1, $18 // psrld xmm9, 24 + db $66, $45, $0F, $EB, $E9 // por xmm13, xmm9 + db $66, $45, $0F, $FE, $C5 // paddd xmm8, xmm13 + db $66, $41, $0F, $EF, $F8 // pxor xmm7, xmm8 + db $66, $44, $0F, $6F, $CF // movdqa xmm9, xmm7 + pslld xmm7, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $F9 // por xmm7, xmm9 + movdqu [rsp], xmm8 + movdqu xmm8, [rsp + 16] + paddd xmm3, xmm4 + db $66, $44, $0F, $EF, $F3 // pxor xmm14, xmm3 + db $66, $45, $0F, $6F, $CE // movdqa xmm9, xmm14 + db $66, $41, $0F, $72, $F6, $10 // pslld xmm14, 16 + db $66, $41, $0F, $72, $D1, $10 // psrld xmm9, 16 + db $66, $45, $0F, $EB, $F1 // por xmm14, xmm9 + db $66, $45, $0F, $FE, $C6 // paddd xmm8, xmm14 + db $66, $41, $0F, $EF, $E0 // pxor xmm4, xmm8 + db $66, $44, $0F, $6F, $CC // movdqa xmm9, xmm4 + pslld xmm4, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $E1 // por xmm4, xmm9 + paddd xmm3, xmm4 + db $66, $44, $0F, $EF, $F3 // pxor xmm14, xmm3 + db $66, $45, $0F, $6F, $CE // movdqa xmm9, xmm14 + db $66, $41, $0F, $72, $F6, $08 // pslld xmm14, 8 + db $66, $41, $0F, $72, $D1, $18 // psrld xmm9, 24 + db $66, $45, $0F, $EB, $F1 // por xmm14, xmm9 + db $66, $45, $0F, $FE, $C6 // paddd xmm8, xmm14 + db $66, $41, $0F, $EF, $E0 // pxor xmm4, xmm8 + db $66, $44, $0F, $6F, $CC // movdqa xmm9, xmm4 + pslld xmm4, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $E1 // por xmm4, xmm9 + movdqu [rsp + 16], xmm8 + sub r10, 2 + jg @@c7539_sse2_round + movdqu xmm8, [rsp + 64] + db $66, $41, $0F, $FE, $C0 // paddd xmm0, xmm8 + movdqu [rsp + 64], xmm0 + movdqu xmm8, [rsp + 80] + db $66, $41, $0F, $FE, $C8 // paddd xmm1, xmm8 + movdqu [rsp + 80], xmm1 + movdqu xmm8, [rsp + 96] + db $66, $41, $0F, $FE, $D0 // paddd xmm2, xmm8 + movdqu [rsp + 96], xmm2 + movdqu xmm8, [rsp + 112] + db $66, $41, $0F, $FE, $D8 // paddd xmm3, xmm8 + movdqu [rsp + 112], xmm3 + movdqu xmm8, [rsp + 128] + db $66, $41, $0F, $FE, $E0 // paddd xmm4, xmm8 + movdqu [rsp + 128], xmm4 + movdqu xmm8, [rsp + 144] + db $66, $41, $0F, $FE, $E8 // paddd xmm5, xmm8 + movdqu [rsp + 144], xmm5 + movdqu xmm8, [rsp + 160] + db $66, $41, $0F, $FE, $F0 // paddd xmm6, xmm8 + movdqu [rsp + 160], xmm6 + movdqu xmm8, [rsp + 176] + db $66, $41, $0F, $FE, $F8 // paddd xmm7, xmm8 + movdqu [rsp + 176], xmm7 + movdqu xmm8, [rsp + 256] + db $66, $45, $0F, $FE, $E0 // paddd xmm12, xmm8 + movdqu [rsp + 256], xmm12 + movdqu xmm8, [rsp + 272] + db $66, $45, $0F, $FE, $E8 // paddd xmm13, xmm8 + movdqu [rsp + 272], xmm13 + movdqu xmm8, [rsp + 288] + db $66, $45, $0F, $FE, $F0 // paddd xmm14, xmm8 + movdqu [rsp + 288], xmm14 + movdqu xmm8, [rsp + 304] + db $66, $45, $0F, $FE, $F8 // paddd xmm15, xmm8 + movdqu [rsp + 304], xmm15 + movdqu xmm8, [rsp] + movdqu xmm9, [rsp + 192] + db $66, $45, $0F, $FE, $C1 // paddd xmm8, xmm9 + movdqu [rsp + 192], xmm8 + movdqu xmm8, [rsp + 16] + movdqu xmm9, [rsp + 208] + db $66, $45, $0F, $FE, $C1 // paddd xmm8, xmm9 + movdqu [rsp + 208], xmm8 + movdqu xmm8, [rsp + 32] + movdqu xmm9, [rsp + 224] + db $66, $45, $0F, $FE, $C1 // paddd xmm8, xmm9 + movdqu [rsp + 224], xmm8 + movdqu xmm8, [rsp + 48] + movdqu xmm9, [rsp + 240] + db $66, $45, $0F, $FE, $C1 // paddd xmm8, xmm9 + movdqu [rsp + 240], xmm8 + add dword ptr [rdx + 48], 4 +{$IFDEF CHACHA_CTR64} + adc dword ptr [rdx + 52], 0 +{$ENDIF} + movdqu xmm0, [rsp + 64] + movdqu xmm1, [rsp + 80] + movdqu xmm2, [rsp + 96] + movdqu xmm3, [rsp + 112] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm6, [r8] + pxor xmm0, xmm6 + movdqu [r9], xmm0 + movdqu xmm6, [r8 + 64] + pxor xmm1, xmm6 + movdqu [r9 + 64], xmm1 + movdqu xmm6, [r8 + 128] + pxor xmm4, xmm6 + movdqu [r9 + 128], xmm4 + movdqu xmm6, [r8 + 192] + pxor xmm3, xmm6 + movdqu [r9 + 192], xmm3 + movdqu xmm0, [rsp + 128] + movdqu xmm1, [rsp + 144] + movdqu xmm2, [rsp + 160] + movdqu xmm3, [rsp + 176] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm6, [r8 + 16] + pxor xmm0, xmm6 + movdqu [r9 + 16], xmm0 + movdqu xmm6, [r8 + 80] + pxor xmm1, xmm6 + movdqu [r9 + 80], xmm1 + movdqu xmm6, [r8 + 144] + pxor xmm4, xmm6 + movdqu [r9 + 144], xmm4 + movdqu xmm6, [r8 + 208] + pxor xmm3, xmm6 + movdqu [r9 + 208], xmm3 + movdqu xmm0, [rsp + 192] + movdqu xmm1, [rsp + 208] + movdqu xmm2, [rsp + 224] + movdqu xmm3, [rsp + 240] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm6, [r8 + 32] + pxor xmm0, xmm6 + movdqu [r9 + 32], xmm0 + movdqu xmm6, [r8 + 96] + pxor xmm1, xmm6 + movdqu [r9 + 96], xmm1 + movdqu xmm6, [r8 + 160] + pxor xmm4, xmm6 + movdqu [r9 + 160], xmm4 + movdqu xmm6, [r8 + 224] + pxor xmm3, xmm6 + movdqu [r9 + 224], xmm3 + movdqu xmm0, [rsp + 256] + movdqu xmm1, [rsp + 272] + movdqu xmm2, [rsp + 288] + movdqu xmm3, [rsp + 304] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm6, [r8 + 48] + pxor xmm0, xmm6 + movdqu [r9 + 48], xmm0 + movdqu xmm6, [r8 + 112] + pxor xmm1, xmm6 + movdqu [r9 + 112], xmm1 + movdqu xmm6, [r8 + 176] + pxor xmm4, xmm6 + movdqu [r9 + 176], xmm4 + movdqu xmm6, [r8 + 240] + pxor xmm3, xmm6 + movdqu [r9 + 240], xmm3 + add rsp, 336 +{$I ..\..\Include\Simd\Common\ClpSimdNonVolatileRestore_x86_64.inc} + diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Ssse3_i386.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Ssse3_i386.inc new file mode 100644 index 00000000..7af122fb --- /dev/null +++ b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Ssse3_i386.inc @@ -0,0 +1,493 @@ +// ChaCha7539 (IETF) 4-way (256B) SSSE3 keystream kernel, vertical layout (i386). +// ------------------------------------------------------------------- +// +// Four 64-byte ChaCha20 blocks, state words held vertically (one block per +// xmm lane). i386 has only 8 xmm, so the 16 state words live in a stack frame; +// each quarter-round loads its 4 words into xmm0-3 (temp xmm4) and the rot16/rot8 masks in xmm6-7. +// rot16/rot8 use pshufb; rot12/rot7 use shift+or. +// +// On entry (after ClpSimdProc4Begin_i386.inc): +// ebx = ARounds, esi = AState (16 UInt32), edi = AIn, eax = AOut. +// +// On exit: +// AState word-12 counter (byte 48) advanced by 4; the keystream is xored +// with AIn into AOut (256 bytes). +// +// punpck* / pshufb are db-encoded for broad assembler compatibility. + sub esp, 560 + mov dword ptr [esp + 528], $01000302 + mov dword ptr [esp + 532], $05040706 + mov dword ptr [esp + 536], $09080B0A + mov dword ptr [esp + 540], $0D0C0F0E + mov dword ptr [esp + 544], $02010003 + mov dword ptr [esp + 548], $06050407 + mov dword ptr [esp + 552], $0A09080B + mov dword ptr [esp + 556], $0E0D0C0F + movdqu xmm6, [esp + 528] + movdqu xmm7, [esp + 544] + mov dword ptr [esp + 512], 0 + mov dword ptr [esp + 516], 1 + mov dword ptr [esp + 520], 2 + mov dword ptr [esp + 524], 3 + movd xmm0, [esi] + pshufd xmm0, xmm0, $00 + movdqu [esp], xmm0 + movdqu [esp + 256], xmm0 + movd xmm0, [esi + 4] + pshufd xmm0, xmm0, $00 + movdqu [esp + 16], xmm0 + movdqu [esp + 272], xmm0 + movd xmm0, [esi + 8] + pshufd xmm0, xmm0, $00 + movdqu [esp + 32], xmm0 + movdqu [esp + 288], xmm0 + movd xmm0, [esi + 12] + pshufd xmm0, xmm0, $00 + movdqu [esp + 48], xmm0 + movdqu [esp + 304], xmm0 + movd xmm0, [esi + 16] + pshufd xmm0, xmm0, $00 + movdqu [esp + 64], xmm0 + movdqu [esp + 320], xmm0 + movd xmm0, [esi + 20] + pshufd xmm0, xmm0, $00 + movdqu [esp + 80], xmm0 + movdqu [esp + 336], xmm0 + movd xmm0, [esi + 24] + pshufd xmm0, xmm0, $00 + movdqu [esp + 96], xmm0 + movdqu [esp + 352], xmm0 + movd xmm0, [esi + 28] + pshufd xmm0, xmm0, $00 + movdqu [esp + 112], xmm0 + movdqu [esp + 368], xmm0 + movd xmm0, [esi + 32] + pshufd xmm0, xmm0, $00 + movdqu [esp + 128], xmm0 + movdqu [esp + 384], xmm0 + movd xmm0, [esi + 36] + pshufd xmm0, xmm0, $00 + movdqu [esp + 144], xmm0 + movdqu [esp + 400], xmm0 + movd xmm0, [esi + 40] + pshufd xmm0, xmm0, $00 + movdqu [esp + 160], xmm0 + movdqu [esp + 416], xmm0 + movd xmm0, [esi + 44] + pshufd xmm0, xmm0, $00 + movdqu [esp + 176], xmm0 + movdqu [esp + 432], xmm0 + movd xmm0, [esi + 48] + pshufd xmm0, xmm0, $00 + movdqu xmm1, [esp + 512] + paddd xmm0, xmm1 + movdqu [esp + 192], xmm0 + movdqu [esp + 448], xmm0 + movd xmm0, [esi + 52] + pshufd xmm0, xmm0, $00 + movdqu [esp + 208], xmm0 + movdqu [esp + 464], xmm0 + movd xmm0, [esi + 56] + pshufd xmm0, xmm0, $00 + movdqu [esp + 224], xmm0 + movdqu [esp + 480], xmm0 + movd xmm0, [esi + 60] + pshufd xmm0, xmm0, $00 + movdqu [esp + 240], xmm0 + movdqu [esp + 496], xmm0 +@@c7539_ssse3_round: + movdqu xmm0, [esp] + movdqu xmm1, [esp + 64] + movdqu xmm2, [esp + 128] + movdqu xmm3, [esp + 192] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DE // pshufb xmm3, xmm6 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DF // pshufb xmm3, xmm7 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp], xmm0 + movdqu [esp + 64], xmm1 + movdqu [esp + 128], xmm2 + movdqu [esp + 192], xmm3 + movdqu xmm0, [esp + 16] + movdqu xmm1, [esp + 80] + movdqu xmm2, [esp + 144] + movdqu xmm3, [esp + 208] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DE // pshufb xmm3, xmm6 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DF // pshufb xmm3, xmm7 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp + 16], xmm0 + movdqu [esp + 80], xmm1 + movdqu [esp + 144], xmm2 + movdqu [esp + 208], xmm3 + movdqu xmm0, [esp + 32] + movdqu xmm1, [esp + 96] + movdqu xmm2, [esp + 160] + movdqu xmm3, [esp + 224] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DE // pshufb xmm3, xmm6 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DF // pshufb xmm3, xmm7 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp + 32], xmm0 + movdqu [esp + 96], xmm1 + movdqu [esp + 160], xmm2 + movdqu [esp + 224], xmm3 + movdqu xmm0, [esp + 48] + movdqu xmm1, [esp + 112] + movdqu xmm2, [esp + 176] + movdqu xmm3, [esp + 240] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DE // pshufb xmm3, xmm6 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DF // pshufb xmm3, xmm7 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp + 48], xmm0 + movdqu [esp + 112], xmm1 + movdqu [esp + 176], xmm2 + movdqu [esp + 240], xmm3 + movdqu xmm0, [esp] + movdqu xmm1, [esp + 80] + movdqu xmm2, [esp + 160] + movdqu xmm3, [esp + 240] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DE // pshufb xmm3, xmm6 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DF // pshufb xmm3, xmm7 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp], xmm0 + movdqu [esp + 80], xmm1 + movdqu [esp + 160], xmm2 + movdqu [esp + 240], xmm3 + movdqu xmm0, [esp + 16] + movdqu xmm1, [esp + 96] + movdqu xmm2, [esp + 176] + movdqu xmm3, [esp + 192] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DE // pshufb xmm3, xmm6 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DF // pshufb xmm3, xmm7 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp + 16], xmm0 + movdqu [esp + 96], xmm1 + movdqu [esp + 176], xmm2 + movdqu [esp + 192], xmm3 + movdqu xmm0, [esp + 32] + movdqu xmm1, [esp + 112] + movdqu xmm2, [esp + 128] + movdqu xmm3, [esp + 208] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DE // pshufb xmm3, xmm6 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DF // pshufb xmm3, xmm7 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp + 32], xmm0 + movdqu [esp + 112], xmm1 + movdqu [esp + 128], xmm2 + movdqu [esp + 208], xmm3 + movdqu xmm0, [esp + 48] + movdqu xmm1, [esp + 64] + movdqu xmm2, [esp + 144] + movdqu xmm3, [esp + 224] + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DE // pshufb xmm3, xmm6 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 12 + psrld xmm4, 20 + por xmm1, xmm4 + paddd xmm0, xmm1 + pxor xmm3, xmm0 + db $66, $0F, $38, $00, $DF // pshufb xmm3, xmm7 + paddd xmm2, xmm3 + pxor xmm1, xmm2 + movdqa xmm4, xmm1 + pslld xmm1, 7 + psrld xmm4, 25 + por xmm1, xmm4 + movdqu [esp + 48], xmm0 + movdqu [esp + 64], xmm1 + movdqu [esp + 144], xmm2 + movdqu [esp + 224], xmm3 + sub ebx, 2 + jg @@c7539_ssse3_round + movdqu xmm0, [esp] + movdqu xmm1, [esp + 256] + paddd xmm0, xmm1 + movdqu [esp], xmm0 + movdqu xmm0, [esp + 16] + movdqu xmm1, [esp + 272] + paddd xmm0, xmm1 + movdqu [esp + 16], xmm0 + movdqu xmm0, [esp + 32] + movdqu xmm1, [esp + 288] + paddd xmm0, xmm1 + movdqu [esp + 32], xmm0 + movdqu xmm0, [esp + 48] + movdqu xmm1, [esp + 304] + paddd xmm0, xmm1 + movdqu [esp + 48], xmm0 + movdqu xmm0, [esp + 64] + movdqu xmm1, [esp + 320] + paddd xmm0, xmm1 + movdqu [esp + 64], xmm0 + movdqu xmm0, [esp + 80] + movdqu xmm1, [esp + 336] + paddd xmm0, xmm1 + movdqu [esp + 80], xmm0 + movdqu xmm0, [esp + 96] + movdqu xmm1, [esp + 352] + paddd xmm0, xmm1 + movdqu [esp + 96], xmm0 + movdqu xmm0, [esp + 112] + movdqu xmm1, [esp + 368] + paddd xmm0, xmm1 + movdqu [esp + 112], xmm0 + movdqu xmm0, [esp + 128] + movdqu xmm1, [esp + 384] + paddd xmm0, xmm1 + movdqu [esp + 128], xmm0 + movdqu xmm0, [esp + 144] + movdqu xmm1, [esp + 400] + paddd xmm0, xmm1 + movdqu [esp + 144], xmm0 + movdqu xmm0, [esp + 160] + movdqu xmm1, [esp + 416] + paddd xmm0, xmm1 + movdqu [esp + 160], xmm0 + movdqu xmm0, [esp + 176] + movdqu xmm1, [esp + 432] + paddd xmm0, xmm1 + movdqu [esp + 176], xmm0 + movdqu xmm0, [esp + 192] + movdqu xmm1, [esp + 448] + paddd xmm0, xmm1 + movdqu [esp + 192], xmm0 + movdqu xmm0, [esp + 208] + movdqu xmm1, [esp + 464] + paddd xmm0, xmm1 + movdqu [esp + 208], xmm0 + movdqu xmm0, [esp + 224] + movdqu xmm1, [esp + 480] + paddd xmm0, xmm1 + movdqu [esp + 224], xmm0 + movdqu xmm0, [esp + 240] + movdqu xmm1, [esp + 496] + paddd xmm0, xmm1 + movdqu [esp + 240], xmm0 + add dword ptr [esi + 48], 4 +{$IFDEF CHACHA_CTR64} + adc dword ptr [esi + 52], 0 +{$ENDIF} + movdqu xmm0, [esp] + movdqu xmm1, [esp + 16] + movdqu xmm2, [esp + 32] + movdqu xmm3, [esp + 48] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm5, [edi] + pxor xmm0, xmm5 + movdqu [eax], xmm0 + movdqu xmm5, [edi + 64] + pxor xmm1, xmm5 + movdqu [eax + 64], xmm1 + movdqu xmm5, [edi + 128] + pxor xmm4, xmm5 + movdqu [eax + 128], xmm4 + movdqu xmm5, [edi + 192] + pxor xmm3, xmm5 + movdqu [eax + 192], xmm3 + movdqu xmm0, [esp + 64] + movdqu xmm1, [esp + 80] + movdqu xmm2, [esp + 96] + movdqu xmm3, [esp + 112] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm5, [edi + 16] + pxor xmm0, xmm5 + movdqu [eax + 16], xmm0 + movdqu xmm5, [edi + 80] + pxor xmm1, xmm5 + movdqu [eax + 80], xmm1 + movdqu xmm5, [edi + 144] + pxor xmm4, xmm5 + movdqu [eax + 144], xmm4 + movdqu xmm5, [edi + 208] + pxor xmm3, xmm5 + movdqu [eax + 208], xmm3 + movdqu xmm0, [esp + 128] + movdqu xmm1, [esp + 144] + movdqu xmm2, [esp + 160] + movdqu xmm3, [esp + 176] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm5, [edi + 32] + pxor xmm0, xmm5 + movdqu [eax + 32], xmm0 + movdqu xmm5, [edi + 96] + pxor xmm1, xmm5 + movdqu [eax + 96], xmm1 + movdqu xmm5, [edi + 160] + pxor xmm4, xmm5 + movdqu [eax + 160], xmm4 + movdqu xmm5, [edi + 224] + pxor xmm3, xmm5 + movdqu [eax + 224], xmm3 + movdqu xmm0, [esp + 192] + movdqu xmm1, [esp + 208] + movdqu xmm2, [esp + 224] + movdqu xmm3, [esp + 240] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm5, [edi + 48] + pxor xmm0, xmm5 + movdqu [eax + 48], xmm0 + movdqu xmm5, [edi + 112] + pxor xmm1, xmm5 + movdqu [eax + 112], xmm1 + movdqu xmm5, [edi + 176] + pxor xmm4, xmm5 + movdqu [eax + 176], xmm4 + movdqu xmm5, [edi + 240] + pxor xmm3, xmm5 + movdqu [eax + 240], xmm3 + add esp, 560 + pop edi + pop esi + pop ebx + diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Ssse3_x86_64.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Ssse3_x86_64.inc new file mode 100644 index 00000000..ac08b118 --- /dev/null +++ b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks4Ssse3_x86_64.inc @@ -0,0 +1,422 @@ +// ChaCha7539 (IETF) 4-way (256B) SSSE3 keystream kernel, vertical layout (x86-64). +// ------------------------------------------------------------------- +// +// Four 64-byte ChaCha20 blocks, state words held vertically (one block per +// xmm lane): xmm0-3 = words a (0-3), xmm4-7 = words b (4-7), xmm12-15 = words +// d (12-15). Words c (8-11) live in a stack slot; xmm8-9 are scratch, xmm10-11 the rot16/rot8 pshufb masks. +// rot16/rot8 use pshufb; rot12/rot7 use shift+or. +// +// On entry (after ClpSimdProc4Begin_x86_64.inc): +// rcx = ARounds, rdx = AState (16 UInt32), r8 = AIn, r9 = AOut. +// +// On exit: +// AState word-12 counter (byte 48) advanced by 4; the keystream is xored +// with AIn into AOut (256 bytes). +// +// Ops touching the extended xmm8-15 registers are db-encoded for broad +// assembler compatibility. + mov r10, rcx +{$I ..\..\Include\Simd\Common\ClpSimdNonVolatileSave_x86_64.inc} + sub rsp, 368 + mov dword ptr [rsp + 336], $01000302 + mov dword ptr [rsp + 340], $05040706 + mov dword ptr [rsp + 344], $09080B0A + mov dword ptr [rsp + 348], $0D0C0F0E + mov dword ptr [rsp + 352], $02010003 + mov dword ptr [rsp + 356], $06050407 + mov dword ptr [rsp + 360], $0A09080B + mov dword ptr [rsp + 364], $0E0D0C0F + movdqu xmm10, [rsp + 336] + movdqu xmm11, [rsp + 352] + mov dword ptr [rsp + 320], 0 + mov dword ptr [rsp + 324], 1 + mov dword ptr [rsp + 328], 2 + mov dword ptr [rsp + 332], 3 + movd xmm0, [rdx] + pshufd xmm0, xmm0, $00 + movdqu [rsp + 64], xmm0 + movd xmm1, [rdx + 4] + pshufd xmm1, xmm1, $00 + movdqu [rsp + 80], xmm1 + movd xmm2, [rdx + 8] + pshufd xmm2, xmm2, $00 + movdqu [rsp + 96], xmm2 + movd xmm3, [rdx + 12] + pshufd xmm3, xmm3, $00 + movdqu [rsp + 112], xmm3 + movd xmm4, [rdx + 16] + pshufd xmm4, xmm4, $00 + movdqu [rsp + 128], xmm4 + movd xmm5, [rdx + 20] + pshufd xmm5, xmm5, $00 + movdqu [rsp + 144], xmm5 + movd xmm6, [rdx + 24] + pshufd xmm6, xmm6, $00 + movdqu [rsp + 160], xmm6 + movd xmm7, [rdx + 28] + pshufd xmm7, xmm7, $00 + movdqu [rsp + 176], xmm7 + movd xmm8, [rdx + 32] + db $66, $45, $0F, $70, $C0, $00 // pshufd xmm8, xmm8, $00 + movdqu [rsp], xmm8 + movdqu [rsp + 192], xmm8 + movd xmm8, [rdx + 36] + db $66, $45, $0F, $70, $C0, $00 // pshufd xmm8, xmm8, $00 + movdqu [rsp + 16], xmm8 + movdqu [rsp + 208], xmm8 + movd xmm8, [rdx + 40] + db $66, $45, $0F, $70, $C0, $00 // pshufd xmm8, xmm8, $00 + movdqu [rsp + 32], xmm8 + movdqu [rsp + 224], xmm8 + movd xmm8, [rdx + 44] + db $66, $45, $0F, $70, $C0, $00 // pshufd xmm8, xmm8, $00 + movdqu [rsp + 48], xmm8 + movdqu [rsp + 240], xmm8 + movd xmm12, [rdx + 48] + db $66, $45, $0F, $70, $E4, $00 // pshufd xmm12, xmm12, $00 + movdqu xmm8, [rsp + 320] + db $66, $45, $0F, $FE, $E0 // paddd xmm12, xmm8 + movdqu [rsp + 256], xmm12 + movd xmm13, [rdx + 52] + db $66, $45, $0F, $70, $ED, $00 // pshufd xmm13, xmm13, $00 + movdqu [rsp + 272], xmm13 + movd xmm14, [rdx + 56] + db $66, $45, $0F, $70, $F6, $00 // pshufd xmm14, xmm14, $00 + movdqu [rsp + 288], xmm14 + movd xmm15, [rdx + 60] + db $66, $45, $0F, $70, $FF, $00 // pshufd xmm15, xmm15, $00 + movdqu [rsp + 304], xmm15 +@@c7539_ssse3_round: + movdqu xmm8, [rsp] + paddd xmm0, xmm4 + db $66, $44, $0F, $EF, $E0 // pxor xmm12, xmm0 + db $66, $45, $0F, $38, $00, $E2 // pshufb xmm12, xmm10 + db $66, $45, $0F, $FE, $C4 // paddd xmm8, xmm12 + db $66, $41, $0F, $EF, $E0 // pxor xmm4, xmm8 + db $66, $44, $0F, $6F, $CC // movdqa xmm9, xmm4 + pslld xmm4, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $E1 // por xmm4, xmm9 + paddd xmm0, xmm4 + db $66, $44, $0F, $EF, $E0 // pxor xmm12, xmm0 + db $66, $45, $0F, $38, $00, $E3 // pshufb xmm12, xmm11 + db $66, $45, $0F, $FE, $C4 // paddd xmm8, xmm12 + db $66, $41, $0F, $EF, $E0 // pxor xmm4, xmm8 + db $66, $44, $0F, $6F, $CC // movdqa xmm9, xmm4 + pslld xmm4, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $E1 // por xmm4, xmm9 + movdqu [rsp], xmm8 + movdqu xmm8, [rsp + 16] + paddd xmm1, xmm5 + db $66, $44, $0F, $EF, $E9 // pxor xmm13, xmm1 + db $66, $45, $0F, $38, $00, $EA // pshufb xmm13, xmm10 + db $66, $45, $0F, $FE, $C5 // paddd xmm8, xmm13 + db $66, $41, $0F, $EF, $E8 // pxor xmm5, xmm8 + db $66, $44, $0F, $6F, $CD // movdqa xmm9, xmm5 + pslld xmm5, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $E9 // por xmm5, xmm9 + paddd xmm1, xmm5 + db $66, $44, $0F, $EF, $E9 // pxor xmm13, xmm1 + db $66, $45, $0F, $38, $00, $EB // pshufb xmm13, xmm11 + db $66, $45, $0F, $FE, $C5 // paddd xmm8, xmm13 + db $66, $41, $0F, $EF, $E8 // pxor xmm5, xmm8 + db $66, $44, $0F, $6F, $CD // movdqa xmm9, xmm5 + pslld xmm5, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $E9 // por xmm5, xmm9 + movdqu [rsp + 16], xmm8 + movdqu xmm8, [rsp + 32] + paddd xmm2, xmm6 + db $66, $44, $0F, $EF, $F2 // pxor xmm14, xmm2 + db $66, $45, $0F, $38, $00, $F2 // pshufb xmm14, xmm10 + db $66, $45, $0F, $FE, $C6 // paddd xmm8, xmm14 + db $66, $41, $0F, $EF, $F0 // pxor xmm6, xmm8 + db $66, $44, $0F, $6F, $CE // movdqa xmm9, xmm6 + pslld xmm6, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $F1 // por xmm6, xmm9 + paddd xmm2, xmm6 + db $66, $44, $0F, $EF, $F2 // pxor xmm14, xmm2 + db $66, $45, $0F, $38, $00, $F3 // pshufb xmm14, xmm11 + db $66, $45, $0F, $FE, $C6 // paddd xmm8, xmm14 + db $66, $41, $0F, $EF, $F0 // pxor xmm6, xmm8 + db $66, $44, $0F, $6F, $CE // movdqa xmm9, xmm6 + pslld xmm6, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $F1 // por xmm6, xmm9 + movdqu [rsp + 32], xmm8 + movdqu xmm8, [rsp + 48] + paddd xmm3, xmm7 + db $66, $44, $0F, $EF, $FB // pxor xmm15, xmm3 + db $66, $45, $0F, $38, $00, $FA // pshufb xmm15, xmm10 + db $66, $45, $0F, $FE, $C7 // paddd xmm8, xmm15 + db $66, $41, $0F, $EF, $F8 // pxor xmm7, xmm8 + db $66, $44, $0F, $6F, $CF // movdqa xmm9, xmm7 + pslld xmm7, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $F9 // por xmm7, xmm9 + paddd xmm3, xmm7 + db $66, $44, $0F, $EF, $FB // pxor xmm15, xmm3 + db $66, $45, $0F, $38, $00, $FB // pshufb xmm15, xmm11 + db $66, $45, $0F, $FE, $C7 // paddd xmm8, xmm15 + db $66, $41, $0F, $EF, $F8 // pxor xmm7, xmm8 + db $66, $44, $0F, $6F, $CF // movdqa xmm9, xmm7 + pslld xmm7, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $F9 // por xmm7, xmm9 + movdqu [rsp + 48], xmm8 + movdqu xmm8, [rsp + 32] + paddd xmm0, xmm5 + db $66, $44, $0F, $EF, $F8 // pxor xmm15, xmm0 + db $66, $45, $0F, $38, $00, $FA // pshufb xmm15, xmm10 + db $66, $45, $0F, $FE, $C7 // paddd xmm8, xmm15 + db $66, $41, $0F, $EF, $E8 // pxor xmm5, xmm8 + db $66, $44, $0F, $6F, $CD // movdqa xmm9, xmm5 + pslld xmm5, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $E9 // por xmm5, xmm9 + paddd xmm0, xmm5 + db $66, $44, $0F, $EF, $F8 // pxor xmm15, xmm0 + db $66, $45, $0F, $38, $00, $FB // pshufb xmm15, xmm11 + db $66, $45, $0F, $FE, $C7 // paddd xmm8, xmm15 + db $66, $41, $0F, $EF, $E8 // pxor xmm5, xmm8 + db $66, $44, $0F, $6F, $CD // movdqa xmm9, xmm5 + pslld xmm5, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $E9 // por xmm5, xmm9 + movdqu [rsp + 32], xmm8 + movdqu xmm8, [rsp + 48] + paddd xmm1, xmm6 + db $66, $44, $0F, $EF, $E1 // pxor xmm12, xmm1 + db $66, $45, $0F, $38, $00, $E2 // pshufb xmm12, xmm10 + db $66, $45, $0F, $FE, $C4 // paddd xmm8, xmm12 + db $66, $41, $0F, $EF, $F0 // pxor xmm6, xmm8 + db $66, $44, $0F, $6F, $CE // movdqa xmm9, xmm6 + pslld xmm6, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $F1 // por xmm6, xmm9 + paddd xmm1, xmm6 + db $66, $44, $0F, $EF, $E1 // pxor xmm12, xmm1 + db $66, $45, $0F, $38, $00, $E3 // pshufb xmm12, xmm11 + db $66, $45, $0F, $FE, $C4 // paddd xmm8, xmm12 + db $66, $41, $0F, $EF, $F0 // pxor xmm6, xmm8 + db $66, $44, $0F, $6F, $CE // movdqa xmm9, xmm6 + pslld xmm6, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $F1 // por xmm6, xmm9 + movdqu [rsp + 48], xmm8 + movdqu xmm8, [rsp] + paddd xmm2, xmm7 + db $66, $44, $0F, $EF, $EA // pxor xmm13, xmm2 + db $66, $45, $0F, $38, $00, $EA // pshufb xmm13, xmm10 + db $66, $45, $0F, $FE, $C5 // paddd xmm8, xmm13 + db $66, $41, $0F, $EF, $F8 // pxor xmm7, xmm8 + db $66, $44, $0F, $6F, $CF // movdqa xmm9, xmm7 + pslld xmm7, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $F9 // por xmm7, xmm9 + paddd xmm2, xmm7 + db $66, $44, $0F, $EF, $EA // pxor xmm13, xmm2 + db $66, $45, $0F, $38, $00, $EB // pshufb xmm13, xmm11 + db $66, $45, $0F, $FE, $C5 // paddd xmm8, xmm13 + db $66, $41, $0F, $EF, $F8 // pxor xmm7, xmm8 + db $66, $44, $0F, $6F, $CF // movdqa xmm9, xmm7 + pslld xmm7, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $F9 // por xmm7, xmm9 + movdqu [rsp], xmm8 + movdqu xmm8, [rsp + 16] + paddd xmm3, xmm4 + db $66, $44, $0F, $EF, $F3 // pxor xmm14, xmm3 + db $66, $45, $0F, $38, $00, $F2 // pshufb xmm14, xmm10 + db $66, $45, $0F, $FE, $C6 // paddd xmm8, xmm14 + db $66, $41, $0F, $EF, $E0 // pxor xmm4, xmm8 + db $66, $44, $0F, $6F, $CC // movdqa xmm9, xmm4 + pslld xmm4, 12 + db $66, $41, $0F, $72, $D1, $14 // psrld xmm9, 20 + db $66, $41, $0F, $EB, $E1 // por xmm4, xmm9 + paddd xmm3, xmm4 + db $66, $44, $0F, $EF, $F3 // pxor xmm14, xmm3 + db $66, $45, $0F, $38, $00, $F3 // pshufb xmm14, xmm11 + db $66, $45, $0F, $FE, $C6 // paddd xmm8, xmm14 + db $66, $41, $0F, $EF, $E0 // pxor xmm4, xmm8 + db $66, $44, $0F, $6F, $CC // movdqa xmm9, xmm4 + pslld xmm4, 7 + db $66, $41, $0F, $72, $D1, $19 // psrld xmm9, 25 + db $66, $41, $0F, $EB, $E1 // por xmm4, xmm9 + movdqu [rsp + 16], xmm8 + sub r10, 2 + jg @@c7539_ssse3_round + movdqu xmm8, [rsp + 64] + db $66, $41, $0F, $FE, $C0 // paddd xmm0, xmm8 + movdqu [rsp + 64], xmm0 + movdqu xmm8, [rsp + 80] + db $66, $41, $0F, $FE, $C8 // paddd xmm1, xmm8 + movdqu [rsp + 80], xmm1 + movdqu xmm8, [rsp + 96] + db $66, $41, $0F, $FE, $D0 // paddd xmm2, xmm8 + movdqu [rsp + 96], xmm2 + movdqu xmm8, [rsp + 112] + db $66, $41, $0F, $FE, $D8 // paddd xmm3, xmm8 + movdqu [rsp + 112], xmm3 + movdqu xmm8, [rsp + 128] + db $66, $41, $0F, $FE, $E0 // paddd xmm4, xmm8 + movdqu [rsp + 128], xmm4 + movdqu xmm8, [rsp + 144] + db $66, $41, $0F, $FE, $E8 // paddd xmm5, xmm8 + movdqu [rsp + 144], xmm5 + movdqu xmm8, [rsp + 160] + db $66, $41, $0F, $FE, $F0 // paddd xmm6, xmm8 + movdqu [rsp + 160], xmm6 + movdqu xmm8, [rsp + 176] + db $66, $41, $0F, $FE, $F8 // paddd xmm7, xmm8 + movdqu [rsp + 176], xmm7 + movdqu xmm8, [rsp + 256] + db $66, $45, $0F, $FE, $E0 // paddd xmm12, xmm8 + movdqu [rsp + 256], xmm12 + movdqu xmm8, [rsp + 272] + db $66, $45, $0F, $FE, $E8 // paddd xmm13, xmm8 + movdqu [rsp + 272], xmm13 + movdqu xmm8, [rsp + 288] + db $66, $45, $0F, $FE, $F0 // paddd xmm14, xmm8 + movdqu [rsp + 288], xmm14 + movdqu xmm8, [rsp + 304] + db $66, $45, $0F, $FE, $F8 // paddd xmm15, xmm8 + movdqu [rsp + 304], xmm15 + movdqu xmm8, [rsp] + movdqu xmm9, [rsp + 192] + db $66, $45, $0F, $FE, $C1 // paddd xmm8, xmm9 + movdqu [rsp + 192], xmm8 + movdqu xmm8, [rsp + 16] + movdqu xmm9, [rsp + 208] + db $66, $45, $0F, $FE, $C1 // paddd xmm8, xmm9 + movdqu [rsp + 208], xmm8 + movdqu xmm8, [rsp + 32] + movdqu xmm9, [rsp + 224] + db $66, $45, $0F, $FE, $C1 // paddd xmm8, xmm9 + movdqu [rsp + 224], xmm8 + movdqu xmm8, [rsp + 48] + movdqu xmm9, [rsp + 240] + db $66, $45, $0F, $FE, $C1 // paddd xmm8, xmm9 + movdqu [rsp + 240], xmm8 + add dword ptr [rdx + 48], 4 +{$IFDEF CHACHA_CTR64} + adc dword ptr [rdx + 52], 0 +{$ENDIF} + movdqu xmm0, [rsp + 64] + movdqu xmm1, [rsp + 80] + movdqu xmm2, [rsp + 96] + movdqu xmm3, [rsp + 112] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm6, [r8] + pxor xmm0, xmm6 + movdqu [r9], xmm0 + movdqu xmm6, [r8 + 64] + pxor xmm1, xmm6 + movdqu [r9 + 64], xmm1 + movdqu xmm6, [r8 + 128] + pxor xmm4, xmm6 + movdqu [r9 + 128], xmm4 + movdqu xmm6, [r8 + 192] + pxor xmm3, xmm6 + movdqu [r9 + 192], xmm3 + movdqu xmm0, [rsp + 128] + movdqu xmm1, [rsp + 144] + movdqu xmm2, [rsp + 160] + movdqu xmm3, [rsp + 176] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm6, [r8 + 16] + pxor xmm0, xmm6 + movdqu [r9 + 16], xmm0 + movdqu xmm6, [r8 + 80] + pxor xmm1, xmm6 + movdqu [r9 + 80], xmm1 + movdqu xmm6, [r8 + 144] + pxor xmm4, xmm6 + movdqu [r9 + 144], xmm4 + movdqu xmm6, [r8 + 208] + pxor xmm3, xmm6 + movdqu [r9 + 208], xmm3 + movdqu xmm0, [rsp + 192] + movdqu xmm1, [rsp + 208] + movdqu xmm2, [rsp + 224] + movdqu xmm3, [rsp + 240] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm6, [r8 + 32] + pxor xmm0, xmm6 + movdqu [r9 + 32], xmm0 + movdqu xmm6, [r8 + 96] + pxor xmm1, xmm6 + movdqu [r9 + 96], xmm1 + movdqu xmm6, [r8 + 160] + pxor xmm4, xmm6 + movdqu [r9 + 160], xmm4 + movdqu xmm6, [r8 + 224] + pxor xmm3, xmm6 + movdqu [r9 + 224], xmm3 + movdqu xmm0, [rsp + 256] + movdqu xmm1, [rsp + 272] + movdqu xmm2, [rsp + 288] + movdqu xmm3, [rsp + 304] + movdqa xmm4, xmm0 + db $66, $0F, $62, $C1 // punpckldq xmm0, xmm1 + db $66, $0F, $6A, $E1 // punpckhdq xmm4, xmm1 + movdqa xmm5, xmm2 + db $66, $0F, $62, $D3 // punpckldq xmm2, xmm3 + db $66, $0F, $6A, $EB // punpckhdq xmm5, xmm3 + movdqa xmm1, xmm0 + db $66, $0F, $6C, $C2 // punpcklqdq xmm0, xmm2 + db $66, $0F, $6D, $CA // punpckhqdq xmm1, xmm2 + movdqa xmm3, xmm4 + db $66, $0F, $6C, $E5 // punpcklqdq xmm4, xmm5 + db $66, $0F, $6D, $DD // punpckhqdq xmm3, xmm5 + movdqu xmm6, [r8 + 48] + pxor xmm0, xmm6 + movdqu [r9 + 48], xmm0 + movdqu xmm6, [r8 + 112] + pxor xmm1, xmm6 + movdqu [r9 + 112], xmm1 + movdqu xmm6, [r8 + 176] + pxor xmm4, xmm6 + movdqu [r9 + 176], xmm4 + movdqu xmm6, [r8 + 240] + pxor xmm3, xmm6 + movdqu [r9 + 240], xmm3 + add rsp, 368 +{$I ..\..\Include\Simd\Common\ClpSimdNonVolatileRestore_x86_64.inc} + diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks8Avx2_x86_64.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks8Avx2_x86_64.inc new file mode 100644 index 00000000..bd2c7065 --- /dev/null +++ b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks8Avx2_x86_64.inc @@ -0,0 +1,448 @@ +// ChaCha7539 (IETF) 8-way (512B) AVX2 keystream kernel, vertical layout (x86-64). +// ------------------------------------------------------------------- +// +// Eight 64-byte ChaCha20 blocks, state words held vertically (one block per +// ymm lane). ymm0-3 = words a (0-3), ymm4-7 = words b (4-7), ymm12-15 = words +// d (12-15); words c (8-11) live in a stack slot; ymm8-11 are scratch. The four +// quarter-rounds of each round are step-interleaved; rot16/rot8 use vpshufb with +// the mask read from memory; rot12/rot7 use vpslld/vpsrld/vpor. +// +// On entry (after ClpSimdProc4Begin_x86_64.inc): +// rcx = ARounds, rdx = AState (16 UInt32), r8 = AIn, r9 = AOut. +// +// On exit: +// AState word-12 counter (byte 48) advanced by 8; the keystream is xored +// with AIn into AOut (512 bytes). +// +// VEX-encoded instructions are db-encoded for broad assembler compatibility. + mov r10, rcx +{$I ..\..\Include\Simd\Common\ClpSimdNonVolatileSave_x86_64.inc} + sub rsp, 1248 + mov dword ptr [rsp + 640], 0 + mov dword ptr [rsp + 644], 1 + mov dword ptr [rsp + 648], 2 + mov dword ptr [rsp + 652], 3 + mov dword ptr [rsp + 656], 4 + mov dword ptr [rsp + 660], 5 + mov dword ptr [rsp + 664], 6 + mov dword ptr [rsp + 668], 7 + mov dword ptr [rsp + 672], $01000302 + mov dword ptr [rsp + 676], $05040706 + mov dword ptr [rsp + 680], $09080B0A + mov dword ptr [rsp + 684], $0D0C0F0E + mov dword ptr [rsp + 688], $01000302 + mov dword ptr [rsp + 692], $05040706 + mov dword ptr [rsp + 696], $09080B0A + mov dword ptr [rsp + 700], $0D0C0F0E + mov dword ptr [rsp + 704], $02010003 + mov dword ptr [rsp + 708], $06050407 + mov dword ptr [rsp + 712], $0A09080B + mov dword ptr [rsp + 716], $0E0D0C0F + mov dword ptr [rsp + 720], $02010003 + mov dword ptr [rsp + 724], $06050407 + mov dword ptr [rsp + 728], $0A09080B + mov dword ptr [rsp + 732], $0E0D0C0F + db $C4, $E2, $7D, $58, $02 // vpbroadcastd ymm0, [rdx] + db $C5, $FE, $7F, $84, $24, $80, $00, $00, $00 // vmovdqu [rsp + 128], ymm0 + db $C4, $E2, $7D, $58, $4A, $04 // vpbroadcastd ymm1, [rdx + 4] + db $C5, $FE, $7F, $8C, $24, $A0, $00, $00, $00 // vmovdqu [rsp + 160], ymm1 + db $C4, $E2, $7D, $58, $52, $08 // vpbroadcastd ymm2, [rdx + 8] + db $C5, $FE, $7F, $94, $24, $C0, $00, $00, $00 // vmovdqu [rsp + 192], ymm2 + db $C4, $E2, $7D, $58, $5A, $0C // vpbroadcastd ymm3, [rdx + 12] + db $C5, $FE, $7F, $9C, $24, $E0, $00, $00, $00 // vmovdqu [rsp + 224], ymm3 + db $C4, $E2, $7D, $58, $62, $10 // vpbroadcastd ymm4, [rdx + 16] + db $C5, $FE, $7F, $A4, $24, $00, $01, $00, $00 // vmovdqu [rsp + 256], ymm4 + db $C4, $E2, $7D, $58, $6A, $14 // vpbroadcastd ymm5, [rdx + 20] + db $C5, $FE, $7F, $AC, $24, $20, $01, $00, $00 // vmovdqu [rsp + 288], ymm5 + db $C4, $E2, $7D, $58, $72, $18 // vpbroadcastd ymm6, [rdx + 24] + db $C5, $FE, $7F, $B4, $24, $40, $01, $00, $00 // vmovdqu [rsp + 320], ymm6 + db $C4, $E2, $7D, $58, $7A, $1C // vpbroadcastd ymm7, [rdx + 28] + db $C5, $FE, $7F, $BC, $24, $60, $01, $00, $00 // vmovdqu [rsp + 352], ymm7 + db $C4, $62, $7D, $58, $42, $20 // vpbroadcastd ymm8, [rdx + 32] + db $C5, $7E, $7F, $84, $24, $80, $01, $00, $00 // vmovdqu [rsp + 384], ymm8 + db $C5, $7E, $7F, $04, $24 // vmovdqu [rsp], ymm8 + db $C4, $62, $7D, $58, $42, $24 // vpbroadcastd ymm8, [rdx + 36] + db $C5, $7E, $7F, $84, $24, $A0, $01, $00, $00 // vmovdqu [rsp + 416], ymm8 + db $C5, $7E, $7F, $44, $24, $20 // vmovdqu [rsp + 32], ymm8 + db $C4, $62, $7D, $58, $42, $28 // vpbroadcastd ymm8, [rdx + 40] + db $C5, $7E, $7F, $84, $24, $C0, $01, $00, $00 // vmovdqu [rsp + 448], ymm8 + db $C5, $7E, $7F, $44, $24, $40 // vmovdqu [rsp + 64], ymm8 + db $C4, $62, $7D, $58, $42, $2C // vpbroadcastd ymm8, [rdx + 44] + db $C5, $7E, $7F, $84, $24, $E0, $01, $00, $00 // vmovdqu [rsp + 480], ymm8 + db $C5, $7E, $7F, $44, $24, $60 // vmovdqu [rsp + 96], ymm8 + db $C4, $62, $7D, $58, $62, $30 // vpbroadcastd ymm12, [rdx + 48] + db $C5, $1D, $FE, $A4, $24, $80, $02, $00, $00 // vpaddd ymm12, ymm12, [rsp + 640] + db $C5, $7E, $7F, $A4, $24, $00, $02, $00, $00 // vmovdqu [rsp + 512], ymm12 + db $C4, $62, $7D, $58, $6A, $34 // vpbroadcastd ymm13, [rdx + 52] + db $C5, $7E, $7F, $AC, $24, $20, $02, $00, $00 // vmovdqu [rsp + 544], ymm13 + db $C4, $62, $7D, $58, $72, $38 // vpbroadcastd ymm14, [rdx + 56] + db $C5, $7E, $7F, $B4, $24, $40, $02, $00, $00 // vmovdqu [rsp + 576], ymm14 + db $C4, $62, $7D, $58, $7A, $3C // vpbroadcastd ymm15, [rdx + 60] + db $C5, $7E, $7F, $BC, $24, $60, $02, $00, $00 // vmovdqu [rsp + 608], ymm15 +@@c7539_avx2_8x_round: + db $C5, $FD, $FE, $C4 // vpaddd ymm0, ymm0, ymm4 + db $C5, $F5, $FE, $CD // vpaddd ymm1, ymm1, ymm5 + db $C5, $ED, $FE, $D6 // vpaddd ymm2, ymm2, ymm6 + db $C5, $E5, $FE, $DF // vpaddd ymm3, ymm3, ymm7 + db $C5, $1D, $EF, $E0 // vpxor ymm12, ymm12, ymm0 + db $C5, $15, $EF, $E9 // vpxor ymm13, ymm13, ymm1 + db $C5, $0D, $EF, $F2 // vpxor ymm14, ymm14, ymm2 + db $C5, $05, $EF, $FB // vpxor ymm15, ymm15, ymm3 + db $C4, $62, $1D, $00, $A4, $24, $A0, $02, $00, $00 // vpshufb ymm12, ymm12, [rsp + 672] + db $C4, $62, $15, $00, $AC, $24, $A0, $02, $00, $00 // vpshufb ymm13, ymm13, [rsp + 672] + db $C4, $62, $0D, $00, $B4, $24, $A0, $02, $00, $00 // vpshufb ymm14, ymm14, [rsp + 672] + db $C4, $62, $05, $00, $BC, $24, $A0, $02, $00, $00 // vpshufb ymm15, ymm15, [rsp + 672] + db $C5, $7E, $6F, $04, $24 // vmovdqu ymm8, [rsp] + db $C5, $7E, $6F, $4C, $24, $20 // vmovdqu ymm9, [rsp + 32] + db $C5, $7E, $6F, $54, $24, $40 // vmovdqu ymm10, [rsp + 64] + db $C5, $7E, $6F, $5C, $24, $60 // vmovdqu ymm11, [rsp + 96] + db $C4, $41, $3D, $FE, $C4 // vpaddd ymm8, ymm8, ymm12 + db $C4, $41, $35, $FE, $CD // vpaddd ymm9, ymm9, ymm13 + db $C4, $41, $2D, $FE, $D6 // vpaddd ymm10, ymm10, ymm14 + db $C4, $41, $25, $FE, $DF // vpaddd ymm11, ymm11, ymm15 + db $C4, $C1, $5D, $EF, $E0 // vpxor ymm4, ymm4, ymm8 + db $C4, $C1, $55, $EF, $E9 // vpxor ymm5, ymm5, ymm9 + db $C4, $C1, $4D, $EF, $F2 // vpxor ymm6, ymm6, ymm10 + db $C4, $C1, $45, $EF, $FB // vpxor ymm7, ymm7, ymm11 + db $C5, $7E, $7F, $04, $24 // vmovdqu [rsp], ymm8 + db $C5, $7E, $7F, $4C, $24, $20 // vmovdqu [rsp + 32], ymm9 + db $C5, $7E, $7F, $54, $24, $40 // vmovdqu [rsp + 64], ymm10 + db $C5, $7E, $7F, $5C, $24, $60 // vmovdqu [rsp + 96], ymm11 + db $C5, $BD, $72, $F4, $0C // vpslld ymm8, ymm4, 12 + db $C5, $B5, $72, $F5, $0C // vpslld ymm9, ymm5, 12 + db $C5, $AD, $72, $F6, $0C // vpslld ymm10, ymm6, 12 + db $C5, $A5, $72, $F7, $0C // vpslld ymm11, ymm7, 12 + db $C5, $DD, $72, $D4, $14 // vpsrld ymm4, ymm4, 20 + db $C5, $D5, $72, $D5, $14 // vpsrld ymm5, ymm5, 20 + db $C5, $CD, $72, $D6, $14 // vpsrld ymm6, ymm6, 20 + db $C5, $C5, $72, $D7, $14 // vpsrld ymm7, ymm7, 20 + db $C5, $BD, $EB, $E4 // vpor ymm4, ymm8, ymm4 + db $C5, $B5, $EB, $ED // vpor ymm5, ymm9, ymm5 + db $C5, $AD, $EB, $F6 // vpor ymm6, ymm10, ymm6 + db $C5, $A5, $EB, $FF // vpor ymm7, ymm11, ymm7 + db $C5, $FD, $FE, $C4 // vpaddd ymm0, ymm0, ymm4 + db $C5, $F5, $FE, $CD // vpaddd ymm1, ymm1, ymm5 + db $C5, $ED, $FE, $D6 // vpaddd ymm2, ymm2, ymm6 + db $C5, $E5, $FE, $DF // vpaddd ymm3, ymm3, ymm7 + db $C5, $1D, $EF, $E0 // vpxor ymm12, ymm12, ymm0 + db $C5, $15, $EF, $E9 // vpxor ymm13, ymm13, ymm1 + db $C5, $0D, $EF, $F2 // vpxor ymm14, ymm14, ymm2 + db $C5, $05, $EF, $FB // vpxor ymm15, ymm15, ymm3 + db $C4, $62, $1D, $00, $A4, $24, $C0, $02, $00, $00 // vpshufb ymm12, ymm12, [rsp + 704] + db $C4, $62, $15, $00, $AC, $24, $C0, $02, $00, $00 // vpshufb ymm13, ymm13, [rsp + 704] + db $C4, $62, $0D, $00, $B4, $24, $C0, $02, $00, $00 // vpshufb ymm14, ymm14, [rsp + 704] + db $C4, $62, $05, $00, $BC, $24, $C0, $02, $00, $00 // vpshufb ymm15, ymm15, [rsp + 704] + db $C5, $7E, $6F, $04, $24 // vmovdqu ymm8, [rsp] + db $C5, $7E, $6F, $4C, $24, $20 // vmovdqu ymm9, [rsp + 32] + db $C5, $7E, $6F, $54, $24, $40 // vmovdqu ymm10, [rsp + 64] + db $C5, $7E, $6F, $5C, $24, $60 // vmovdqu ymm11, [rsp + 96] + db $C4, $41, $3D, $FE, $C4 // vpaddd ymm8, ymm8, ymm12 + db $C4, $41, $35, $FE, $CD // vpaddd ymm9, ymm9, ymm13 + db $C4, $41, $2D, $FE, $D6 // vpaddd ymm10, ymm10, ymm14 + db $C4, $41, $25, $FE, $DF // vpaddd ymm11, ymm11, ymm15 + db $C4, $C1, $5D, $EF, $E0 // vpxor ymm4, ymm4, ymm8 + db $C4, $C1, $55, $EF, $E9 // vpxor ymm5, ymm5, ymm9 + db $C4, $C1, $4D, $EF, $F2 // vpxor ymm6, ymm6, ymm10 + db $C4, $C1, $45, $EF, $FB // vpxor ymm7, ymm7, ymm11 + db $C5, $7E, $7F, $04, $24 // vmovdqu [rsp], ymm8 + db $C5, $7E, $7F, $4C, $24, $20 // vmovdqu [rsp + 32], ymm9 + db $C5, $7E, $7F, $54, $24, $40 // vmovdqu [rsp + 64], ymm10 + db $C5, $7E, $7F, $5C, $24, $60 // vmovdqu [rsp + 96], ymm11 + db $C5, $BD, $72, $F4, $07 // vpslld ymm8, ymm4, 7 + db $C5, $B5, $72, $F5, $07 // vpslld ymm9, ymm5, 7 + db $C5, $AD, $72, $F6, $07 // vpslld ymm10, ymm6, 7 + db $C5, $A5, $72, $F7, $07 // vpslld ymm11, ymm7, 7 + db $C5, $DD, $72, $D4, $19 // vpsrld ymm4, ymm4, 25 + db $C5, $D5, $72, $D5, $19 // vpsrld ymm5, ymm5, 25 + db $C5, $CD, $72, $D6, $19 // vpsrld ymm6, ymm6, 25 + db $C5, $C5, $72, $D7, $19 // vpsrld ymm7, ymm7, 25 + db $C5, $BD, $EB, $E4 // vpor ymm4, ymm8, ymm4 + db $C5, $B5, $EB, $ED // vpor ymm5, ymm9, ymm5 + db $C5, $AD, $EB, $F6 // vpor ymm6, ymm10, ymm6 + db $C5, $A5, $EB, $FF // vpor ymm7, ymm11, ymm7 + db $C5, $FD, $FE, $C5 // vpaddd ymm0, ymm0, ymm5 + db $C5, $F5, $FE, $CE // vpaddd ymm1, ymm1, ymm6 + db $C5, $ED, $FE, $D7 // vpaddd ymm2, ymm2, ymm7 + db $C5, $E5, $FE, $DC // vpaddd ymm3, ymm3, ymm4 + db $C5, $05, $EF, $F8 // vpxor ymm15, ymm15, ymm0 + db $C5, $1D, $EF, $E1 // vpxor ymm12, ymm12, ymm1 + db $C5, $15, $EF, $EA // vpxor ymm13, ymm13, ymm2 + db $C5, $0D, $EF, $F3 // vpxor ymm14, ymm14, ymm3 + db $C4, $62, $05, $00, $BC, $24, $A0, $02, $00, $00 // vpshufb ymm15, ymm15, [rsp + 672] + db $C4, $62, $1D, $00, $A4, $24, $A0, $02, $00, $00 // vpshufb ymm12, ymm12, [rsp + 672] + db $C4, $62, $15, $00, $AC, $24, $A0, $02, $00, $00 // vpshufb ymm13, ymm13, [rsp + 672] + db $C4, $62, $0D, $00, $B4, $24, $A0, $02, $00, $00 // vpshufb ymm14, ymm14, [rsp + 672] + db $C5, $7E, $6F, $44, $24, $40 // vmovdqu ymm8, [rsp + 64] + db $C5, $7E, $6F, $4C, $24, $60 // vmovdqu ymm9, [rsp + 96] + db $C5, $7E, $6F, $14, $24 // vmovdqu ymm10, [rsp] + db $C5, $7E, $6F, $5C, $24, $20 // vmovdqu ymm11, [rsp + 32] + db $C4, $41, $3D, $FE, $C7 // vpaddd ymm8, ymm8, ymm15 + db $C4, $41, $35, $FE, $CC // vpaddd ymm9, ymm9, ymm12 + db $C4, $41, $2D, $FE, $D5 // vpaddd ymm10, ymm10, ymm13 + db $C4, $41, $25, $FE, $DE // vpaddd ymm11, ymm11, ymm14 + db $C4, $C1, $55, $EF, $E8 // vpxor ymm5, ymm5, ymm8 + db $C4, $C1, $4D, $EF, $F1 // vpxor ymm6, ymm6, ymm9 + db $C4, $C1, $45, $EF, $FA // vpxor ymm7, ymm7, ymm10 + db $C4, $C1, $5D, $EF, $E3 // vpxor ymm4, ymm4, ymm11 + db $C5, $7E, $7F, $44, $24, $40 // vmovdqu [rsp + 64], ymm8 + db $C5, $7E, $7F, $4C, $24, $60 // vmovdqu [rsp + 96], ymm9 + db $C5, $7E, $7F, $14, $24 // vmovdqu [rsp], ymm10 + db $C5, $7E, $7F, $5C, $24, $20 // vmovdqu [rsp + 32], ymm11 + db $C5, $BD, $72, $F5, $0C // vpslld ymm8, ymm5, 12 + db $C5, $B5, $72, $F6, $0C // vpslld ymm9, ymm6, 12 + db $C5, $AD, $72, $F7, $0C // vpslld ymm10, ymm7, 12 + db $C5, $A5, $72, $F4, $0C // vpslld ymm11, ymm4, 12 + db $C5, $D5, $72, $D5, $14 // vpsrld ymm5, ymm5, 20 + db $C5, $CD, $72, $D6, $14 // vpsrld ymm6, ymm6, 20 + db $C5, $C5, $72, $D7, $14 // vpsrld ymm7, ymm7, 20 + db $C5, $DD, $72, $D4, $14 // vpsrld ymm4, ymm4, 20 + db $C5, $BD, $EB, $ED // vpor ymm5, ymm8, ymm5 + db $C5, $B5, $EB, $F6 // vpor ymm6, ymm9, ymm6 + db $C5, $AD, $EB, $FF // vpor ymm7, ymm10, ymm7 + db $C5, $A5, $EB, $E4 // vpor ymm4, ymm11, ymm4 + db $C5, $FD, $FE, $C5 // vpaddd ymm0, ymm0, ymm5 + db $C5, $F5, $FE, $CE // vpaddd ymm1, ymm1, ymm6 + db $C5, $ED, $FE, $D7 // vpaddd ymm2, ymm2, ymm7 + db $C5, $E5, $FE, $DC // vpaddd ymm3, ymm3, ymm4 + db $C5, $05, $EF, $F8 // vpxor ymm15, ymm15, ymm0 + db $C5, $1D, $EF, $E1 // vpxor ymm12, ymm12, ymm1 + db $C5, $15, $EF, $EA // vpxor ymm13, ymm13, ymm2 + db $C5, $0D, $EF, $F3 // vpxor ymm14, ymm14, ymm3 + db $C4, $62, $05, $00, $BC, $24, $C0, $02, $00, $00 // vpshufb ymm15, ymm15, [rsp + 704] + db $C4, $62, $1D, $00, $A4, $24, $C0, $02, $00, $00 // vpshufb ymm12, ymm12, [rsp + 704] + db $C4, $62, $15, $00, $AC, $24, $C0, $02, $00, $00 // vpshufb ymm13, ymm13, [rsp + 704] + db $C4, $62, $0D, $00, $B4, $24, $C0, $02, $00, $00 // vpshufb ymm14, ymm14, [rsp + 704] + db $C5, $7E, $6F, $44, $24, $40 // vmovdqu ymm8, [rsp + 64] + db $C5, $7E, $6F, $4C, $24, $60 // vmovdqu ymm9, [rsp + 96] + db $C5, $7E, $6F, $14, $24 // vmovdqu ymm10, [rsp] + db $C5, $7E, $6F, $5C, $24, $20 // vmovdqu ymm11, [rsp + 32] + db $C4, $41, $3D, $FE, $C7 // vpaddd ymm8, ymm8, ymm15 + db $C4, $41, $35, $FE, $CC // vpaddd ymm9, ymm9, ymm12 + db $C4, $41, $2D, $FE, $D5 // vpaddd ymm10, ymm10, ymm13 + db $C4, $41, $25, $FE, $DE // vpaddd ymm11, ymm11, ymm14 + db $C4, $C1, $55, $EF, $E8 // vpxor ymm5, ymm5, ymm8 + db $C4, $C1, $4D, $EF, $F1 // vpxor ymm6, ymm6, ymm9 + db $C4, $C1, $45, $EF, $FA // vpxor ymm7, ymm7, ymm10 + db $C4, $C1, $5D, $EF, $E3 // vpxor ymm4, ymm4, ymm11 + db $C5, $7E, $7F, $44, $24, $40 // vmovdqu [rsp + 64], ymm8 + db $C5, $7E, $7F, $4C, $24, $60 // vmovdqu [rsp + 96], ymm9 + db $C5, $7E, $7F, $14, $24 // vmovdqu [rsp], ymm10 + db $C5, $7E, $7F, $5C, $24, $20 // vmovdqu [rsp + 32], ymm11 + db $C5, $BD, $72, $F5, $07 // vpslld ymm8, ymm5, 7 + db $C5, $B5, $72, $F6, $07 // vpslld ymm9, ymm6, 7 + db $C5, $AD, $72, $F7, $07 // vpslld ymm10, ymm7, 7 + db $C5, $A5, $72, $F4, $07 // vpslld ymm11, ymm4, 7 + db $C5, $D5, $72, $D5, $19 // vpsrld ymm5, ymm5, 25 + db $C5, $CD, $72, $D6, $19 // vpsrld ymm6, ymm6, 25 + db $C5, $C5, $72, $D7, $19 // vpsrld ymm7, ymm7, 25 + db $C5, $DD, $72, $D4, $19 // vpsrld ymm4, ymm4, 25 + db $C5, $BD, $EB, $ED // vpor ymm5, ymm8, ymm5 + db $C5, $B5, $EB, $F6 // vpor ymm6, ymm9, ymm6 + db $C5, $AD, $EB, $FF // vpor ymm7, ymm10, ymm7 + db $C5, $A5, $EB, $E4 // vpor ymm4, ymm11, ymm4 + sub r10, 2 + jg @@c7539_avx2_8x_round + db $C5, $7E, $6F, $84, $24, $80, $00, $00, $00 // vmovdqu ymm8, [rsp + 128] + db $C4, $C1, $7D, $FE, $C0 // vpaddd ymm0, ymm0, ymm8 + db $C5, $FE, $7F, $84, $24, $80, $00, $00, $00 // vmovdqu [rsp + 128], ymm0 + db $C5, $7E, $6F, $84, $24, $A0, $00, $00, $00 // vmovdqu ymm8, [rsp + 160] + db $C4, $C1, $75, $FE, $C8 // vpaddd ymm1, ymm1, ymm8 + db $C5, $FE, $7F, $8C, $24, $A0, $00, $00, $00 // vmovdqu [rsp + 160], ymm1 + db $C5, $7E, $6F, $84, $24, $C0, $00, $00, $00 // vmovdqu ymm8, [rsp + 192] + db $C4, $C1, $6D, $FE, $D0 // vpaddd ymm2, ymm2, ymm8 + db $C5, $FE, $7F, $94, $24, $C0, $00, $00, $00 // vmovdqu [rsp + 192], ymm2 + db $C5, $7E, $6F, $84, $24, $E0, $00, $00, $00 // vmovdqu ymm8, [rsp + 224] + db $C4, $C1, $65, $FE, $D8 // vpaddd ymm3, ymm3, ymm8 + db $C5, $FE, $7F, $9C, $24, $E0, $00, $00, $00 // vmovdqu [rsp + 224], ymm3 + db $C5, $7E, $6F, $84, $24, $00, $01, $00, $00 // vmovdqu ymm8, [rsp + 256] + db $C4, $C1, $5D, $FE, $E0 // vpaddd ymm4, ymm4, ymm8 + db $C5, $FE, $7F, $A4, $24, $00, $01, $00, $00 // vmovdqu [rsp + 256], ymm4 + db $C5, $7E, $6F, $84, $24, $20, $01, $00, $00 // vmovdqu ymm8, [rsp + 288] + db $C4, $C1, $55, $FE, $E8 // vpaddd ymm5, ymm5, ymm8 + db $C5, $FE, $7F, $AC, $24, $20, $01, $00, $00 // vmovdqu [rsp + 288], ymm5 + db $C5, $7E, $6F, $84, $24, $40, $01, $00, $00 // vmovdqu ymm8, [rsp + 320] + db $C4, $C1, $4D, $FE, $F0 // vpaddd ymm6, ymm6, ymm8 + db $C5, $FE, $7F, $B4, $24, $40, $01, $00, $00 // vmovdqu [rsp + 320], ymm6 + db $C5, $7E, $6F, $84, $24, $60, $01, $00, $00 // vmovdqu ymm8, [rsp + 352] + db $C4, $C1, $45, $FE, $F8 // vpaddd ymm7, ymm7, ymm8 + db $C5, $FE, $7F, $BC, $24, $60, $01, $00, $00 // vmovdqu [rsp + 352], ymm7 + db $C5, $7E, $6F, $84, $24, $00, $02, $00, $00 // vmovdqu ymm8, [rsp + 512] + db $C4, $41, $1D, $FE, $E0 // vpaddd ymm12, ymm12, ymm8 + db $C5, $7E, $7F, $A4, $24, $00, $02, $00, $00 // vmovdqu [rsp + 512], ymm12 + db $C5, $7E, $6F, $84, $24, $20, $02, $00, $00 // vmovdqu ymm8, [rsp + 544] + db $C4, $41, $15, $FE, $E8 // vpaddd ymm13, ymm13, ymm8 + db $C5, $7E, $7F, $AC, $24, $20, $02, $00, $00 // vmovdqu [rsp + 544], ymm13 + db $C5, $7E, $6F, $84, $24, $40, $02, $00, $00 // vmovdqu ymm8, [rsp + 576] + db $C4, $41, $0D, $FE, $F0 // vpaddd ymm14, ymm14, ymm8 + db $C5, $7E, $7F, $B4, $24, $40, $02, $00, $00 // vmovdqu [rsp + 576], ymm14 + db $C5, $7E, $6F, $84, $24, $60, $02, $00, $00 // vmovdqu ymm8, [rsp + 608] + db $C4, $41, $05, $FE, $F8 // vpaddd ymm15, ymm15, ymm8 + db $C5, $7E, $7F, $BC, $24, $60, $02, $00, $00 // vmovdqu [rsp + 608], ymm15 + db $C5, $7E, $6F, $04, $24 // vmovdqu ymm8, [rsp] + db $C5, $7E, $6F, $8C, $24, $80, $01, $00, $00 // vmovdqu ymm9, [rsp + 384] + db $C4, $41, $3D, $FE, $C1 // vpaddd ymm8, ymm8, ymm9 + db $C5, $7E, $7F, $84, $24, $80, $01, $00, $00 // vmovdqu [rsp + 384], ymm8 + db $C5, $7E, $6F, $44, $24, $20 // vmovdqu ymm8, [rsp + 32] + db $C5, $7E, $6F, $8C, $24, $A0, $01, $00, $00 // vmovdqu ymm9, [rsp + 416] + db $C4, $41, $3D, $FE, $C1 // vpaddd ymm8, ymm8, ymm9 + db $C5, $7E, $7F, $84, $24, $A0, $01, $00, $00 // vmovdqu [rsp + 416], ymm8 + db $C5, $7E, $6F, $44, $24, $40 // vmovdqu ymm8, [rsp + 64] + db $C5, $7E, $6F, $8C, $24, $C0, $01, $00, $00 // vmovdqu ymm9, [rsp + 448] + db $C4, $41, $3D, $FE, $C1 // vpaddd ymm8, ymm8, ymm9 + db $C5, $7E, $7F, $84, $24, $C0, $01, $00, $00 // vmovdqu [rsp + 448], ymm8 + db $C5, $7E, $6F, $44, $24, $60 // vmovdqu ymm8, [rsp + 96] + db $C5, $7E, $6F, $8C, $24, $E0, $01, $00, $00 // vmovdqu ymm9, [rsp + 480] + db $C4, $41, $3D, $FE, $C1 // vpaddd ymm8, ymm8, ymm9 + db $C5, $7E, $7F, $84, $24, $E0, $01, $00, $00 // vmovdqu [rsp + 480], ymm8 + add dword ptr [rdx + 48], 8 +{$IFDEF CHACHA_CTR64} + adc dword ptr [rdx + 52], 0 +{$ENDIF} + db $C5, $FE, $6F, $84, $24, $80, $00, $00, $00 // vmovdqu ymm0, [rsp + 128] + db $C5, $FE, $6F, $8C, $24, $A0, $00, $00, $00 // vmovdqu ymm1, [rsp + 160] + db $C5, $FE, $6F, $94, $24, $C0, $00, $00, $00 // vmovdqu ymm2, [rsp + 192] + db $C5, $FE, $6F, $9C, $24, $E0, $00, $00, $00 // vmovdqu ymm3, [rsp + 224] + db $C5, $FD, $6F, $E0 // vmovdqa ymm4, ymm0 + db $C5, $FD, $62, $C1 // vpunpckldq ymm0, ymm0, ymm1 + db $C5, $DD, $6A, $E1 // vpunpckhdq ymm4, ymm4, ymm1 + db $C5, $FD, $6F, $EA // vmovdqa ymm5, ymm2 + db $C5, $ED, $62, $D3 // vpunpckldq ymm2, ymm2, ymm3 + db $C5, $D5, $6A, $EB // vpunpckhdq ymm5, ymm5, ymm3 + db $C5, $FD, $6F, $C8 // vmovdqa ymm1, ymm0 + db $C5, $FD, $6C, $C2 // vpunpcklqdq ymm0, ymm0, ymm2 + db $C5, $F5, $6D, $CA // vpunpckhqdq ymm1, ymm1, ymm2 + db $C5, $FD, $6F, $DC // vmovdqa ymm3, ymm4 + db $C5, $DD, $6C, $E5 // vpunpcklqdq ymm4, ymm4, ymm5 + db $C5, $E5, $6D, $DD // vpunpckhqdq ymm3, ymm3, ymm5 + db $C5, $FA, $7F, $84, $24, $E0, $02, $00, $00 // vmovdqu [rsp + 736], xmm0 + db $C4, $E3, $7D, $39, $84, $24, $E0, $03, $00, $00, $01 // vextracti128 [rsp + 992], ymm0, 1 + db $C5, $FA, $7F, $8C, $24, $20, $03, $00, $00 // vmovdqu [rsp + 800], xmm1 + db $C4, $E3, $7D, $39, $8C, $24, $20, $04, $00, $00, $01 // vextracti128 [rsp + 1056], ymm1, 1 + db $C5, $FA, $7F, $A4, $24, $60, $03, $00, $00 // vmovdqu [rsp + 864], xmm4 + db $C4, $E3, $7D, $39, $A4, $24, $60, $04, $00, $00, $01 // vextracti128 [rsp + 1120], ymm4, 1 + db $C5, $FA, $7F, $9C, $24, $A0, $03, $00, $00 // vmovdqu [rsp + 928], xmm3 + db $C4, $E3, $7D, $39, $9C, $24, $A0, $04, $00, $00, $01 // vextracti128 [rsp + 1184], ymm3, 1 + db $C5, $FE, $6F, $84, $24, $00, $01, $00, $00 // vmovdqu ymm0, [rsp + 256] + db $C5, $FE, $6F, $8C, $24, $20, $01, $00, $00 // vmovdqu ymm1, [rsp + 288] + db $C5, $FE, $6F, $94, $24, $40, $01, $00, $00 // vmovdqu ymm2, [rsp + 320] + db $C5, $FE, $6F, $9C, $24, $60, $01, $00, $00 // vmovdqu ymm3, [rsp + 352] + db $C5, $FD, $6F, $E0 // vmovdqa ymm4, ymm0 + db $C5, $FD, $62, $C1 // vpunpckldq ymm0, ymm0, ymm1 + db $C5, $DD, $6A, $E1 // vpunpckhdq ymm4, ymm4, ymm1 + db $C5, $FD, $6F, $EA // vmovdqa ymm5, ymm2 + db $C5, $ED, $62, $D3 // vpunpckldq ymm2, ymm2, ymm3 + db $C5, $D5, $6A, $EB // vpunpckhdq ymm5, ymm5, ymm3 + db $C5, $FD, $6F, $C8 // vmovdqa ymm1, ymm0 + db $C5, $FD, $6C, $C2 // vpunpcklqdq ymm0, ymm0, ymm2 + db $C5, $F5, $6D, $CA // vpunpckhqdq ymm1, ymm1, ymm2 + db $C5, $FD, $6F, $DC // vmovdqa ymm3, ymm4 + db $C5, $DD, $6C, $E5 // vpunpcklqdq ymm4, ymm4, ymm5 + db $C5, $E5, $6D, $DD // vpunpckhqdq ymm3, ymm3, ymm5 + db $C5, $FA, $7F, $84, $24, $F0, $02, $00, $00 // vmovdqu [rsp + 752], xmm0 + db $C4, $E3, $7D, $39, $84, $24, $F0, $03, $00, $00, $01 // vextracti128 [rsp + 1008], ymm0, 1 + db $C5, $FA, $7F, $8C, $24, $30, $03, $00, $00 // vmovdqu [rsp + 816], xmm1 + db $C4, $E3, $7D, $39, $8C, $24, $30, $04, $00, $00, $01 // vextracti128 [rsp + 1072], ymm1, 1 + db $C5, $FA, $7F, $A4, $24, $70, $03, $00, $00 // vmovdqu [rsp + 880], xmm4 + db $C4, $E3, $7D, $39, $A4, $24, $70, $04, $00, $00, $01 // vextracti128 [rsp + 1136], ymm4, 1 + db $C5, $FA, $7F, $9C, $24, $B0, $03, $00, $00 // vmovdqu [rsp + 944], xmm3 + db $C4, $E3, $7D, $39, $9C, $24, $B0, $04, $00, $00, $01 // vextracti128 [rsp + 1200], ymm3, 1 + db $C5, $FE, $6F, $84, $24, $80, $01, $00, $00 // vmovdqu ymm0, [rsp + 384] + db $C5, $FE, $6F, $8C, $24, $A0, $01, $00, $00 // vmovdqu ymm1, [rsp + 416] + db $C5, $FE, $6F, $94, $24, $C0, $01, $00, $00 // vmovdqu ymm2, [rsp + 448] + db $C5, $FE, $6F, $9C, $24, $E0, $01, $00, $00 // vmovdqu ymm3, [rsp + 480] + db $C5, $FD, $6F, $E0 // vmovdqa ymm4, ymm0 + db $C5, $FD, $62, $C1 // vpunpckldq ymm0, ymm0, ymm1 + db $C5, $DD, $6A, $E1 // vpunpckhdq ymm4, ymm4, ymm1 + db $C5, $FD, $6F, $EA // vmovdqa ymm5, ymm2 + db $C5, $ED, $62, $D3 // vpunpckldq ymm2, ymm2, ymm3 + db $C5, $D5, $6A, $EB // vpunpckhdq ymm5, ymm5, ymm3 + db $C5, $FD, $6F, $C8 // vmovdqa ymm1, ymm0 + db $C5, $FD, $6C, $C2 // vpunpcklqdq ymm0, ymm0, ymm2 + db $C5, $F5, $6D, $CA // vpunpckhqdq ymm1, ymm1, ymm2 + db $C5, $FD, $6F, $DC // vmovdqa ymm3, ymm4 + db $C5, $DD, $6C, $E5 // vpunpcklqdq ymm4, ymm4, ymm5 + db $C5, $E5, $6D, $DD // vpunpckhqdq ymm3, ymm3, ymm5 + db $C5, $FA, $7F, $84, $24, $00, $03, $00, $00 // vmovdqu [rsp + 768], xmm0 + db $C4, $E3, $7D, $39, $84, $24, $00, $04, $00, $00, $01 // vextracti128 [rsp + 1024], ymm0, 1 + db $C5, $FA, $7F, $8C, $24, $40, $03, $00, $00 // vmovdqu [rsp + 832], xmm1 + db $C4, $E3, $7D, $39, $8C, $24, $40, $04, $00, $00, $01 // vextracti128 [rsp + 1088], ymm1, 1 + db $C5, $FA, $7F, $A4, $24, $80, $03, $00, $00 // vmovdqu [rsp + 896], xmm4 + db $C4, $E3, $7D, $39, $A4, $24, $80, $04, $00, $00, $01 // vextracti128 [rsp + 1152], ymm4, 1 + db $C5, $FA, $7F, $9C, $24, $C0, $03, $00, $00 // vmovdqu [rsp + 960], xmm3 + db $C4, $E3, $7D, $39, $9C, $24, $C0, $04, $00, $00, $01 // vextracti128 [rsp + 1216], ymm3, 1 + db $C5, $FE, $6F, $84, $24, $00, $02, $00, $00 // vmovdqu ymm0, [rsp + 512] + db $C5, $FE, $6F, $8C, $24, $20, $02, $00, $00 // vmovdqu ymm1, [rsp + 544] + db $C5, $FE, $6F, $94, $24, $40, $02, $00, $00 // vmovdqu ymm2, [rsp + 576] + db $C5, $FE, $6F, $9C, $24, $60, $02, $00, $00 // vmovdqu ymm3, [rsp + 608] + db $C5, $FD, $6F, $E0 // vmovdqa ymm4, ymm0 + db $C5, $FD, $62, $C1 // vpunpckldq ymm0, ymm0, ymm1 + db $C5, $DD, $6A, $E1 // vpunpckhdq ymm4, ymm4, ymm1 + db $C5, $FD, $6F, $EA // vmovdqa ymm5, ymm2 + db $C5, $ED, $62, $D3 // vpunpckldq ymm2, ymm2, ymm3 + db $C5, $D5, $6A, $EB // vpunpckhdq ymm5, ymm5, ymm3 + db $C5, $FD, $6F, $C8 // vmovdqa ymm1, ymm0 + db $C5, $FD, $6C, $C2 // vpunpcklqdq ymm0, ymm0, ymm2 + db $C5, $F5, $6D, $CA // vpunpckhqdq ymm1, ymm1, ymm2 + db $C5, $FD, $6F, $DC // vmovdqa ymm3, ymm4 + db $C5, $DD, $6C, $E5 // vpunpcklqdq ymm4, ymm4, ymm5 + db $C5, $E5, $6D, $DD // vpunpckhqdq ymm3, ymm3, ymm5 + db $C5, $FA, $7F, $84, $24, $10, $03, $00, $00 // vmovdqu [rsp + 784], xmm0 + db $C4, $E3, $7D, $39, $84, $24, $10, $04, $00, $00, $01 // vextracti128 [rsp + 1040], ymm0, 1 + db $C5, $FA, $7F, $8C, $24, $50, $03, $00, $00 // vmovdqu [rsp + 848], xmm1 + db $C4, $E3, $7D, $39, $8C, $24, $50, $04, $00, $00, $01 // vextracti128 [rsp + 1104], ymm1, 1 + db $C5, $FA, $7F, $A4, $24, $90, $03, $00, $00 // vmovdqu [rsp + 912], xmm4 + db $C4, $E3, $7D, $39, $A4, $24, $90, $04, $00, $00, $01 // vextracti128 [rsp + 1168], ymm4, 1 + db $C5, $FA, $7F, $9C, $24, $D0, $03, $00, $00 // vmovdqu [rsp + 976], xmm3 + db $C4, $E3, $7D, $39, $9C, $24, $D0, $04, $00, $00, $01 // vextracti128 [rsp + 1232], ymm3, 1 + db $C5, $FE, $6F, $84, $24, $E0, $02, $00, $00 // vmovdqu ymm0, [rsp + 736] + db $C4, $C1, $7D, $EF, $00 // vpxor ymm0, ymm0, [r8 + 0] + db $C4, $C1, $7E, $7F, $01 // vmovdqu [r9], ymm0 + db $C5, $FE, $6F, $84, $24, $00, $03, $00, $00 // vmovdqu ymm0, [rsp + 768] + db $C4, $C1, $7D, $EF, $40, $20 // vpxor ymm0, ymm0, [r8 + 32] + db $C4, $C1, $7E, $7F, $41, $20 // vmovdqu [r9 + 32], ymm0 + db $C5, $FE, $6F, $84, $24, $20, $03, $00, $00 // vmovdqu ymm0, [rsp + 800] + db $C4, $C1, $7D, $EF, $40, $40 // vpxor ymm0, ymm0, [r8 + 64] + db $C4, $C1, $7E, $7F, $41, $40 // vmovdqu [r9 + 64], ymm0 + db $C5, $FE, $6F, $84, $24, $40, $03, $00, $00 // vmovdqu ymm0, [rsp + 832] + db $C4, $C1, $7D, $EF, $40, $60 // vpxor ymm0, ymm0, [r8 + 96] + db $C4, $C1, $7E, $7F, $41, $60 // vmovdqu [r9 + 96], ymm0 + db $C5, $FE, $6F, $84, $24, $60, $03, $00, $00 // vmovdqu ymm0, [rsp + 864] + db $C4, $C1, $7D, $EF, $80, $80, $00, $00, $00 // vpxor ymm0, ymm0, [r8 + 128] + db $C4, $C1, $7E, $7F, $81, $80, $00, $00, $00 // vmovdqu [r9 + 128], ymm0 + db $C5, $FE, $6F, $84, $24, $80, $03, $00, $00 // vmovdqu ymm0, [rsp + 896] + db $C4, $C1, $7D, $EF, $80, $A0, $00, $00, $00 // vpxor ymm0, ymm0, [r8 + 160] + db $C4, $C1, $7E, $7F, $81, $A0, $00, $00, $00 // vmovdqu [r9 + 160], ymm0 + db $C5, $FE, $6F, $84, $24, $A0, $03, $00, $00 // vmovdqu ymm0, [rsp + 928] + db $C4, $C1, $7D, $EF, $80, $C0, $00, $00, $00 // vpxor ymm0, ymm0, [r8 + 192] + db $C4, $C1, $7E, $7F, $81, $C0, $00, $00, $00 // vmovdqu [r9 + 192], ymm0 + db $C5, $FE, $6F, $84, $24, $C0, $03, $00, $00 // vmovdqu ymm0, [rsp + 960] + db $C4, $C1, $7D, $EF, $80, $E0, $00, $00, $00 // vpxor ymm0, ymm0, [r8 + 224] + db $C4, $C1, $7E, $7F, $81, $E0, $00, $00, $00 // vmovdqu [r9 + 224], ymm0 + db $C5, $FE, $6F, $84, $24, $E0, $03, $00, $00 // vmovdqu ymm0, [rsp + 992] + db $C4, $C1, $7D, $EF, $80, $00, $01, $00, $00 // vpxor ymm0, ymm0, [r8 + 256] + db $C4, $C1, $7E, $7F, $81, $00, $01, $00, $00 // vmovdqu [r9 + 256], ymm0 + db $C5, $FE, $6F, $84, $24, $00, $04, $00, $00 // vmovdqu ymm0, [rsp + 1024] + db $C4, $C1, $7D, $EF, $80, $20, $01, $00, $00 // vpxor ymm0, ymm0, [r8 + 288] + db $C4, $C1, $7E, $7F, $81, $20, $01, $00, $00 // vmovdqu [r9 + 288], ymm0 + db $C5, $FE, $6F, $84, $24, $20, $04, $00, $00 // vmovdqu ymm0, [rsp + 1056] + db $C4, $C1, $7D, $EF, $80, $40, $01, $00, $00 // vpxor ymm0, ymm0, [r8 + 320] + db $C4, $C1, $7E, $7F, $81, $40, $01, $00, $00 // vmovdqu [r9 + 320], ymm0 + db $C5, $FE, $6F, $84, $24, $40, $04, $00, $00 // vmovdqu ymm0, [rsp + 1088] + db $C4, $C1, $7D, $EF, $80, $60, $01, $00, $00 // vpxor ymm0, ymm0, [r8 + 352] + db $C4, $C1, $7E, $7F, $81, $60, $01, $00, $00 // vmovdqu [r9 + 352], ymm0 + db $C5, $FE, $6F, $84, $24, $60, $04, $00, $00 // vmovdqu ymm0, [rsp + 1120] + db $C4, $C1, $7D, $EF, $80, $80, $01, $00, $00 // vpxor ymm0, ymm0, [r8 + 384] + db $C4, $C1, $7E, $7F, $81, $80, $01, $00, $00 // vmovdqu [r9 + 384], ymm0 + db $C5, $FE, $6F, $84, $24, $80, $04, $00, $00 // vmovdqu ymm0, [rsp + 1152] + db $C4, $C1, $7D, $EF, $80, $A0, $01, $00, $00 // vpxor ymm0, ymm0, [r8 + 416] + db $C4, $C1, $7E, $7F, $81, $A0, $01, $00, $00 // vmovdqu [r9 + 416], ymm0 + db $C5, $FE, $6F, $84, $24, $A0, $04, $00, $00 // vmovdqu ymm0, [rsp + 1184] + db $C4, $C1, $7D, $EF, $80, $C0, $01, $00, $00 // vpxor ymm0, ymm0, [r8 + 448] + db $C4, $C1, $7E, $7F, $81, $C0, $01, $00, $00 // vmovdqu [r9 + 448], ymm0 + db $C5, $FE, $6F, $84, $24, $C0, $04, $00, $00 // vmovdqu ymm0, [rsp + 1216] + db $C4, $C1, $7D, $EF, $80, $E0, $01, $00, $00 // vpxor ymm0, ymm0, [r8 + 480] + db $C4, $C1, $7E, $7F, $81, $E0, $01, $00, $00 // vmovdqu [r9 + 480], ymm0 + db $C5, $F8, $77 // vzeroupper + add rsp, 1248 +{$I ..\..\Include\Simd\Common\ClpSimdNonVolatileRestore_x86_64.inc} + diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks2Avx2_i386.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks2Avx2_i386.inc deleted file mode 100644 index 647c3305..00000000 --- a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks2Avx2_i386.inc +++ /dev/null @@ -1,16 +0,0 @@ -// ChaCha7539 (IETF) 128B, AVX2, i386. Little-endian state in [esi]; two 32-bit block counters in YMM lanes. -// Fused I/O xor: read plaintext at AIn (edi), xor with ChaCha output, write to AOut (eax). -// Fragments: ChaCha7539_Avx2_128B_LoadState_i386, ChaCha7539_Avx2_DoubleRound.inc, ChaCha7539_Avx2_128B_XorStore_i386 -// After ClpSimdProc4Begin_i386.inc: ebx=ARounds, esi=AState, edi=AIn, eax=AOut. - mov edx, ebx -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_128B_LoadState_i386.inc} - @@chacha7539_avx2_i386_pb2: -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_DoubleRound.inc} - sub edx, 2 - jg @@chacha7539_avx2_i386_pb2 -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_128B_XorStore_i386.inc} - db $81, $C4, $C8, $00, $00, $00 // add esp, 0xc8 - db $C5, $F8, $77 // vzeroupper - pop edi - pop esi - pop ebx diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks2Avx2_x86_64.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks2Avx2_x86_64.inc deleted file mode 100644 index 1fbebd20..00000000 --- a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks2Avx2_x86_64.inc +++ /dev/null @@ -1,13 +0,0 @@ -// ChaCha7539 (IETF) 128B, AVX2. Little-endian state in [rdx]; two 32-bit block counters in YMM lanes. -// Fused I/O xor: read plaintext at AIn (r8), xor with ChaCha output, write to AOut (r9) — no 128B keystream temp in Pascal; xor in asm (XorStore) after rounds. -// Fragments: ChaCha7539_Avx2_128B_LoadState, ChaCha7539_Avx2_DoubleRound.inc (VEX db), ChaCha7539_Avx2_128B_XorStore .inc -// After ClpSimdProc4Begin_x86_64.inc: rcx=ARounds, rdx=AState, r8=AIn, r9=AOut. - mov r10, rcx -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_128B_LoadState_x86_64.inc} - @@chacha7539_avx2_dround: -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_DoubleRound.inc} - sub r10, 2 - jg @@chacha7539_avx2_dround -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_128B_XorStore_x86_64.inc} - db $48, $81, $C4, $C8, $00, $00, $00 // add rsp, 0xc8 - db $C5, $F8, $77 // vzeroupper diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks4Avx2_i386.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks4Avx2_i386.inc deleted file mode 100644 index 8eea7cf1..00000000 --- a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks4Avx2_i386.inc +++ /dev/null @@ -1,27 +0,0 @@ -// ChaCha7539 (IETF) 256B, AVX2, i386. Two 128B blocks: same fused I/O xor as ProcessBlocks2 (AIn=edi, AOut=eax). -// One vzeroupper; add edi/eax,+128 between blocks. LoadState .inc reloads IETF state at [esi] (word 12 already advanced after block 1). -// After ClpSimdProc4Begin_i386.inc: ebx=ARounds, esi=AState, edi=AIn, eax=AOut. - mov edx, ebx - // --- first 128B --- -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_128B_LoadState_i386.inc} - @@c7539_avx2_i386_pb4_b1: -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_DoubleRound.inc} - sub edx, 2 - jg @@c7539_avx2_i386_pb4_b1 -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_128B_XorStore_i386.inc} - db $81, $C4, $C8, $00, $00, $00 // add esp, 0xc8 - add edi, 128 - add eax, 128 - mov edx, ebx - // --- second 128B (IETF state at [esi+48] is already advanced) --- -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_128B_LoadState_i386.inc} - @@c7539_avx2_i386_pb4_b2: -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_DoubleRound.inc} - sub edx, 2 - jg @@c7539_avx2_i386_pb4_b2 -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_128B_XorStore_i386.inc} - db $81, $C4, $C8, $00, $00, $00 // add esp, 0xc8 - db $C5, $F8, $77 // vzeroupper - pop edi - pop esi - pop ebx diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks4Avx2_x86_64.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks4Avx2_x86_64.inc deleted file mode 100644 index e2a9a728..00000000 --- a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539ProcessBlocks4Avx2_x86_64.inc +++ /dev/null @@ -1,24 +0,0 @@ -// ChaCha7539 (IETF) 256B, AVX2. Two 128B blocks: same fused I/O xor as ProcessBlocks2 (AIn=r8, AOut=r9; no large keystream temp in Pascal). -// One vzeroupper; add r8/r9,+128 between blocks. LoadState .inc reloads IETF state at [rdx] (word 12 already advanced after block 1). -// After ClpSimdProc4Begin_x86_64.inc: rcx=ARounds, rdx=AState, r8=AIn, r9=AOut. - mov r10, rcx - // --- first 128B --- -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_128B_LoadState_x86_64.inc} - @@c7539_avx2_pb4_b1: -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_DoubleRound.inc} - sub r10, 2 - jg @@c7539_avx2_pb4_b1 -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_128B_XorStore_x86_64.inc} - db $48, $81, $C4, $C8, $00, $00, $00 // add rsp, 0xc8 - add r8, 128 - add r9, 128 - mov r10, rcx - // --- second 128B (IETF state at [rdx+48] is already advanced) --- -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_128B_LoadState_x86_64.inc} - @@c7539_avx2_pb4_b2: -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_DoubleRound.inc} - sub r10, 2 - jg @@c7539_avx2_pb4_b2 -{$I ..\..\Include\Simd\ChaCha\ChaCha7539_Avx2_128B_XorStore_x86_64.inc} - db $48, $81, $C4, $C8, $00, $00, $00 // add rsp, 0xc8 - db $C5, $F8, $77 // vzeroupper diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_LoadState_i386.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_LoadState_i386.inc deleted file mode 100644 index 98f4ad4b..00000000 --- a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_LoadState_i386.inc +++ /dev/null @@ -1,27 +0,0 @@ -// ChaCha7539 (IETF) AVX2: 128B block prologue, i386. Fused I/O xor path: full keystream is not written to a Pascal temp; XorStore .inc xors in asm. -// sub esp,0xC8; state from ESI; bump IETF word-12 counter twice; save YMM scratch to [esp]. -// Parent must set edx := ebx (ARounds) before this include, once per 128B block (ProcessBlocks2 and each half of ProcessBlocks4). - db $81, $EC, $C8, $00, $00, $00 // sub esp, 0xc8 - db $C5, $FA, $6F, $26 // vmovdqu xmm4, xmmword ptr [esi] - db $C5, $FC, $57, $C0 // vxorps ymm0, ymm0, ymm0 - db $C4, $E3, $7D, $18, $C4, $00 // vinsertf128 ymm0, ymm0, xmm4, 0 - db $C4, $E3, $7D, $18, $C4, $01 // vinsertf128 ymm0, ymm0, xmm4, 1 - db $C5, $FA, $6F, $66, $10 // vmovdqu xmm4, xmmword ptr [esi + 0x10] - db $C5, $F4, $57, $C9 // vxorps ymm1, ymm1, ymm1 - db $C4, $E3, $75, $18, $CC, $00 // vinsertf128 ymm1, ymm1, xmm4, 0 - db $C4, $E3, $75, $18, $CC, $01 // vinsertf128 ymm1, ymm1, xmm4, 1 - db $C5, $FA, $6F, $66, $20 // vmovdqu xmm4, xmmword ptr [esi + 0x20] - db $C5, $EC, $57, $D2 // vxorps ymm2, ymm2, ymm2 - db $C4, $E3, $6D, $18, $D4, $00 // vinsertf128 ymm2, ymm2, xmm4, 0 - db $C4, $E3, $6D, $18, $D4, $01 // vinsertf128 ymm2, ymm2, xmm4, 1 - db $C5, $FA, $6F, $66, $30 // vmovdqu xmm4, xmmword ptr [esi + 0x30] - db $83, $46, $30, $01 // add dword ptr [esi + 0x30], 1 - db $C5, $FA, $6F, $6E, $30 // vmovdqu xmm5, xmmword ptr [esi + 0x30] - db $83, $46, $30, $01 // add dword ptr [esi + 0x30], 1 - db $C5, $E4, $57, $DB // vxorps ymm3, ymm3, ymm3 - db $C4, $E3, $65, $18, $DC, $00 // vinsertf128 ymm3, ymm3, xmm4, 0 - db $C4, $E3, $65, $18, $DD, $01 // vinsertf128 ymm3, ymm3, xmm5, 1 - db $C5, $FE, $7F, $04, $24 // vmovdqu ymmword ptr [esp], ymm0 - db $C5, $FE, $7F, $4C, $24, $20 // vmovdqu ymmword ptr [esp + 0x20], ymm1 - db $C5, $FE, $7F, $54, $24, $40 // vmovdqu ymmword ptr [esp + 0x40], ymm2 - db $C5, $FE, $7F, $5C, $24, $60 // vmovdqu ymmword ptr [esp + 0x60], ymm3 diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_LoadState_x86_64.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_LoadState_x86_64.inc deleted file mode 100644 index 9cb47994..00000000 --- a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_LoadState_x86_64.inc +++ /dev/null @@ -1,27 +0,0 @@ -// ChaCha7539 (IETF) AVX2: 128B block prologue. Fused I/O xor path: full keystream is not written to a Pascal temp; XorStore .inc xors in asm. -// sub rsp,0xC8; state from RDX; bump IETF word-12 counter twice; save YMM scratch to [rsp]. -// Parent must set r10 := rcx (rounds) before this include, once per 128B block (ProcessBlocks2 and each half of ProcessBlocks4). - db $48, $81, $EC, $C8, $00, $00, $00 // sub rsp, 0xc8 - db $C5, $FA, $6F, $22 // vmovdqu xmm4, xmmword ptr [rdx] - db $C5, $FC, $57, $C0 // vxorps ymm0, ymm0, ymm0 - db $C4, $E3, $7D, $18, $C4, $00 // vinsertf128 ymm0, ymm0, xmm4, 0 - db $C4, $E3, $7D, $18, $C4, $01 // vinsertf128 ymm0, ymm0, xmm4, 1 - db $C5, $FA, $6F, $62, $10 // vmovdqu xmm4, xmmword ptr [rdx + 0x10] - db $C5, $F4, $57, $C9 // vxorps ymm1, ymm1, ymm1 - db $C4, $E3, $75, $18, $CC, $00 // vinsertf128 ymm1, ymm1, xmm4, 0 - db $C4, $E3, $75, $18, $CC, $01 // vinsertf128 ymm1, ymm1, xmm4, 1 - db $C5, $FA, $6F, $62, $20 // vmovdqu xmm4, xmmword ptr [rdx + 0x20] - db $C5, $EC, $57, $D2 // vxorps ymm2, ymm2, ymm2 - db $C4, $E3, $6D, $18, $D4, $00 // vinsertf128 ymm2, ymm2, xmm4, 0 - db $C4, $E3, $6D, $18, $D4, $01 // vinsertf128 ymm2, ymm2, xmm4, 1 - db $C5, $FA, $6F, $62, $30 // vmovdqu xmm4, xmmword ptr [rdx + 0x30] - db $83, $42, $30, $01 // add dword ptr [rdx + 0x30], 1 - db $C5, $FA, $6F, $6A, $30 // vmovdqu xmm5, xmmword ptr [rdx + 0x30] - db $83, $42, $30, $01 // add dword ptr [rdx + 0x30], 1 - db $C5, $E4, $57, $DB // vxorps ymm3, ymm3, ymm3 - db $C4, $E3, $65, $18, $DC, $00 // vinsertf128 ymm3, ymm3, xmm4, 0 - db $C4, $E3, $65, $18, $DD, $01 // vinsertf128 ymm3, ymm3, xmm5, 1 - db $C5, $FE, $7F, $04, $24 // vmovdqu ymmword ptr [rsp], ymm0 - db $C5, $FE, $7F, $4C, $24, $20 // vmovdqu ymmword ptr [rsp + 0x20], ymm1 - db $C5, $FE, $7F, $54, $24, $40 // vmovdqu ymmword ptr [rsp + 0x40], ymm2 - db $C5, $FE, $7F, $5C, $24, $60 // vmovdqu ymmword ptr [rsp + 0x60], ymm3 diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_XorStore_i386.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_XorStore_i386.inc deleted file mode 100644 index 67a6ba7d..00000000 --- a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_XorStore_i386.inc +++ /dev/null @@ -1,26 +0,0 @@ -// ChaCha7539 (IETF) AVX2: after rounds, add back initial state from [esp] scratch, vperm2f128, then fused I/O xor, i386. -// Fused I/O xor: plaintext at EDI, ciphertext at EAX (encrypt; in-place if AIn=AOut). Offsets 0..0x7F. - db $C5, $FE, $6F, $24, $24 // vmovdqu ymm4, ymmword ptr [esp] - db $C5, $FD, $FE, $C4 // vpaddd ymm0, ymm0, ymm4 - db $C5, $FE, $6F, $64, $24, $20 // vmovdqu ymm4, ymmword ptr [esp + 0x20] - db $C5, $F5, $FE, $CC // vpaddd ymm1, ymm1, ymm4 - db $C5, $FE, $6F, $64, $24, $40 // vmovdqu ymm4, ymmword ptr [esp + 0x40] - db $C5, $ED, $FE, $D4 // vpaddd ymm2, ymm2, ymm4 - db $C5, $FE, $6F, $64, $24, $60 // vmovdqu ymm4, ymmword ptr [esp + 0x60] - db $C5, $E5, $FE, $DC // vpaddd ymm3, ymm3, ymm4 - db $C4, $E3, $7D, $06, $E1, $20 // vperm2f128 ymm4, ymm0, ymm1, 0x20 - db $C5, $FE, $6F, $2F // vmovdqu ymm5, ymmword ptr [edi] - db $C5, $DD, $EF, $E5 // vpxor ymm4, ymm4, ymm5 - db $C5, $FE, $7F, $20 // vmovdqu ymmword ptr [eax], ymm4 - db $C4, $E3, $6D, $06, $E3, $20 // vperm2f128 ymm4, ymm2, ymm3, 0x20 - db $C5, $FE, $6F, $6F, $20 // vmovdqu ymm5, ymmword ptr [edi + 0x20] - db $C5, $DD, $EF, $E5 // vpxor ymm4, ymm4, ymm5 - db $C5, $FE, $7F, $60, $20 // vmovdqu ymmword ptr [eax + 0x20], ymm4 - db $C4, $E3, $7D, $06, $E1, $31 // vperm2f128 ymm4, ymm0, ymm1, 0x31 - db $C5, $FE, $6F, $6F, $40 // vmovdqu ymm5, ymmword ptr [edi + 0x40] - db $C5, $DD, $EF, $E5 // vpxor ymm4, ymm4, ymm5 - db $C5, $FE, $7F, $60, $40 // vmovdqu ymmword ptr [eax + 0x40], ymm4 - db $C4, $E3, $6D, $06, $E3, $31 // vperm2f128 ymm4, ymm2, ymm3, 0x31 - db $C5, $FE, $6F, $6F, $60 // vmovdqu ymm5, ymmword ptr [edi + 0x60] - db $C5, $DD, $EF, $E5 // vpxor ymm4, ymm4, ymm5 - db $C5, $FE, $7F, $60, $60 // vmovdqu ymmword ptr [eax + 0x60], ymm4 diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_XorStore_x86_64.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_XorStore_x86_64.inc deleted file mode 100644 index 010dd6c8..00000000 --- a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_128B_XorStore_x86_64.inc +++ /dev/null @@ -1,26 +0,0 @@ -// ChaCha7539 (IETF) AVX2: after rounds, add back initial state from [rsp] scratch, vperm2f128, then fused I/O xor. -// Fused I/O xor: produce running output, xor with plaintext at r8, store ciphertext at r9 (encrypt; in-place if AIn=AOut). Offsets 0..0x7F. - db $C5, $FE, $6F, $24, $24 // vmovdqu ymm4, ymmword ptr [rsp] - db $C5, $FD, $FE, $C4 // vpaddd ymm0, ymm0, ymm4 - db $C5, $FE, $6F, $64, $24, $20 // vmovdqu ymm4, ymmword ptr [rsp + 0x20] - db $C5, $F5, $FE, $CC // vpaddd ymm1, ymm1, ymm4 - db $C5, $FE, $6F, $64, $24, $40 // vmovdqu ymm4, ymmword ptr [rsp + 0x40] - db $C5, $ED, $FE, $D4 // vpaddd ymm2, ymm2, ymm4 - db $C5, $FE, $6F, $64, $24, $60 // vmovdqu ymm4, ymmword ptr [rsp + 0x60] - db $C5, $E5, $FE, $DC // vpaddd ymm3, ymm3, ymm4 - db $C4, $E3, $7D, $06, $E1, $20 // vperm2f128 ymm4, ymm0, ymm1, 0x20 - db $C4, $C1, $7E, $6F, $28 // vmovdqu ymm5, ymmword ptr [r8] - db $C5, $DD, $EF, $E5 // vpxor ymm4, ymm4, ymm5 - db $C4, $C1, $7E, $7F, $21 // vmovdqu ymmword ptr [r9], ymm4 - db $C4, $E3, $6D, $06, $E3, $20 // vperm2f128 ymm4, ymm2, ymm3, 0x20 - db $C4, $C1, $7E, $6F, $68, $20 // vmovdqu ymm5, ymmword ptr [r8 + 0x20] - db $C5, $DD, $EF, $E5 // vpxor ymm4, ymm4, ymm5 - db $C4, $C1, $7E, $7F, $61, $20 // vmovdqu ymmword ptr [r9 + 0x20], ymm4 - db $C4, $E3, $7D, $06, $E1, $31 // vperm2f128 ymm4, ymm0, ymm1, 0x31 - db $C4, $C1, $7E, $6F, $68, $40 // vmovdqu ymm5, ymmword ptr [r8 + 0x40] - db $C5, $DD, $EF, $E5 // vpxor ymm4, ymm4, ymm5 - db $C4, $C1, $7E, $7F, $61, $40 // vmovdqu ymmword ptr [r9 + 0x40], ymm4 - db $C4, $E3, $6D, $06, $E3, $31 // vperm2f128 ymm4, ymm2, ymm3, 0x31 - db $C4, $C1, $7E, $6F, $68, $60 // vmovdqu ymm5, ymmword ptr [r8 + 0x60] - db $C5, $DD, $EF, $E5 // vpxor ymm4, ymm4, ymm5 - db $C4, $C1, $7E, $7F, $61, $60 // vmovdqu ymmword ptr [r9 + 0x60], ymm4 diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_DoubleRound.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_DoubleRound.inc deleted file mode 100644 index f7b1db25..00000000 --- a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539_Avx2_DoubleRound.inc +++ /dev/null @@ -1,57 +0,0 @@ -// ChaCha7539 (IETF) AVX2: one "double round" in two 32-lane YMMs (4 quarter-rounds). VEX db-encoded; ymm-only — same bytes in IA-32 and x86-64. -// ARX only — no fused I/O xor here (that is XorStore .inc after the round loop). Parent supplies: sub , 2 / jg . -// ChaCha20 in this tree uses SSE2, not this VEX include. - db $C5, $FD, $FE, $C1 // vpaddd ymm0, ymm0, ymm1 - db $C5, $E5, $EF, $D8 // vpxor ymm3, ymm3, ymm0 - db $C5, $FD, $6F, $E3 // vmovdqa ymm4, ymm3 - db $C5, $E5, $72, $D3, $10 // vpsrld ymm3, ymm3, 0x10 - db $C5, $DD, $72, $F4, $10 // vpslld ymm4, ymm4, 0x10 - db $C5, $E5, $EB, $DC // vpor ymm3, ymm3, ymm4 - db $C5, $ED, $FE, $D3 // vpaddd ymm2, ymm2, ymm3 - db $C5, $F5, $EF, $CA // vpxor ymm1, ymm1, ymm2 - db $C5, $FD, $6F, $E1 // vmovdqa ymm4, ymm1 - db $C5, $F5, $72, $D1, $14 // vpsrld ymm1, ymm1, 0x14 - db $C5, $DD, $72, $F4, $0C // vpslld ymm4, ymm4, 0xc - db $C5, $F5, $EB, $CC // vpor ymm1, ymm1, ymm4 - db $C5, $FD, $FE, $C1 // vpaddd ymm0, ymm0, ymm1 - db $C5, $E5, $EF, $D8 // vpxor ymm3, ymm3, ymm0 - db $C5, $FD, $6F, $E3 // vmovdqa ymm4, ymm3 - db $C5, $E5, $72, $D3, $18 // vpsrld ymm3, ymm3, 0x18 - db $C5, $DD, $72, $F4, $08 // vpslld ymm4, ymm4, 8 - db $C5, $E5, $EB, $DC // vpor ymm3, ymm3, ymm4 - db $C5, $ED, $FE, $D3 // vpaddd ymm2, ymm2, ymm3 - db $C5, $F5, $EF, $CA // vpxor ymm1, ymm1, ymm2 - db $C5, $FD, $6F, $E1 // vmovdqa ymm4, ymm1 - db $C5, $F5, $72, $D1, $19 // vpsrld ymm1, ymm1, 0x19 - db $C5, $DD, $72, $F4, $07 // vpslld ymm4, ymm4, 7 - db $C5, $F5, $EB, $CC // vpor ymm1, ymm1, ymm4 - db $C5, $FD, $70, $C9, $39 // vpshufd ymm1, ymm1, 0x39 - db $C5, $FD, $70, $D2, $4E // vpshufd ymm2, ymm2, 0x4e - db $C5, $FD, $70, $DB, $93 // vpshufd ymm3, ymm3, 0x93 - db $C5, $FD, $FE, $C1 // vpaddd ymm0, ymm0, ymm1 - db $C5, $E5, $EF, $D8 // vpxor ymm3, ymm3, ymm0 - db $C5, $FD, $6F, $E3 // vmovdqa ymm4, ymm3 - db $C5, $E5, $72, $D3, $10 // vpsrld ymm3, ymm3, 0x10 - db $C5, $DD, $72, $F4, $10 // vpslld ymm4, ymm4, 0x10 - db $C5, $E5, $EB, $DC // vpor ymm3, ymm3, ymm4 - db $C5, $ED, $FE, $D3 // vpaddd ymm2, ymm2, ymm3 - db $C5, $F5, $EF, $CA // vpxor ymm1, ymm1, ymm2 - db $C5, $FD, $6F, $E1 // vmovdqa ymm4, ymm1 - db $C5, $F5, $72, $D1, $14 // vpsrld ymm1, ymm1, 0x14 - db $C5, $DD, $72, $F4, $0C // vpslld ymm4, ymm4, 0xc - db $C5, $F5, $EB, $CC // vpor ymm1, ymm1, ymm4 - db $C5, $FD, $FE, $C1 // vpaddd ymm0, ymm0, ymm1 - db $C5, $E5, $EF, $D8 // vpxor ymm3, ymm3, ymm0 - db $C5, $FD, $6F, $E3 // vmovdqa ymm4, ymm3 - db $C5, $E5, $72, $D3, $18 // vpsrld ymm3, ymm3, 0x18 - db $C5, $DD, $72, $F4, $08 // vpslld ymm4, ymm4, 8 - db $C5, $E5, $EB, $DC // vpor ymm3, ymm3, ymm4 - db $C5, $ED, $FE, $D3 // vpaddd ymm2, ymm2, ymm3 - db $C5, $F5, $EF, $CA // vpxor ymm1, ymm1, ymm2 - db $C5, $FD, $6F, $E1 // vmovdqa ymm4, ymm1 - db $C5, $F5, $72, $D1, $19 // vpsrld ymm1, ymm1, 0x19 - db $C5, $DD, $72, $F4, $07 // vpslld ymm4, ymm4, 7 - db $C5, $F5, $EB, $CC // vpor ymm1, ymm1, ymm4 - db $C5, $FD, $70, $C9, $93 // vpshufd ymm1, ymm1, 0x93 - db $C5, $FD, $70, $D2, $4E // vpshufd ymm2, ymm2, 0x4e - db $C5, $FD, $70, $DB, $39 // vpshufd ymm3, ymm3, 0x39 diff --git a/CryptoLib/src/Interfaces/Crypto/ClpIBulkStreamCipher.pas b/CryptoLib/src/Interfaces/Crypto/ClpIBulkStreamCipher.pas new file mode 100644 index 00000000..5973718e --- /dev/null +++ b/CryptoLib/src/Interfaces/Crypto/ClpIBulkStreamCipher.pas @@ -0,0 +1,53 @@ +{ *********************************************************************************** } +{ * CryptoLib Library * } +{ * Author - Ugochukwu Mmaduekwe * } +{ * Github Repository * } +{ * * } +{ * Distributed under the MIT software license, see the accompanying file LICENSE * } +{ * or visit http://www.opensource.org/licenses/mit-license.php. * } +{ * * } +{ * Acknowledgements: * } +{ * * } +{ * Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring * } +{ * the development of this library * } +{ * ******************************************************************************* * } + +(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *) + +unit ClpIBulkStreamCipher; + +{$I ..\..\Include\CryptoLib.inc} + +interface + +uses + ClpIStreamCipher, + ClpCryptoLibTypes; + +type + /// + /// Capability interface for stream ciphers that emit many consecutive 64-byte + /// keystream blocks per call via a SIMD kernel. Resolved with Supports() and + /// driven through ProcessBlocks; its absence means "no fast path". + /// + IBulkStreamCipher = interface(IStreamCipher) + ['{7F1C4E62-9A3D-4B18-8E5A-2D6F1B0C7A94}'] + + /// + /// Transform ABlockCount 64-byte blocks; byte-identical to ABlockCount + /// single-block transforms and advances the counter by ABlockCount. Requires + /// block-aligned state; input and output must be identical or fully disjoint. + /// + /// Bytes produced (ABlockCount * 64). + function ProcessBlocks(const AInBuf: TCryptoLibByteArray; + AInOff, ABlockCount: Int32; const AOutBuf: TCryptoLibByteArray; + AOutOff: Int32): Int32; overload; + + /// Pointer overload of ProcessBlocks; same semantics. + function ProcessBlocks(AInput, AOutput: PByte; + ABlockCount: Int32): Int32; overload; + end; + +implementation + +end. diff --git a/CryptoLib/src/Packages/Delphi/CryptoLib4PascalPackage.dpk b/CryptoLib/src/Packages/Delphi/CryptoLib4PascalPackage.dpk index e4a1fc52..ddbdc48c 100644 --- a/CryptoLib/src/Packages/Delphi/CryptoLib4PascalPackage.dpk +++ b/CryptoLib/src/Packages/Delphi/CryptoLib4PascalPackage.dpk @@ -657,6 +657,7 @@ contains ClpIBlockCipherMode in '..\..\Interfaces\Crypto\Modes\ClpIBlockCipherMode.pas', ClpIBulkBlockCipherMode in '..\..\Interfaces\Crypto\Modes\ClpIBulkBlockCipherMode.pas', ClpIBulkBlockCipher in '..\..\Interfaces\Crypto\ClpIBulkBlockCipher.pas', + ClpIBulkStreamCipher in '..\..\Interfaces\Crypto\ClpIBulkStreamCipher.pas', ClpIEcbBlockCipher in '..\..\Interfaces\Crypto\Modes\ClpIEcbBlockCipher.pas', ClpEcbBlockCipher in '..\..\Crypto\Modes\ClpEcbBlockCipher.pas', ClpGnuObjectIdentifiers in '..\..\Asn1\Gnu\ClpGnuObjectIdentifiers.pas', diff --git a/CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk b/CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk index c5296e79..37b2c89c 100644 --- a/CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk +++ b/CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk @@ -31,7 +31,7 @@ Acknowledgements: Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the development of this library "/> - + @@ -3213,6 +3213,10 @@ Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the devel + + + + diff --git a/CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.pas b/CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.pas index 4e35c4b3..9ce3f30f 100644 --- a/CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.pas +++ b/CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.pas @@ -257,7 +257,7 @@ interface ClpPoly1305X86Backend, ClpGhashSimd, ClpGhashX86Backend, ClpGcmSivSimd, ClpGcmSivX86Backend, ClpAesNiFusedX86Backend, ClpBinPolySimd, ClpAesSimd, ClpIFusedCtrKernel, ClpAesNiCtrKernel, ClpByteXorSimd, ClpByteXorX86Backend, - ClpIFusedCbcKernel, ClpAesNiCbcKernel; + ClpIFusedCbcKernel, ClpAesNiCbcKernel, ClpIBulkStreamCipher; implementation From d134ca89a2430933e5d03443c9988ebcb9e5ec21 Mon Sep 17 00:00:00 2001 From: Ugochukwu Mmaduekwe Date: Thu, 9 Jul 2026 15:39:44 +0100 Subject: [PATCH 2/6] Fold ChaCha/Salsa ProcessBlocks2/4/8 into ProcessBlocks(count) Now that IBulkStreamCipher.ProcessBlocks(count) exists, the fixed-width bulk methods are redundant with the unified DoProcessBlocks ladder. - Engines: TChaChaBaseEngine and TSalsa20Engine ProcessBytes/DoFinal compute the whole-block count and make a single DoProcessBlocks call (which ladders 8->4->2->1 / 2->1 internally) plus the partial tail, replacing the fixed-width tier cascades (and their per-tier re-validation). Remove the public ProcessBlocks2/4/8 (ChaCha) and ProcessBlocks2 (Salsa). - Interface: drop ProcessBlocks2/4 from IChaCha7539Engine (it now exposes only DoFinal + ProcessBlock); bulk is purely the optional IBulkStreamCipher capability. Engine bulk surface is {ProcessBlock, ProcessBlocks(count)}. - TChaCha20Poly1305: collapse the ProcessBlock/2/4/8 wrappers into one ProcessBlocksBulk(count) and drive the AEAD body through IBulkStreamCipher as a 512B (8-way) stride loop + a single remaining-blocks call, keeping the same FDataCount bookkeeping. A single-block else-path covers a custom engine that exposes no bulk interface. --- .../src/Crypto/Engines/ClpChaChaEngine.pas | 139 ++---------------- .../src/Crypto/Engines/ClpSalsa20Engine.pas | 30 +--- .../src/Crypto/Modes/ClpChaCha20Poly1305.pas | 128 ++++++---------- .../Crypto/Engines/ClpIChaCha7539Engine.pas | 6 - 4 files changed, 67 insertions(+), 236 deletions(-) diff --git a/CryptoLib/src/Crypto/Engines/ClpChaChaEngine.pas b/CryptoLib/src/Crypto/Engines/ClpChaChaEngine.pas index 8832cc3d..d77e3a1e 100644 --- a/CryptoLib/src/Crypto/Engines/ClpChaChaEngine.pas +++ b/CryptoLib/src/Crypto/Engines/ClpChaChaEngine.pas @@ -86,15 +86,6 @@ TChaChaBaseEngine = class(TSalsa20Engine) procedure ProcessBlock(const AInBytes: TCryptoLibByteArray; AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); - procedure ProcessBlocks2(const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); override; - - procedure ProcessBlocks4(const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); - - procedure ProcessBlocks8(const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); - class procedure ChaChaCore(ARounds: Int32; const AInput: TCryptoLibUInt32Array; const AOutput: TCryptoLibByteArray); static; @@ -156,7 +147,7 @@ procedure TChaChaBaseEngine.GenerateKeyStream(const AOutput: TCryptoLibByteArray procedure TChaChaBaseEngine.DoFinal(const AInBuf: TCryptoLibByteArray; AInOff, AInLen: Int32; const AOutBuf: TCryptoLibByteArray; AOutOff: Int32); var - LIdx, LQ: Int32; + LIdx, LQ, LWholeBytes: Int32; begin if (not FInitialised) then begin @@ -172,36 +163,13 @@ procedure TChaChaBaseEngine.DoFinal(const AInBuf: TCryptoLibByteArray; TCheck.DataLength(AInBuf, AInOff, AInLen, SInputBufferTooShort); TCheck.OutputLength(AOutBuf, AOutOff, AInLen, SOutputBufferTooShort); - while (AInLen >= 512) do - begin - ProcessBlocks8(AInBuf, AInOff, AOutBuf, AOutOff); - AInOff := AInOff + 512; - AInLen := AInLen - 512; - AOutOff := AOutOff + 512; - end; - - while (AInLen >= 256) do - begin - ProcessBlocks4(AInBuf, AInOff, AOutBuf, AOutOff); - AInOff := AInOff + 256; - AInLen := AInLen - 256; - AOutOff := AOutOff + 256; - end; - - while (AInLen >= 128) do - begin - ProcessBlocks2(AInBuf, AInOff, AOutBuf, AOutOff); - AInOff := AInOff + 128; - AInLen := AInLen - 128; - AOutOff := AOutOff + 128; - end; - if (AInLen >= 64) then begin - ImplProcessBlock(AInBuf, AInOff, AOutBuf, AOutOff); - AInOff := AInOff + 64; - AInLen := AInLen - 64; - AOutOff := AOutOff + 64; + LWholeBytes := (AInLen shr 6) shl 6; // whole 64B blocks, engine ladders 8/4/2/1 + DoProcessBlocks(PByte(@AInBuf[AInOff]), PByte(@AOutBuf[AOutOff]), AInLen shr 6); + AInOff := AInOff + LWholeBytes; + AInLen := AInLen - LWholeBytes; + AOutOff := AOutOff + LWholeBytes; end; if (AInLen > 0) then @@ -262,33 +230,13 @@ procedure TChaChaBaseEngine.ProcessBytes(const AInBytes: TCryptoLibByteArray; System.Dec(ALen, LTake); continue; end; - if (ALen >= 512) then - begin - ProcessBlocks8(AInBytes, AInOff, AOutBytes, AOutOff); - AInOff := AInOff + 512; - AOutOff := AOutOff + 512; - System.Dec(ALen, 512); - end - else if (ALen >= 256) then - begin - ProcessBlocks4(AInBytes, AInOff, AOutBytes, AOutOff); - AInOff := AInOff + 256; - AOutOff := AOutOff + 256; - System.Dec(ALen, 256); - end - else if (ALen >= 128) then - begin - ProcessBlocks2(AInBytes, AInOff, AOutBytes, AOutOff); - AInOff := AInOff + 128; - AOutOff := AOutOff + 128; - System.Dec(ALen, 128); - end - else if (ALen >= 64) then + if (ALen >= 64) then begin - ImplProcessBlock(AInBytes, AInOff, AOutBytes, AOutOff); - AInOff := AInOff + 64; - AOutOff := AOutOff + 64; - System.Dec(ALen, 64); + LTake := (ALen shr 6) shl 6; // whole 64B blocks; engine ladders 8/4/2/1 + DoProcessBlocks(PByte(@AInBytes[AInOff]), PByte(@AOutBytes[AOutOff]), ALen shr 6); + AInOff := AInOff + LTake; + AOutOff := AOutOff + LTake; + System.Dec(ALen, LTake); end else begin @@ -334,27 +282,6 @@ procedure TChaChaBaseEngine.ProcessBlock(const AInBytes: TCryptoLibByteArray; ImplProcessBlock(AInBytes, AInOff, AOutBytes, AOutOff); end; -procedure TChaChaBaseEngine.ProcessBlocks2(const AInBytes: TCryptoLibByteArray; - AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); -begin - if (not FInitialised) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotInitialised, - [AlgorithmName]); - end; - if (FIndex <> 0) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotBlockAligned, - [AlgorithmName]); - end; - if (LimitExceeded(UInt32(128))) then - begin - raise EMaxBytesExceededCryptoLibException.CreateRes(@SMaxByteExceeded); - end; - - ProcessBlocks2Fast(PByte(@AInBytes[AInOff]), PByte(@AOutBytes[AOutOff])); -end; - procedure TChaChaBaseEngine.ProcessBlockFast(AIn, AOut: PByte); begin ChaChaCore(FRounds, FEngineState, FKeyStream); @@ -428,48 +355,6 @@ function TChaChaBaseEngine.DoProcessBlocks(AIn, AOut: PByte; end; end; -procedure TChaChaBaseEngine.ProcessBlocks4(const AInBytes: TCryptoLibByteArray; - AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); -begin - if (not FInitialised) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotInitialised, - [AlgorithmName]); - end; - if (FIndex <> 0) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotBlockAligned, - [AlgorithmName]); - end; - if (LimitExceeded(UInt32(256))) then - begin - raise EMaxBytesExceededCryptoLibException.CreateRes(@SMaxByteExceeded); - end; - - ProcessBlocks4Fast(PByte(@AInBytes[AInOff]), PByte(@AOutBytes[AOutOff])); -end; - -procedure TChaChaBaseEngine.ProcessBlocks8(const AInBytes: TCryptoLibByteArray; - AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); -begin - if (not FInitialised) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotInitialised, - [AlgorithmName]); - end; - if (FIndex <> 0) then - begin - raise EInvalidOperationCryptoLibException.CreateResFmt(@SNotBlockAligned, - [AlgorithmName]); - end; - if (LimitExceeded(UInt32(512))) then - begin - raise EMaxBytesExceededCryptoLibException.CreateRes(@SMaxByteExceeded); - end; - - ProcessBlocks8Fast(PByte(@AInBytes[AInOff]), PByte(@AOutBytes[AOutOff])); -end; - class procedure TChaChaBaseEngine.ChaChaCore(ARounds: Int32; const AInput: TCryptoLibUInt32Array; const AOutput: TCryptoLibByteArray); var diff --git a/CryptoLib/src/Crypto/Engines/ClpSalsa20Engine.pas b/CryptoLib/src/Crypto/Engines/ClpSalsa20Engine.pas index b0a1f402..24f18204 100644 --- a/CryptoLib/src/Crypto/Engines/ClpSalsa20Engine.pas +++ b/CryptoLib/src/Crypto/Engines/ClpSalsa20Engine.pas @@ -139,9 +139,6 @@ TSalsa20Engine = class(TInterfacedObject, ISalsa20Engine, IStreamCipher, const AParameters: ICipherParameters); virtual; function ReturnByte(AInput: Byte): Byte; virtual; - procedure ProcessBlocks2(const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); virtual; - // IBulkStreamCipher: bulk keystream over whole 64B blocks; engine owns the ladder. function ProcessBlocks(const AInBuf: TCryptoLibByteArray; AInOff, ABlockCount: Int32; const AOutBuf: TCryptoLibByteArray; @@ -329,14 +326,6 @@ procedure TSalsa20Engine.ImplProcessBlock( TByteUtilities.&Xor(64, LInP, LKeyP, LOutP); end; -procedure TSalsa20Engine.ProcessBlocks2( - const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); -begin - AssertInitialisedAndBlockAligned; - ProcessBlocks2Fast(PByte(@AInBytes[AInOff]), PByte(@AOutBytes[AOutOff])); -end; - procedure TSalsa20Engine.ProcessBlockFast(AIn, AOut: PByte); begin GenerateKeyStream(FKeyStream); @@ -461,20 +450,13 @@ procedure TSalsa20Engine.ProcessBytes(const AInBytes: TCryptoLibByteArray; continue; end; - if (ALen >= 128) then + if (ALen >= 64) then begin - ProcessBlocks2(AInBytes, AInOff, AOutBytes, AOutOff); - AInOff := AInOff + 128; - AOutOff := AOutOff + 128; - System.Dec(ALen, 128); - continue; - end - else if (ALen >= 64) then - begin - ImplProcessBlock(AInBytes, AInOff, AOutBytes, AOutOff); - AInOff := AInOff + 64; - AOutOff := AOutOff + 64; - System.Dec(ALen, 64); + LTake := (ALen shr 6) shl 6; // whole 64B blocks; engine ladders 2/1 + DoProcessBlocks(PByte(@AInBytes[AInOff]), PByte(@AOutBytes[AOutOff]), ALen shr 6); + AInOff := AInOff + LTake; + AOutOff := AOutOff + LTake; + System.Dec(ALen, LTake); continue; end else diff --git a/CryptoLib/src/Crypto/Modes/ClpChaCha20Poly1305.pas b/CryptoLib/src/Crypto/Modes/ClpChaCha20Poly1305.pas index e271fa51..7beb4cdf 100644 --- a/CryptoLib/src/Crypto/Modes/ClpChaCha20Poly1305.pas +++ b/CryptoLib/src/Crypto/Modes/ClpChaCha20Poly1305.pas @@ -134,14 +134,10 @@ TChaCha20Poly1305 = class(TInterfacedObject, IChaCha20Poly1305, IAeadCipher) procedure PadMac(ACount: UInt64); procedure ProcessBlock(const AInBytes: TCryptoLibByteArray; AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); - procedure ProcessBlocks2(const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); - procedure ProcessBlocks4(const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); - // 8-block (512B) tier via the engine's bulk stream interface; keeps the same - // running data-count bookkeeping as the narrower tiers. - procedure ProcessBlocks8(const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); + // Bulk tier via the engine's IBulkStreamCipher (ACount whole 64B blocks); keeps + // the same running data-count bookkeeping as the single-block ProcessBlock. + procedure ProcessBlocksBulk(const AInBytes: TCryptoLibByteArray; + AInOff, ACount: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); procedure ProcessData(const AInBytes: TCryptoLibByteArray; AInOff, AInLen: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); procedure Reset(AClearMac, AResetCipher: Boolean); overload; @@ -405,7 +401,7 @@ function TChaCha20Poly1305.ProcessByte(AInput: Byte; function TChaCha20Poly1305.ProcessBytes(const AInput: TCryptoLibByteArray; AInOff, ALen: Int32; const AOutput: TCryptoLibByteArray; AOutOff: Int32): Int32; var - LResultLen, LAvailable, LInLimit1, LInLimit2: Int32; + LResultLen, LAvailable, LInLimit1, LInLimit2, LRemBlocks: Int32; begin if (AInput = nil) then raise EArgumentNilCryptoLibException.CreateRes(@SInBytesNil); @@ -463,37 +459,34 @@ function TChaCha20Poly1305.ProcessBytes(const AInput: TCryptoLibByteArray; if (FBulkChaCha <> nil) then begin + // Bulk: MAC + decrypt in 512B (8-way) strides, then the remaining whole + // blocks (< 8) in a single engine-laddered call. while (AInOff <= LInLimit2 - (BufSize * 6)) do begin FPoly1305.BlockUpdate(AInput, AInOff, BufSize * 8); - ProcessBlocks8(AInput, AInOff, AOutput, AOutOff + LResultLen); + ProcessBlocksBulk(AInput, AInOff, 8, AOutput, AOutOff + LResultLen); AInOff := AInOff + BufSize * 8; LResultLen := LResultLen + BufSize * 8; end; - end; - - while (AInOff <= LInLimit2 - (BufSize * 2)) do - begin - FPoly1305.BlockUpdate(AInput, AInOff, BufSize * 4); - ProcessBlocks4(AInput, AInOff, AOutput, AOutOff + LResultLen); - AInOff := AInOff + BufSize * 4; - LResultLen := LResultLen + BufSize * 4; - end; - - while (AInOff <= LInLimit2) do - begin - FPoly1305.BlockUpdate(AInput, AInOff, BufSize * 2); - ProcessBlocks2(AInput, AInOff, AOutput, AOutOff + LResultLen); - AInOff := AInOff + BufSize * 2; - LResultLen := LResultLen + BufSize * 2; - end; - - if (AInOff <= LInLimit1) then + if (AInOff <= LInLimit1) then + begin + LRemBlocks := ((LInLimit1 - AInOff) div BufSize) + 1; + FPoly1305.BlockUpdate(AInput, AInOff, LRemBlocks * BufSize); + ProcessBlocksBulk(AInput, AInOff, LRemBlocks, AOutput, AOutOff + LResultLen); + AInOff := AInOff + LRemBlocks * BufSize; + LResultLen := LResultLen + LRemBlocks * BufSize; + end; + end + else begin - FPoly1305.BlockUpdate(AInput, AInOff, BufSize); - ProcessBlock(AInput, AInOff, AOutput, AOutOff + LResultLen); - AInOff := AInOff + BufSize; - LResultLen := LResultLen + BufSize; + // No bulk engine: single-block MAC-then-decrypt. + while (AInOff <= LInLimit1) do + begin + FPoly1305.BlockUpdate(AInput, AInOff, BufSize); + ProcessBlock(AInput, AInOff, AOutput, AOutOff + LResultLen); + AInOff := AInOff + BufSize; + LResultLen := LResultLen + BufSize; + end; end; FBufPos := System.Length(FBuf) + LInLimit1 - AInOff; @@ -523,33 +516,30 @@ function TChaCha20Poly1305.ProcessBytes(const AInput: TCryptoLibByteArray; if (FBulkChaCha <> nil) then begin + // Bulk: encrypt in 512B (8-way) strides, then the remaining whole blocks + // (< 8) in a single engine-laddered call; MAC over the ciphertext below. while (AInOff <= LInLimit2 - (BufSize * 6)) do begin - ProcessBlocks8(AInput, AInOff, AOutput, AOutOff + LResultLen); + ProcessBlocksBulk(AInput, AInOff, 8, AOutput, AOutOff + LResultLen); AInOff := AInOff + BufSize * 8; LResultLen := LResultLen + BufSize * 8; end; - end; - - while (AInOff <= LInLimit2 - (BufSize * 2)) do - begin - ProcessBlocks4(AInput, AInOff, AOutput, AOutOff + LResultLen); - AInOff := AInOff + BufSize * 4; - LResultLen := LResultLen + BufSize * 4; - end; - - while (AInOff <= LInLimit2) do - begin - ProcessBlocks2(AInput, AInOff, AOutput, AOutOff + LResultLen); - AInOff := AInOff + BufSize * 2; - LResultLen := LResultLen + BufSize * 2; - end; - - if (AInOff <= LInLimit1) then + if (AInOff <= LInLimit1) then + begin + LRemBlocks := ((LInLimit1 - AInOff) div BufSize) + 1; + ProcessBlocksBulk(AInput, AInOff, LRemBlocks, AOutput, AOutOff + LResultLen); + AInOff := AInOff + LRemBlocks * BufSize; + LResultLen := LResultLen + LRemBlocks * BufSize; + end; + end + else begin - ProcessBlock(AInput, AInOff, AOutput, AOutOff + LResultLen); - AInOff := AInOff + BufSize; - LResultLen := LResultLen + BufSize; + while (AInOff <= LInLimit1) do + begin + ProcessBlock(AInput, AInOff, AOutput, AOutOff + LResultLen); + AInOff := AInOff + BufSize; + LResultLen := LResultLen + BufSize; + end; end; FPoly1305.BlockUpdate(AOutput, AOutOff, LResultLen); @@ -732,34 +722,14 @@ procedure TChaCha20Poly1305.ProcessBlock(const AInBytes: TCryptoLibByteArray; FDataCount := IncrementCount(FDataCount, 64, DataLimit); end; -procedure TChaCha20Poly1305.ProcessBlocks2(const AInBytes: TCryptoLibByteArray; - AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); -begin - TCheck.OutputLength(AOutBytes, AOutOff, 128, SOutputBufferTooShort); - - FChaCha20.ProcessBlocks2(AInBytes, AInOff, AOutBytes, AOutOff); - - FDataCount := IncrementCount(FDataCount, 128, DataLimit); -end; - -procedure TChaCha20Poly1305.ProcessBlocks4(const AInBytes: TCryptoLibByteArray; - AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); -begin - TCheck.OutputLength(AOutBytes, AOutOff, 256, SOutputBufferTooShort); - - FChaCha20.ProcessBlocks4(AInBytes, AInOff, AOutBytes, AOutOff); - - FDataCount := IncrementCount(FDataCount, 256, DataLimit); -end; - -procedure TChaCha20Poly1305.ProcessBlocks8(const AInBytes: TCryptoLibByteArray; - AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); +procedure TChaCha20Poly1305.ProcessBlocksBulk(const AInBytes: TCryptoLibByteArray; + AInOff, ACount: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); begin - TCheck.OutputLength(AOutBytes, AOutOff, 512, SOutputBufferTooShort); + TCheck.OutputLength(AOutBytes, AOutOff, ACount * BufSize, SOutputBufferTooShort); - FBulkChaCha.ProcessBlocks(AInBytes, AInOff, 8, AOutBytes, AOutOff); + FBulkChaCha.ProcessBlocks(AInBytes, AInOff, ACount, AOutBytes, AOutOff); - FDataCount := IncrementCount(FDataCount, 512, DataLimit); + FDataCount := IncrementCount(FDataCount, ACount * BufSize, DataLimit); end; procedure TChaCha20Poly1305.ProcessData(const AInBytes: TCryptoLibByteArray; diff --git a/CryptoLib/src/Interfaces/Crypto/Engines/ClpIChaCha7539Engine.pas b/CryptoLib/src/Interfaces/Crypto/Engines/ClpIChaCha7539Engine.pas index 7a8d7061..81972072 100644 --- a/CryptoLib/src/Interfaces/Crypto/Engines/ClpIChaCha7539Engine.pas +++ b/CryptoLib/src/Interfaces/Crypto/Engines/ClpIChaCha7539Engine.pas @@ -35,12 +35,6 @@ interface procedure ProcessBlock(const AInBytes: TCryptoLibByteArray; AInOff: Int32; const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); - procedure ProcessBlocks2(const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); - - procedure ProcessBlocks4(const AInBytes: TCryptoLibByteArray; AInOff: Int32; - const AOutBytes: TCryptoLibByteArray; AOutOff: Int32); - end; implementation From 142c6281d35aac2f164704e4178449d95fcbda8a Mon Sep 17 00:00:00 2001 From: Ugochukwu Mmaduekwe Date: Thu, 9 Jul 2026 16:21:48 +0100 Subject: [PATCH 3/6] Fold AES fixed-width ProcessFourBlocks/ProcessEightBlocks into ProcessBlocks(count) The fixed-width batch methods on IAesHardwareEngine had no production caller (all modes use IBulkBlockCipher.ProcessBlocks(count); the fused AES-NI kernels use the raw key schedule) and baked x86's 4/8 widths into what is meant to be an architecture-neutral hardware-AES interface (a future ARMv8 engine seats on the same interface). - IAesHardwareEngine: drop ProcessFourBlocks / ProcessEightBlocks (array + ptr); it now adds only the single-block ProcessBlock(ptr) over IBulkBlockCipher. Bulk is the width-agnostic ProcessBlocks(count) ladder each engine drives at its own internal widths. - TAesEngineX86: remove the public fixed-width methods and their partial-overlap stack-buffer staging (no caller; it contradicts the identical-or-disjoint IBulkBlockCipher contract). The 4/8-wide *Fast helpers stay as the strict-private inner steps of the ProcessBlocks ladder; single-block ProcessBlock keeps its overlap staging. - AesHardwareEngineTests: migrate batch-vs-single and PByte-parity coverage to ProcessBlocks(4)/ProcessBlocks(8) (arch-neutral, ready for a future ARM engine); drop the 6 partial-overlap memory-layout tests that exercised the removed staging. --- .../src/Crypto/AesHardwareEngineTests.pas | 259 ++---------------- .../src/Crypto/Engines/ClpAesEngineX86.pas | 135 +-------- .../Crypto/Engines/ClpIAesHardwareEngine.pas | 36 +-- 3 files changed, 36 insertions(+), 394 deletions(-) diff --git a/CryptoLib.Tests/src/Crypto/AesHardwareEngineTests.pas b/CryptoLib.Tests/src/Crypto/AesHardwareEngineTests.pas index f2a0b90e..95a33532 100644 --- a/CryptoLib.Tests/src/Crypto/AesHardwareEngineTests.pas +++ b/CryptoLib.Tests/src/Crypto/AesHardwareEngineTests.pas @@ -43,9 +43,10 @@ interface type /// /// Engine-agnostic test suite for hardware-accelerated AES engines. All the - /// vector / Monte-Carlo / engine-check coverage plus the SIMD batch (4-/8-wide) - /// parity and memory-layout coverage lives here, written against - /// . A concrete per-architecture suite only + /// vector / Monte-Carlo / engine-check coverage plus the bulk batch parity + /// (ProcessBlocks 4-/8-wide vs single-block) and single-block memory-layout + /// coverage lives here, written against (bulk + /// via its inherited IBulkBlockCipher). A concrete per-architecture suite only /// has to supply four hooks (CreateHwEngine / EngineSupported / EngineLabel / /// GetEngineFactory) and register itself under its architecture guard; the /// published tests are inherited and discovered automatically. @@ -62,8 +63,6 @@ TAesHardwareEngineTestBase = class abstract(TAesBlockCipherTestBase) procedure ImplTestEightBlocks(AForEncryption: Boolean; AKeySizeBytes: Int32); procedure ImplTestPByteOverloadParity(AKeySizeBytes: Int32); procedure ImplTestProcessBlockMemoryLayouts(AKeySizeBytes: Int32); - procedure ImplTestProcessFourBlocksMemoryLayouts(AKeySizeBytes: Int32); - procedure ImplTestProcessEightBlocksMemoryLayouts(AKeySizeBytes: Int32); published // TestBlockCipherVector / TestMonteCarloAES / TestBadParameters are // inherited from TAesBlockCipherTestBase (guarded by EngineSupported). @@ -88,12 +87,6 @@ TAesHardwareEngineTestBase = class abstract(TAesBlockCipherTestBase) procedure TestProcessBlockMemoryLayouts128; procedure TestProcessBlockMemoryLayouts192; procedure TestProcessBlockMemoryLayouts256; - procedure TestProcessFourBlocksMemoryLayouts128; - procedure TestProcessFourBlocksMemoryLayouts192; - procedure TestProcessFourBlocksMemoryLayouts256; - procedure TestProcessEightBlocksMemoryLayouts128; - procedure TestProcessEightBlocksMemoryLayouts192; - procedure TestProcessEightBlocksMemoryLayouts256; end; {$IFDEF CRYPTOLIB_X86_SIMD} @@ -143,13 +136,13 @@ procedure TAesHardwareEngineTestBase.ImplTestFourBlocks(AForEncryption: Boolean; LRnd.NextBytes(LKey); LEngine := CreateHwEngine; LEngine.Init(AForEncryption, TKeyParameter.Create(LKey) as IKeyParameter); - LEngine.ProcessFourBlocks(LData, 0, LFourOut, 0); + LEngine.ProcessBlocks(LData, 0, 4, LFourOut, 0); for LJ := 0 to 3 do LEngine.ProcessBlock(LData, LJ * 16, LSingleOut, LJ * 16); if not AreEqual(LFourOut, LSingleOut) then begin Fail(Format( - 'ProcessFourBlocks vs ProcessBlock mismatch (key %d bytes, iteration %d)', + 'ProcessBlocks(4) vs ProcessBlock mismatch (key %d bytes, iteration %d)', [AKeySizeBytes, LI])); end; end; @@ -175,13 +168,13 @@ procedure TAesHardwareEngineTestBase.ImplTestEightBlocks(AForEncryption: Boolean LRnd.NextBytes(LKey); LEngine := CreateHwEngine; LEngine.Init(AForEncryption, TKeyParameter.Create(LKey) as IKeyParameter); - LEngine.ProcessEightBlocks(LData, 0, LEightOut, 0); + LEngine.ProcessBlocks(LData, 0, 8, LEightOut, 0); for LJ := 0 to 7 do LEngine.ProcessBlock(LData, LJ * 16, LSingleOut, LJ * 16); if not AreEqual(LEightOut, LSingleOut) then begin Fail(Format( - 'ProcessEightBlocks vs ProcessBlock mismatch (key %d bytes, iteration %d)', + 'ProcessBlocks(8) vs ProcessBlock mismatch (key %d bytes, iteration %d)', [AKeySizeBytes, LI])); end; end; @@ -231,31 +224,31 @@ procedure TAesHardwareEngineTestBase.ImplTestPByteOverloadParity(AKeySizeBytes: LRnd.NextBytes(LIn64); LFourArr := System.Copy(LIn64); LFourPtr := System.Copy(LIn64); - LEngine.ProcessFourBlocks(LIn64, 0, LFourArr, 0); - LEngine.ProcessFourBlocks(@LIn64[0], @LFourPtr[0]); + LEngine.ProcessBlocks(LIn64, 0, 4, LFourArr, 0); + LEngine.ProcessBlocks(@LIn64[0], @LFourPtr[0], 4); if not AreEqual(LFourArr, LFourPtr) then - Fail(Format('ProcessFourBlocks PByte disjoint mismatch (key %d, iter %d)', + Fail(Format('ProcessBlocks(4) PByte disjoint mismatch (key %d, iter %d)', [AKeySizeBytes, LI])); LFourPtr := System.Copy(LIn64); - LEngine.ProcessFourBlocks(@LFourPtr[0], @LFourPtr[0]); + LEngine.ProcessBlocks(@LFourPtr[0], @LFourPtr[0], 4); if not AreEqual(LFourArr, LFourPtr) then - Fail(Format('ProcessFourBlocks PByte in-place mismatch (key %d, iter %d)', + Fail(Format('ProcessBlocks(4) PByte in-place mismatch (key %d, iter %d)', [AKeySizeBytes, LI])); LRnd.NextBytes(LIn128); LEightArr := System.Copy(LIn128); LEightPtr := System.Copy(LIn128); - LEngine.ProcessEightBlocks(LIn128, 0, LEightArr, 0); - LEngine.ProcessEightBlocks(@LIn128[0], @LEightPtr[0]); + LEngine.ProcessBlocks(LIn128, 0, 8, LEightArr, 0); + LEngine.ProcessBlocks(@LIn128[0], @LEightPtr[0], 8); if not AreEqual(LEightArr, LEightPtr) then - Fail(Format('ProcessEightBlocks PByte disjoint mismatch (key %d, iter %d)', + Fail(Format('ProcessBlocks(8) PByte disjoint mismatch (key %d, iter %d)', [AKeySizeBytes, LI])); LEightPtr := System.Copy(LIn128); - LEngine.ProcessEightBlocks(@LEightPtr[0], @LEightPtr[0]); + LEngine.ProcessBlocks(@LEightPtr[0], @LEightPtr[0], 8); if not AreEqual(LEightArr, LEightPtr) then - Fail(Format('ProcessEightBlocks PByte in-place mismatch (key %d, iter %d)', + Fail(Format('ProcessBlocks(8) PByte in-place mismatch (key %d, iter %d)', [AKeySizeBytes, LI])); end; end; @@ -365,180 +358,6 @@ procedure TAesHardwareEngineTestBase.ImplTestProcessBlockMemoryLayouts(AKeySizeB end; end; -procedure TAesHardwareEngineTestBase.ImplTestProcessFourBlocksMemoryLayouts(AKeySizeBytes: Int32); -var - LRnd: ISecureRandom; - LKey, LPlain, LCipher, LScratch: TBytes; - LI: Int32; - LEngine: IAesHardwareEngine; - - function MemEq(const A: TBytes; AOff: Int32; const B: TBytes; BOff, ALen: Int32): Boolean; - begin - Result := CompareMem(@A[AOff], @B[BOff], ALen); - end; - -begin - LRnd := TSecureRandom.Create(); - System.SetLength(LKey, AKeySizeBytes); - System.SetLength(LPlain, 64); - System.SetLength(LCipher, 64); - - for LI := 0 to 24 do - begin - LRnd.NextBytes(LKey); - LRnd.NextBytes(LPlain); - LEngine := CreateHwEngine; - LEngine.Init(True, TKeyParameter.Create(LKey) as IKeyParameter); - LEngine.ProcessFourBlocks(LPlain, 0, LCipher, 0); - - LScratch := System.Copy(LPlain); - LEngine.ProcessFourBlocks(@LScratch[0], @LScratch[0]); - if not AreEqual(LCipher, LScratch) then - Fail(Format('ProcessFourBlocks enc in-place (key %d, iter %d)', [AKeySizeBytes, LI])); - - System.SetLength(LScratch, 192); - System.Move(LPlain[0], LScratch[0], 64); - System.FillChar(LScratch[64], 128, $5A); - LEngine.ProcessFourBlocks(@LScratch[0], @LScratch[64]); - if not MemEq(LCipher, 0, LScratch, 64, 64) then - Fail(Format('ProcessFourBlocks enc disjoint same allocation (key %d, iter %d)', - [AKeySizeBytes, LI])); - - System.SetLength(LScratch, 128); - System.Move(LPlain[0], LScratch[0], 64); - System.FillChar(LScratch[64], 64, 0); - LEngine.ProcessFourBlocks(@LScratch[0], @LScratch[32]); - if not MemEq(LCipher, 0, LScratch, 32, 64) then - Fail(Format('ProcessFourBlocks enc overlap dst=src+32 (key %d, iter %d)', - [AKeySizeBytes, LI])); - - System.FillChar(LScratch[0], 128, 0); - System.Move(LPlain[0], LScratch[32], 64); - LEngine.ProcessFourBlocks(@LScratch[32], @LScratch[0]); - if not MemEq(LCipher, 0, LScratch, 0, 64) then - Fail(Format('ProcessFourBlocks enc overlap dst=src-32 (key %d, iter %d)', - [AKeySizeBytes, LI])); - - LEngine.Init(False, TKeyParameter.Create(LKey) as IKeyParameter); - LEngine.ProcessFourBlocks(LCipher, 0, LPlain, 0); - - LScratch := System.Copy(LCipher); - LEngine.ProcessFourBlocks(@LScratch[0], @LScratch[0]); - if not AreEqual(LPlain, LScratch) then - Fail(Format('ProcessFourBlocks dec in-place (key %d, iter %d)', [AKeySizeBytes, LI])); - - System.SetLength(LScratch, 192); - System.Move(LCipher[0], LScratch[0], 64); - System.FillChar(LScratch[64], 128, $4B); - LEngine.ProcessFourBlocks(@LScratch[0], @LScratch[64]); - if not MemEq(LPlain, 0, LScratch, 64, 64) then - Fail(Format('ProcessFourBlocks dec disjoint same allocation (key %d, iter %d)', - [AKeySizeBytes, LI])); - - System.SetLength(LScratch, 128); - System.Move(LCipher[0], LScratch[0], 64); - System.FillChar(LScratch[64], 64, $33); - LEngine.ProcessFourBlocks(@LScratch[0], @LScratch[32]); - if not MemEq(LPlain, 0, LScratch, 32, 64) then - Fail(Format('ProcessFourBlocks dec overlap dst=src+32 (key %d, iter %d)', - [AKeySizeBytes, LI])); - - System.FillChar(LScratch[0], 128, $44); - System.Move(LCipher[0], LScratch[32], 64); - LEngine.ProcessFourBlocks(@LScratch[32], @LScratch[0]); - if not MemEq(LPlain, 0, LScratch, 0, 64) then - Fail(Format('ProcessFourBlocks dec overlap dst=src-32 (key %d, iter %d)', - [AKeySizeBytes, LI])); - end; -end; - -procedure TAesHardwareEngineTestBase.ImplTestProcessEightBlocksMemoryLayouts(AKeySizeBytes: Int32); -var - LRnd: ISecureRandom; - LKey, LPlain, LCipher, LScratch: TBytes; - LI: Int32; - LEngine: IAesHardwareEngine; - - function MemEq(const A: TBytes; AOff: Int32; const B: TBytes; BOff, ALen: Int32): Boolean; - begin - Result := CompareMem(@A[AOff], @B[BOff], ALen); - end; - -begin - LRnd := TSecureRandom.Create(); - System.SetLength(LKey, AKeySizeBytes); - System.SetLength(LPlain, 128); - System.SetLength(LCipher, 128); - - for LI := 0 to 14 do - begin - LRnd.NextBytes(LKey); - LRnd.NextBytes(LPlain); - LEngine := CreateHwEngine; - LEngine.Init(True, TKeyParameter.Create(LKey) as IKeyParameter); - LEngine.ProcessEightBlocks(LPlain, 0, LCipher, 0); - - LScratch := System.Copy(LPlain); - LEngine.ProcessEightBlocks(@LScratch[0], @LScratch[0]); - if not AreEqual(LCipher, LScratch) then - Fail(Format('ProcessEightBlocks enc in-place (key %d, iter %d)', [AKeySizeBytes, LI])); - - System.SetLength(LScratch, 384); - System.Move(LPlain[0], LScratch[0], 128); - System.FillChar(LScratch[128], 256, $5A); - LEngine.ProcessEightBlocks(@LScratch[0], @LScratch[128]); - if not MemEq(LCipher, 0, LScratch, 128, 128) then - Fail(Format('ProcessEightBlocks enc disjoint same allocation (key %d, iter %d)', - [AKeySizeBytes, LI])); - - System.SetLength(LScratch, 256); - System.Move(LPlain[0], LScratch[0], 128); - System.FillChar(LScratch[128], 128, 0); - LEngine.ProcessEightBlocks(@LScratch[0], @LScratch[64]); - if not MemEq(LCipher, 0, LScratch, 64, 128) then - Fail(Format('ProcessEightBlocks enc overlap dst=src+64 (key %d, iter %d)', - [AKeySizeBytes, LI])); - - System.FillChar(LScratch[0], 256, 0); - System.Move(LPlain[0], LScratch[64], 128); - LEngine.ProcessEightBlocks(@LScratch[64], @LScratch[0]); - if not MemEq(LCipher, 0, LScratch, 0, 128) then - Fail(Format('ProcessEightBlocks enc overlap dst=src-64 (key %d, iter %d)', - [AKeySizeBytes, LI])); - - LEngine.Init(False, TKeyParameter.Create(LKey) as IKeyParameter); - LEngine.ProcessEightBlocks(LCipher, 0, LPlain, 0); - - LScratch := System.Copy(LCipher); - LEngine.ProcessEightBlocks(@LScratch[0], @LScratch[0]); - if not AreEqual(LPlain, LScratch) then - Fail(Format('ProcessEightBlocks dec in-place (key %d, iter %d)', [AKeySizeBytes, LI])); - - System.SetLength(LScratch, 384); - System.Move(LCipher[0], LScratch[0], 128); - System.FillChar(LScratch[128], 256, $4B); - LEngine.ProcessEightBlocks(@LScratch[0], @LScratch[128]); - if not MemEq(LPlain, 0, LScratch, 128, 128) then - Fail(Format('ProcessEightBlocks dec disjoint same allocation (key %d, iter %d)', - [AKeySizeBytes, LI])); - - System.SetLength(LScratch, 256); - System.Move(LCipher[0], LScratch[0], 128); - System.FillChar(LScratch[128], 128, $33); - LEngine.ProcessEightBlocks(@LScratch[0], @LScratch[64]); - if not MemEq(LPlain, 0, LScratch, 64, 128) then - Fail(Format('ProcessEightBlocks dec overlap dst=src+64 (key %d, iter %d)', - [AKeySizeBytes, LI])); - - System.FillChar(LScratch[0], 256, $44); - System.Move(LCipher[0], LScratch[64], 128); - LEngine.ProcessEightBlocks(@LScratch[64], @LScratch[0]); - if not MemEq(LPlain, 0, LScratch, 0, 128) then - Fail(Format('ProcessEightBlocks dec overlap dst=src-64 (key %d, iter %d)', - [AKeySizeBytes, LI])); - end; -end; - procedure TAesHardwareEngineTestBase.TestEngineChecks128; var LKey: TBytes; @@ -707,48 +526,6 @@ procedure TAesHardwareEngineTestBase.TestProcessBlockMemoryLayouts256; ImplTestProcessBlockMemoryLayouts(32); end; -procedure TAesHardwareEngineTestBase.TestProcessFourBlocksMemoryLayouts128; -begin - if not EngineSupported then - Exit; - ImplTestProcessFourBlocksMemoryLayouts(16); -end; - -procedure TAesHardwareEngineTestBase.TestProcessFourBlocksMemoryLayouts192; -begin - if not EngineSupported then - Exit; - ImplTestProcessFourBlocksMemoryLayouts(24); -end; - -procedure TAesHardwareEngineTestBase.TestProcessFourBlocksMemoryLayouts256; -begin - if not EngineSupported then - Exit; - ImplTestProcessFourBlocksMemoryLayouts(32); -end; - -procedure TAesHardwareEngineTestBase.TestProcessEightBlocksMemoryLayouts128; -begin - if not EngineSupported then - Exit; - ImplTestProcessEightBlocksMemoryLayouts(16); -end; - -procedure TAesHardwareEngineTestBase.TestProcessEightBlocksMemoryLayouts192; -begin - if not EngineSupported then - Exit; - ImplTestProcessEightBlocksMemoryLayouts(24); -end; - -procedure TAesHardwareEngineTestBase.TestProcessEightBlocksMemoryLayouts256; -begin - if not EngineSupported then - Exit; - ImplTestProcessEightBlocksMemoryLayouts(32); -end; - {$IFDEF CRYPTOLIB_X86_SIMD} function CreateAesX86Engine: IBlockCipher; diff --git a/CryptoLib/src/Crypto/Engines/ClpAesEngineX86.pas b/CryptoLib/src/Crypto/Engines/ClpAesEngineX86.pas index 9636ce45..8461ee63 100644 --- a/CryptoLib/src/Crypto/Engines/ClpAesEngineX86.pas +++ b/CryptoLib/src/Crypto/Engines/ClpAesEngineX86.pas @@ -76,28 +76,16 @@ TAesEngineX86 = class sealed(TInterfacedObject, IAesEngineX86, IAesHardwareEng function GetAlgorithmName: String; // ===== Internal fast-path helpers (engine's own ProcessBlocks ladder) ===== - // Bypass the nil-pointer / overlap safety checks and the stack-buffer - // staging used by the public ProcessBlock / ProcessFourBlocks / - // ProcessEightBlocks variants. Only ProcessBlocks (PByte overload) drives - // these: it has already honoured the IBulkBlockCipher aliasing contract - // (identical-or-fully-disjoint) for the whole batch, so each 4/8-wide - // slice inherits that same contract for free. Hidden behind strict private - // so no external caller can reach them and accidentally skip safety. - /// - /// Four consecutive 16-byte blocks (64 bytes) via pointers. Skips - /// nil/overlap safety checks and the stack-buffer copy used by - /// . Callers MUST pass valid 64-byte - /// buffers that are either identical (in-place) or fully disjoint. - /// + // The 4/8-wide inner steps of the IBulkBlockCipher ProcessBlocks ladder. + // Only ProcessBlocks (PByte overload) drives these: it has already honoured + // the IBulkBlockCipher aliasing contract (identical-or-fully-disjoint) for + // the whole batch, so each slice inherits it. Strict private so no external + // caller can reach them and skip that check. + /// Four consecutive 16-byte blocks (64 bytes) via pointers. + /// Identical-or-fully-disjoint buffers only. function ProcessFourBlocksFast(AInput, AOutput: PByte): Int32; inline; - /// - /// Eight consecutive 16-byte blocks (128 bytes) via pointers. Skips the - /// nil/overlap safety checks and stack-buffer copy used by the safe - /// / / - /// variants. Callers MUST pass valid - /// 128-byte buffers that are either identical (in-place) or fully - /// disjoint. - /// + /// Eight consecutive 16-byte blocks (128 bytes) via pointers. + /// Identical-or-fully-disjoint buffers only. function ProcessEightBlocksFast(AInput, AOutput: PByte): Int32; inline; public class function IsSupported: Boolean; static; @@ -107,18 +95,7 @@ TAesEngineX86 = class sealed(TInterfacedObject, IAesEngineX86, IAesHardwareEng function GetBlockSize(): Int32; function ProcessBlock(const AInput: TCryptoLibByteArray; AInOff: Int32; const AOutput: TCryptoLibByteArray; AOutOff: Int32): Int32; overload; - function ProcessFourBlocks(const AInput: TCryptoLibByteArray; AInOff: Int32; - const AOutput: TCryptoLibByteArray; AOutOff: Int32): Int32; overload; - /// - /// Eight consecutive 16-byte blocks (128 bytes). In-place, disjoint, and - /// overlapping ranges are handled safely; overlapping ranges are staged - /// through a 128-byte stack buffer. Returns BlockSize * 8. - /// - function ProcessEightBlocks(const AInput: TCryptoLibByteArray; AInOff: Int32; - const AOutput: TCryptoLibByteArray; AOutOff: Int32): Int32; overload; function ProcessBlock(AInput, AOutput: PByte): Int32; overload; - function ProcessFourBlocks(AInput, AOutput: PByte): Int32; overload; - function ProcessEightBlocks(AInput, AOutput: PByte): Int32; overload; // ===== IBulkBlockCipher ===== // Generic multi-block fast path exposed as a cipher-agnostic capability @@ -1035,36 +1012,10 @@ function TAesEngineX86.ProcessBlock(const AInput: TCryptoLibByteArray; Result := ProcessBlock(@AInput[AInOff], @AOutput[AOutOff]); end; -function TAesEngineX86.ProcessFourBlocks(const AInput: TCryptoLibByteArray; - AInOff: Int32; const AOutput: TCryptoLibByteArray; AOutOff: Int32): Int32; -begin - if FKeys = nil then - raise EInvalidOperationCryptoLibException.CreateRes(@SAesEngineX86NotInitialised); - - TCheck.DataLength(AInput, AInOff, 64, SInputBufferTooShort); - TCheck.OutputLength(AOutput, AOutOff, 64, SOutputBufferTooShort); - - Result := ProcessFourBlocks(@AInput[AInOff], @AOutput[AOutOff]); -end; - -function TAesEngineX86.ProcessEightBlocks(const AInput: TCryptoLibByteArray; - AInOff: Int32; const AOutput: TCryptoLibByteArray; AOutOff: Int32): Int32; -begin - if FKeys = nil then - raise EInvalidOperationCryptoLibException.CreateRes(@SAesEngineX86NotInitialised); - - TCheck.DataLength(AInput, AInOff, 128, SInputBufferTooShort); - TCheck.OutputLength(AOutput, AOutOff, 128, SOutputBufferTooShort); - - Result := ProcessEightBlocks(@AInput[AInOff], @AOutput[AOutOff]); -end; - // ===================================================================== -// Pointer-overload block processing - defense-in-depth version that -// guards against overlapping in/out ranges by staging through a stack -// buffer. Same validation as the array overloads plus nil-pointer and -// binding checks. Used by higher-level modes (CTR, GCM) that already -// know the buffer shape. +// Pointer-overload single-block processing - defense-in-depth version +// that guards against overlapping in/out ranges by staging through a +// stack buffer, plus nil-pointer and binding checks. // ===================================================================== function TAesEngineX86.ProcessBlock(AInput, AOutput: PByte): Int32; @@ -1099,68 +1050,6 @@ function TAesEngineX86.ProcessBlock(AInput, AOutput: PByte): Int32; Result := 16; end; -function TAesEngineX86.ProcessFourBlocks(AInput, AOutput: PByte): Int32; -var - LWork: array [0 .. 63] of Byte; -begin - if FKeys = nil then - raise EInvalidOperationCryptoLibException.CreateRes(@SAesEngineX86NotInitialised); - if not Assigned(FAesNiCipherFour) or not Assigned(FAesNiCipherFourInOut) then - raise EInvalidOperationCryptoLibException.CreateRes(@SAesEngineX86NotInitialised); - if (AInput = nil) or (AOutput = nil) then - raise EArgumentCryptoLibException.CreateRes(@SNilPointerBuffer); - - if AInput = AOutput then - begin - FAesNiCipherFour(AOutput, FKeys); - Result := 64; - Exit; - end; - - if ((AOutput >= AInput) and (AOutput < AInput + 64)) or - ((AInput >= AOutput) and (AInput < AOutput + 64)) then - begin - System.Move(AInput^, LWork[0], 64); - FAesNiCipherFour(@LWork[0], FKeys); - System.Move(LWork[0], AOutput^, 64); - FillChar(LWork, SizeOf(LWork), 0); - end - else - FAesNiCipherFourInOut(AInput, AOutput, FKeys); - Result := 64; -end; - -function TAesEngineX86.ProcessEightBlocks(AInput, AOutput: PByte): Int32; -var - LWork: array [0 .. 127] of Byte; -begin - if FKeys = nil then - raise EInvalidOperationCryptoLibException.CreateRes(@SAesEngineX86NotInitialised); - if not Assigned(FAesNiCipherEight) or not Assigned(FAesNiCipherEightInOut) then - raise EInvalidOperationCryptoLibException.CreateRes(@SAesEngineX86NotInitialised); - if (AInput = nil) or (AOutput = nil) then - raise EArgumentCryptoLibException.CreateRes(@SNilPointerBuffer); - - if AInput = AOutput then - begin - FAesNiCipherEight(AOutput, FKeys); - Result := 128; - Exit; - end; - - if ((AOutput >= AInput) and (AOutput < AInput + 128)) or - ((AInput >= AOutput) and (AInput < AOutput + 128)) then - begin - System.Move(AInput^, LWork[0], 128); - FAesNiCipherEight(@LWork[0], FKeys); - System.Move(LWork[0], AOutput^, 128); - FillChar(LWork, SizeOf(LWork), 0); - end - else - FAesNiCipherEightInOut(AInput, AOutput, FKeys); - Result := 128; -end; - // ===================================================================== // "Fast" pointer overloads - no validation, no overlap staging. Only // callable from code paths that have already proven their preconditions diff --git a/CryptoLib/src/Interfaces/Crypto/Engines/ClpIAesHardwareEngine.pas b/CryptoLib/src/Interfaces/Crypto/Engines/ClpIAesHardwareEngine.pas index 691036ec..76722b00 100644 --- a/CryptoLib/src/Interfaces/Crypto/Engines/ClpIAesHardwareEngine.pas +++ b/CryptoLib/src/Interfaces/Crypto/Engines/ClpIAesHardwareEngine.pas @@ -28,12 +28,12 @@ interface /// /// Architecture-neutral capability interface for hardware-accelerated AES /// engines (e.g. AES-NI on x86 via TAesEngineX86; a NEON/Crypto-Ext - /// ARMv8 engine could implement the same surface). It exposes the - /// fixed-width 4-/8-block batch entry points and the raw-pointer single-block - /// overload that sit beneath the generic - /// ladder. The aliasing contract for every overload here is identical to - /// IBulkBlockCipher: AInput / AOutput MUST be either identical pointers - /// (in-place) or reference fully disjoint ranges of the stated size. + /// ARMv8 engine could implement the same surface). Bulk work goes through the + /// width-agnostic ladder, which each engine + /// drives at its own internal batch widths; this interface adds only a + /// raw-pointer single-block overload. Aliasing for the pointer overload is + /// identical to IBulkBlockCipher: AInput / AOutput MUST be identical pointers + /// (in-place) or reference fully disjoint ranges. /// /// /// This interface is the shared surface that engine-agnostic test suites and @@ -49,30 +49,6 @@ interface /// behind each pointer and the standard identical-or-disjoint aliasing. /// function ProcessBlock(AInput, AOutput: PByte): Int32; overload; - - /// - /// Four consecutive 16-byte blocks (64 bytes) from AInput[AInOff] into - /// AOutput[AOutOff]. - /// - function ProcessFourBlocks(const AInput: TCryptoLibByteArray; AInOff: Int32; - const AOutput: TCryptoLibByteArray; AOutOff: Int32): Int32; overload; - - /// - /// Four consecutive 16-byte blocks (64 bytes) via raw pointers. - /// - function ProcessFourBlocks(AInput, AOutput: PByte): Int32; overload; - - /// - /// Eight consecutive 16-byte blocks (128 bytes) from AInput[AInOff] into - /// AOutput[AOutOff]. - /// - function ProcessEightBlocks(const AInput: TCryptoLibByteArray; AInOff: Int32; - const AOutput: TCryptoLibByteArray; AOutOff: Int32): Int32; overload; - - /// - /// Eight consecutive 16-byte blocks (128 bytes) via raw pointers. - /// - function ProcessEightBlocks(AInput, AOutput: PByte): Int32; overload; end; implementation From 29d11a23119d2b827ec3d19b6a1d96c326b2f867 Mon Sep 17 00:00:00 2001 From: Ugochukwu Mmaduekwe Date: Thu, 9 Jul 2026 19:00:30 +0100 Subject: [PATCH 4/6] Add 2-way SSE2 Poly1305 bulk kernel (x86_64 + i386) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fills the sub-AVX2 gap in the Poly1305 dispatch ladder: without it, any non-AVX2 CPU fell back to the radix-2^26 scalar path, collapsing the MAC (~240 MB/s) and Poly-bound AEAD (~70 MB/s). The new kernel is a 2-lane (xmm) radix-2^26 narrowing of the 4-way AVX2 kernel — same 5x5 schoolbook multiply mod 2^130-5 with the 5*r wraparound, 2 blocks/iter against an r/r^2 power table, pshufd horizontal fold — keeping SIMD/scalar radix parity across the whole ladder. --- .../src/Crypto/Macs/ClpPoly1305X86Backend.pas | 115 +++- .../Poly1305BlocksBulkSse2Core_i386.inc | 508 ++++++++++++++++++ .../Poly1305BlocksBulkSse2Core_x86_64.inc | 394 ++++++++++++++ 3 files changed, 995 insertions(+), 22 deletions(-) create mode 100644 CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkSse2Core_i386.inc create mode 100644 CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkSse2Core_x86_64.inc diff --git a/CryptoLib/src/Crypto/Macs/ClpPoly1305X86Backend.pas b/CryptoLib/src/Crypto/Macs/ClpPoly1305X86Backend.pas index cdd71d09..f9f49ae3 100644 --- a/CryptoLib/src/Crypto/Macs/ClpPoly1305X86Backend.pas +++ b/CryptoLib/src/Crypto/Macs/ClpPoly1305X86Backend.pas @@ -169,12 +169,56 @@ procedure Poly1305Avx2InitPowerTable(var APowTable: TCryptoLibByteArray; LTbl^[9, LIdx] := 0; end; -// Asm wrapper around the architecture-specific 4-way bulk kernel. The .inc -// files contain pure assembly (db-encoded VEX with mnemonic comments); the -// Pascal layer below is just the procedure header + the ClpSimdProc5Begin ABI -// glue + the kernel body include. ACtx points at the 72-byte R/S/H/K -// portion of TPoly1305State; APowTable points at the separate 320-byte -// power table buffer; the kernel never reads the K limbs. +// (Re)allocate APowTable and pack r^1, r^2 for the 2-way SSE2 bulk kernel. +// 160 bytes = 10 rows x 4 dwords. Rows 0..4 hold limbs of [r^2, r^2, r^2, r^1] +// (so a broadcast load gives r^2 in both 64-bit lanes and a +4 shifted load +// gives [r^2, r^1]); rows 5..8 hold the 5x wraparound multipliers; row 9 is +// padding for the +4 over-read of the last shifted load. +procedure Poly1305Sse2InitPowerTable(var APowTable: TCryptoLibByteArray; + const AState: TPoly1305State); +const + TableSize = Int32(160); +type + TPowTableLayout = array[0..9, 0..3] of UInt32; + PPowTableLayout = ^TPowTableLayout; +var + LTbl: PPowTableLayout; + Lr1, Lr2: array[0..4] of UInt32; + LIdx, LRow, LJ: Int32; +begin + System.SetLength(APowTable, TableSize); + LTbl := PPowTableLayout(APowTable); + + Lr1[0] := AState.R0; + Lr1[1] := AState.R1; + Lr1[2] := AState.R2; + Lr1[3] := AState.R3; + Lr1[4] := AState.R4; + + Poly1305MulLimbs(Lr2, Lr1, Lr1); + + for LIdx := 0 to 4 do + begin + LTbl^[LIdx, 0] := Lr2[LIdx]; + LTbl^[LIdx, 1] := Lr2[LIdx]; + LTbl^[LIdx, 2] := Lr2[LIdx]; + LTbl^[LIdx, 3] := Lr1[LIdx]; + end; + + for LRow := 5 to 8 do + begin + LJ := LRow - 4; // 1..4 + LTbl^[LRow, 0] := Lr2[LJ] * 5; + LTbl^[LRow, 1] := Lr2[LJ] * 5; + LTbl^[LRow, 2] := Lr2[LJ] * 5; + LTbl^[LRow, 3] := Lr1[LJ] * 5; + end; + + for LIdx := 0 to 3 do + LTbl^[9, LIdx] := 0; +end; + +// AVX2 4-way bulk kernel (r^1..r^4 power table, 64-byte stride). procedure Poly1305BlocksBulkAvx2Core(ACtx, APowTable, AInp: PByte; ALen: NativeUInt; APad: Int32); {$IFDEF CRYPTOLIB_X86_64_ASM} @@ -187,6 +231,19 @@ procedure Poly1305BlocksBulkAvx2Core(ACtx, APowTable, AInp: PByte; {$ENDIF} end; +// SSE2 2-way bulk kernel (r/r^2 power table, 32-byte stride). +procedure Poly1305BlocksBulkSse2Core(ACtx, APowTable, AInp: PByte; + ALen: NativeUInt; APad: Int32); +{$IFDEF CRYPTOLIB_X86_64_ASM} +{$I ..\..\Include\Simd\Common\ClpSimdProc5Begin_x86_64.inc} +{$I ..\..\Include\Simd\Poly1305\Poly1305BlocksBulkSse2Core_x86_64.inc} +{$ENDIF} +{$IFDEF CRYPTOLIB_I386_ASM} +{$I ..\..\Include\Simd\Common\ClpSimdProc5Begin_i386.inc} +{$I ..\..\Include\Simd\Poly1305\Poly1305BlocksBulkSse2Core_i386.inc} +{$ENDIF} +end; + {$ENDIF CRYPTOLIB_X86_SIMD} { TPoly1305X86Backend } @@ -195,12 +252,17 @@ class function TPoly1305X86Backend.TryInitPowerTable(var APowTable: TCryptoLibBy const AState: TPoly1305State): Boolean; begin {$IFDEF CRYPTOLIB_X86_SIMD} - case TCpuFeatures.X86.SelectSlot([TX86SimdLevel.AVX2]) of + case TCpuFeatures.X86.SelectSlot([TX86SimdLevel.AVX2, TX86SimdLevel.SSE2]) of TX86SimdLevel.AVX2: begin Poly1305Avx2InitPowerTable(APowTable, AState); Exit(True); end; + TX86SimdLevel.SSE2: + begin + Poly1305Sse2InitPowerTable(APowTable, AState); + Exit(True); + end; end; {$ENDIF} Result := False; @@ -209,26 +271,35 @@ class function TPoly1305X86Backend.TryInitPowerTable(var APowTable: TCryptoLibBy class function TPoly1305X86Backend.ProcessBulk(var AState: TPoly1305State; APowTable: PByte; const ABuf: TCryptoLibByteArray; AOff, ANumBlocks: Int32): Int32; {$IFDEF CRYPTOLIB_X86_SIMD} -const - // Minimum number of 16-byte blocks before the AVX2 4-way kernel pays off - // over the scalar block step; smaller batches go straight to the caller's - // scalar tail. - LMinBlocks = Int32(4); - // Number of 16-byte blocks consumed per AVX2 kernel iteration (one block - // per 64-bit lane of a 256-bit ymm); used to round the dispatch count - // down to a multiple supported by the kernel. - LLaneCount = Int32(4); var LSimdBlocks: Int32; {$ENDIF} begin {$IFDEF CRYPTOLIB_X86_SIMD} - if (APowTable <> nil) and (ANumBlocks >= LMinBlocks) then - begin - LSimdBlocks := ANumBlocks and not (LLaneCount - 1); - Poly1305BlocksBulkAvx2Core(@AState, APowTable, @ABuf[AOff], - NativeUInt(LSimdBlocks) * 16, 1); - Exit(LSimdBlocks); + if (APowTable = nil) then + Exit(0); + // The tier is re-selected here; SelectSlot is deterministic, so it matches the + // one TryInitPowerTable built the power table for. AVX2 consumes 4 blocks per + // iteration, SSE2 2; both need at least one lane's worth to pay off. + case TCpuFeatures.X86.SelectSlot([TX86SimdLevel.AVX2, TX86SimdLevel.SSE2]) of + TX86SimdLevel.AVX2: + begin + if ANumBlocks < 4 then + Exit(0); + LSimdBlocks := ANumBlocks and not 3; + Poly1305BlocksBulkAvx2Core(@AState, APowTable, @ABuf[AOff], + NativeUInt(LSimdBlocks) * 16, 1); + Exit(LSimdBlocks); + end; + TX86SimdLevel.SSE2: + begin + if ANumBlocks < 2 then + Exit(0); + LSimdBlocks := ANumBlocks and not 1; + Poly1305BlocksBulkSse2Core(@AState, APowTable, @ABuf[AOff], + NativeUInt(LSimdBlocks) * 16, 1); + Exit(LSimdBlocks); + end; end; {$ENDIF} Result := 0; diff --git a/CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkSse2Core_i386.inc b/CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkSse2Core_i386.inc new file mode 100644 index 00000000..7c288564 --- /dev/null +++ b/CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkSse2Core_i386.inc @@ -0,0 +1,508 @@ +// Poly1305 2-way SSE2 bulk MAC kernel (i386). +// ------------------------------------------------------------------- +// 2-lane (128-bit xmm) radix-2^26 narrowing of the 4-way AVX2 kernel: +// same 5x5 schoolbook multiply mod 2^130-5 (with the 5*r wraparound), +// 2 blocks per iteration against an r/r^2 power table, then a single +// pshufd-based horizontal fold of the 2 lanes. +// +// i386 has only xmm0..7 (no callee-saved xmm), so the accumulator +// H0..H4 and the transient products D0..D4 live in a 160-byte esp +// stack frame; xmm7 = mask26 and xmm6 = padbit stay resident. Every +// table/state access is an unaligned movdqu load/store (SSE memory- +// operand arithmetic would #GP on the non-16-aligned power table). +// +// On entry (after ClpSimdProc5Begin_i386.inc): +// ebx = ACtx (72-byte R/S/H/K state); esi = APowTable (160-byte r/r^2) +// edi = AInp; eax = ALen (multiple of 32, >= 32); ecx = APad (ignored) +// +// Power table: row j at [esi + 16*j]; rows 0..4 r-limbs [r2,r2,r2,r1], +// rows 5..8 s-limbs (5*r), row 9 pad. Bulk reads [+16*j] (broadcast r^2); +// tail reads [+16*j+4] ([r^2,r^1]). + + sub esp, 160 + // ---- Prologue: mask26 (xmm7), padbit (xmm6) ---- + db $66, $0F, $76, $FF // pcmpeqd xmm7, xmm7 + db $66, $0F, $73, $D7, $26 // psrlq xmm7, 38 + db $66, $0F, $76, $F6 // pcmpeqd xmm6, xmm6 + db $66, $0F, $73, $D6, $3F // psrlq xmm6, 63 + db $66, $0F, $73, $F6, $18 // psllq xmm6, 24 + // ---- Load H0..H4 (lane 0) into the stack frame ---- + db $66, $0F, $6E, $43, $24 // movd xmm0, dword ptr [ebx + 36] + db $F3, $0F, $7F, $04, $24 // movdqu [esp], xmm0 + db $66, $0F, $6E, $43, $28 // movd xmm0, dword ptr [ebx + 40] + db $F3, $0F, $7F, $44, $24, $10 // movdqu [esp + 16], xmm0 + db $66, $0F, $6E, $43, $2C // movd xmm0, dword ptr [ebx + 44] + db $F3, $0F, $7F, $44, $24, $20 // movdqu [esp + 32], xmm0 + db $66, $0F, $6E, $43, $30 // movd xmm0, dword ptr [ebx + 48] + db $F3, $0F, $7F, $44, $24, $30 // movdqu [esp + 48], xmm0 + db $66, $0F, $6E, $43, $34 // movd xmm0, dword ptr [ebx + 52] + db $F3, $0F, $7F, $44, $24, $40 // movdqu [esp + 64], xmm0 + // ---- Pre-loop: absorb first 2 blocks ---- + db $F3, $0F, $6F, $07 // movdqu xmm0, [edi] + db $F3, $0F, $6F, $4F, $10 // movdqu xmm1, [edi + 16] + add edi, 32 + db $66, $0F, $6F, $D0 // movdqa xmm2, xmm0 + db $66, $0F, $73, $DA, $06 // psrldq xmm2, 6 + db $66, $0F, $6F, $D9 // movdqa xmm3, xmm1 + db $66, $0F, $73, $DB, $06 // psrldq xmm3, 6 + db $66, $0F, $6F, $E0 // movdqa xmm4, xmm0 + db $66, $0F, $6D, $E1 // punpckhqdq xmm4, xmm1 + db $66, $0F, $6C, $C1 // punpcklqdq xmm0, xmm1 + db $66, $0F, $6C, $D3 // punpcklqdq xmm2, xmm3 + db $66, $0F, $6F, $DA // movdqa xmm3, xmm2 + db $66, $0F, $73, $D3, $1E // psrlq xmm3, 30 + db $66, $0F, $73, $D2, $04 // psrlq xmm2, 4 + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $73, $D4, $28 // psrlq xmm4, 40 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $66, $0F, $DB, $CF // pand xmm1, xmm7 + db $66, $0F, $DB, $D7 // pand xmm2, xmm7 + db $66, $0F, $DB, $DF // pand xmm3, xmm7 + db $66, $0F, $EB, $E6 // por xmm4, xmm6 + db $F3, $0F, $6F, $2C, $24 // movdqu xmm5, [esp] + db $66, $0F, $D4, $E8 // paddq xmm5, xmm0 + db $F3, $0F, $7F, $2C, $24 // movdqu [esp], xmm5 + db $F3, $0F, $6F, $6C, $24, $10 // movdqu xmm5, [esp + 16] + db $66, $0F, $D4, $E9 // paddq xmm5, xmm1 + db $F3, $0F, $7F, $6C, $24, $10 // movdqu [esp + 16], xmm5 + db $F3, $0F, $6F, $6C, $24, $20 // movdqu xmm5, [esp + 32] + db $66, $0F, $D4, $EA // paddq xmm5, xmm2 + db $F3, $0F, $7F, $6C, $24, $20 // movdqu [esp + 32], xmm5 + db $F3, $0F, $6F, $6C, $24, $30 // movdqu xmm5, [esp + 48] + db $66, $0F, $D4, $EB // paddq xmm5, xmm3 + db $F3, $0F, $7F, $6C, $24, $30 // movdqu [esp + 48], xmm5 + db $F3, $0F, $6F, $6C, $24, $40 // movdqu xmm5, [esp + 64] + db $66, $0F, $D4, $EC // paddq xmm5, xmm4 + db $F3, $0F, $7F, $6C, $24, $40 // movdqu [esp + 64], xmm5 + sub eax, 32 + jz @@poly1305_sse2_tail + +@@poly1305_sse2_loop: + // ---- Bulk: H *= r^2 (broadcast) ---- + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $F3, $0F, $6F, $4E, $40 // movdqu xmm1, [esi + 64] + db $66, $0F, $F4, $C1 // pmuludq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $10 // movdqu xmm1, [esp + 16] + db $F3, $0F, $6F, $56, $30 // movdqu xmm2, [esi + 48] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $20 // movdqu xmm1, [esp + 32] + db $F3, $0F, $6F, $56, $20 // movdqu xmm2, [esi + 32] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $30 // movdqu xmm1, [esp + 48] + db $F3, $0F, $6F, $56, $10 // movdqu xmm2, [esi + 16] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $40 // movdqu xmm1, [esp + 64] + db $F3, $0F, $6F, $16 // movdqu xmm2, [esi] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $84, $24, $90, $00, $00, $00 // movdqu [esp + 144], xmm0 + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $F3, $0F, $6F, $4E, $30 // movdqu xmm1, [esi + 48] + db $66, $0F, $F4, $C1 // pmuludq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $10 // movdqu xmm1, [esp + 16] + db $F3, $0F, $6F, $56, $20 // movdqu xmm2, [esi + 32] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $20 // movdqu xmm1, [esp + 32] + db $F3, $0F, $6F, $56, $10 // movdqu xmm2, [esi + 16] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $30 // movdqu xmm1, [esp + 48] + db $F3, $0F, $6F, $16 // movdqu xmm2, [esi] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $40 // movdqu xmm1, [esp + 64] + db $F3, $0F, $6F, $96, $80, $00, $00, $00 // movdqu xmm2, [esi + 128] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $84, $24, $80, $00, $00, $00 // movdqu [esp + 128], xmm0 + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $F3, $0F, $6F, $4E, $20 // movdqu xmm1, [esi + 32] + db $66, $0F, $F4, $C1 // pmuludq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $10 // movdqu xmm1, [esp + 16] + db $F3, $0F, $6F, $56, $10 // movdqu xmm2, [esi + 16] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $20 // movdqu xmm1, [esp + 32] + db $F3, $0F, $6F, $16 // movdqu xmm2, [esi] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $30 // movdqu xmm1, [esp + 48] + db $F3, $0F, $6F, $96, $80, $00, $00, $00 // movdqu xmm2, [esi + 128] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $40 // movdqu xmm1, [esp + 64] + db $F3, $0F, $6F, $56, $70 // movdqu xmm2, [esi + 112] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $44, $24, $70 // movdqu [esp + 112], xmm0 + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $F3, $0F, $6F, $4E, $10 // movdqu xmm1, [esi + 16] + db $66, $0F, $F4, $C1 // pmuludq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $10 // movdqu xmm1, [esp + 16] + db $F3, $0F, $6F, $16 // movdqu xmm2, [esi] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $20 // movdqu xmm1, [esp + 32] + db $F3, $0F, $6F, $96, $80, $00, $00, $00 // movdqu xmm2, [esi + 128] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $30 // movdqu xmm1, [esp + 48] + db $F3, $0F, $6F, $56, $70 // movdqu xmm2, [esi + 112] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $40 // movdqu xmm1, [esp + 64] + db $F3, $0F, $6F, $56, $60 // movdqu xmm2, [esi + 96] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $44, $24, $60 // movdqu [esp + 96], xmm0 + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $F3, $0F, $6F, $0E // movdqu xmm1, [esi] + db $66, $0F, $F4, $C1 // pmuludq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $10 // movdqu xmm1, [esp + 16] + db $F3, $0F, $6F, $96, $80, $00, $00, $00 // movdqu xmm2, [esi + 128] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $20 // movdqu xmm1, [esp + 32] + db $F3, $0F, $6F, $56, $70 // movdqu xmm2, [esi + 112] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $30 // movdqu xmm1, [esp + 48] + db $F3, $0F, $6F, $56, $60 // movdqu xmm2, [esi + 96] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $40 // movdqu xmm1, [esp + 64] + db $F3, $0F, $6F, $56, $50 // movdqu xmm2, [esi + 80] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $44, $24, $50 // movdqu [esp + 80], xmm0 + // ---- Lazy reduce D -> H ---- + db $F3, $0F, $6F, $44, $24, $50 // movdqu xmm0, [esp + 80] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $04, $24 // movdqu [esp], xmm0 + db $F3, $0F, $6F, $54, $24, $60 // movdqu xmm2, [esp + 96] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $54, $24, $60 // movdqu [esp + 96], xmm2 + db $F3, $0F, $6F, $44, $24, $60 // movdqu xmm0, [esp + 96] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $44, $24, $10 // movdqu [esp + 16], xmm0 + db $F3, $0F, $6F, $54, $24, $70 // movdqu xmm2, [esp + 112] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $54, $24, $70 // movdqu [esp + 112], xmm2 + db $F3, $0F, $6F, $44, $24, $70 // movdqu xmm0, [esp + 112] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $44, $24, $20 // movdqu [esp + 32], xmm0 + db $F3, $0F, $6F, $94, $24, $80, $00, $00, $00 // movdqu xmm2, [esp + 128] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $94, $24, $80, $00, $00, $00 // movdqu [esp + 128], xmm2 + db $F3, $0F, $6F, $84, $24, $80, $00, $00, $00 // movdqu xmm0, [esp + 128] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $44, $24, $30 // movdqu [esp + 48], xmm0 + db $F3, $0F, $6F, $94, $24, $90, $00, $00, $00 // movdqu xmm2, [esp + 144] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $94, $24, $90, $00, $00, $00 // movdqu [esp + 144], xmm2 + db $F3, $0F, $6F, $84, $24, $90, $00, $00, $00 // movdqu xmm0, [esp + 144] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $44, $24, $40 // movdqu [esp + 64], xmm0 + db $66, $0F, $6F, $D1 // movdqa xmm2, xmm1 + db $66, $0F, $73, $F2, $02 // psllq xmm2, 2 + db $66, $0F, $D4, $CA // paddq xmm1, xmm2 + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $04, $24 // movdqu [esp], xmm0 + db $F3, $0F, $6F, $54, $24, $10 // movdqu xmm2, [esp + 16] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $54, $24, $10 // movdqu [esp + 16], xmm2 + // ---- Absorb next 2 blocks ---- + db $F3, $0F, $6F, $07 // movdqu xmm0, [edi] + db $F3, $0F, $6F, $4F, $10 // movdqu xmm1, [edi + 16] + add edi, 32 + db $66, $0F, $6F, $D0 // movdqa xmm2, xmm0 + db $66, $0F, $73, $DA, $06 // psrldq xmm2, 6 + db $66, $0F, $6F, $D9 // movdqa xmm3, xmm1 + db $66, $0F, $73, $DB, $06 // psrldq xmm3, 6 + db $66, $0F, $6F, $E0 // movdqa xmm4, xmm0 + db $66, $0F, $6D, $E1 // punpckhqdq xmm4, xmm1 + db $66, $0F, $6C, $C1 // punpcklqdq xmm0, xmm1 + db $66, $0F, $6C, $D3 // punpcklqdq xmm2, xmm3 + db $66, $0F, $6F, $DA // movdqa xmm3, xmm2 + db $66, $0F, $73, $D3, $1E // psrlq xmm3, 30 + db $66, $0F, $73, $D2, $04 // psrlq xmm2, 4 + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $73, $D4, $28 // psrlq xmm4, 40 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $66, $0F, $DB, $CF // pand xmm1, xmm7 + db $66, $0F, $DB, $D7 // pand xmm2, xmm7 + db $66, $0F, $DB, $DF // pand xmm3, xmm7 + db $66, $0F, $EB, $E6 // por xmm4, xmm6 + db $F3, $0F, $6F, $2C, $24 // movdqu xmm5, [esp] + db $66, $0F, $D4, $E8 // paddq xmm5, xmm0 + db $F3, $0F, $7F, $2C, $24 // movdqu [esp], xmm5 + db $F3, $0F, $6F, $6C, $24, $10 // movdqu xmm5, [esp + 16] + db $66, $0F, $D4, $E9 // paddq xmm5, xmm1 + db $F3, $0F, $7F, $6C, $24, $10 // movdqu [esp + 16], xmm5 + db $F3, $0F, $6F, $6C, $24, $20 // movdqu xmm5, [esp + 32] + db $66, $0F, $D4, $EA // paddq xmm5, xmm2 + db $F3, $0F, $7F, $6C, $24, $20 // movdqu [esp + 32], xmm5 + db $F3, $0F, $6F, $6C, $24, $30 // movdqu xmm5, [esp + 48] + db $66, $0F, $D4, $EB // paddq xmm5, xmm3 + db $F3, $0F, $7F, $6C, $24, $30 // movdqu [esp + 48], xmm5 + db $F3, $0F, $6F, $6C, $24, $40 // movdqu xmm5, [esp + 64] + db $66, $0F, $D4, $EC // paddq xmm5, xmm4 + db $F3, $0F, $7F, $6C, $24, $40 // movdqu [esp + 64], xmm5 + sub eax, 32 + jnz @@poly1305_sse2_loop + +@@poly1305_sse2_tail: + // ---- Tail: H *= [r^2, r^1] (shifted table read) ---- + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $F3, $0F, $6F, $4E, $44 // movdqu xmm1, [esi + 68] + db $66, $0F, $F4, $C1 // pmuludq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $10 // movdqu xmm1, [esp + 16] + db $F3, $0F, $6F, $56, $34 // movdqu xmm2, [esi + 52] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $20 // movdqu xmm1, [esp + 32] + db $F3, $0F, $6F, $56, $24 // movdqu xmm2, [esi + 36] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $30 // movdqu xmm1, [esp + 48] + db $F3, $0F, $6F, $56, $14 // movdqu xmm2, [esi + 20] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $40 // movdqu xmm1, [esp + 64] + db $F3, $0F, $6F, $56, $04 // movdqu xmm2, [esi + 4] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $84, $24, $90, $00, $00, $00 // movdqu [esp + 144], xmm0 + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $F3, $0F, $6F, $4E, $34 // movdqu xmm1, [esi + 52] + db $66, $0F, $F4, $C1 // pmuludq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $10 // movdqu xmm1, [esp + 16] + db $F3, $0F, $6F, $56, $24 // movdqu xmm2, [esi + 36] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $20 // movdqu xmm1, [esp + 32] + db $F3, $0F, $6F, $56, $14 // movdqu xmm2, [esi + 20] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $30 // movdqu xmm1, [esp + 48] + db $F3, $0F, $6F, $56, $04 // movdqu xmm2, [esi + 4] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $40 // movdqu xmm1, [esp + 64] + db $F3, $0F, $6F, $96, $84, $00, $00, $00 // movdqu xmm2, [esi + 132] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $84, $24, $80, $00, $00, $00 // movdqu [esp + 128], xmm0 + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $F3, $0F, $6F, $4E, $24 // movdqu xmm1, [esi + 36] + db $66, $0F, $F4, $C1 // pmuludq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $10 // movdqu xmm1, [esp + 16] + db $F3, $0F, $6F, $56, $14 // movdqu xmm2, [esi + 20] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $20 // movdqu xmm1, [esp + 32] + db $F3, $0F, $6F, $56, $04 // movdqu xmm2, [esi + 4] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $30 // movdqu xmm1, [esp + 48] + db $F3, $0F, $6F, $96, $84, $00, $00, $00 // movdqu xmm2, [esi + 132] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $40 // movdqu xmm1, [esp + 64] + db $F3, $0F, $6F, $56, $74 // movdqu xmm2, [esi + 116] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $44, $24, $70 // movdqu [esp + 112], xmm0 + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $F3, $0F, $6F, $4E, $14 // movdqu xmm1, [esi + 20] + db $66, $0F, $F4, $C1 // pmuludq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $10 // movdqu xmm1, [esp + 16] + db $F3, $0F, $6F, $56, $04 // movdqu xmm2, [esi + 4] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $20 // movdqu xmm1, [esp + 32] + db $F3, $0F, $6F, $96, $84, $00, $00, $00 // movdqu xmm2, [esi + 132] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $30 // movdqu xmm1, [esp + 48] + db $F3, $0F, $6F, $56, $74 // movdqu xmm2, [esi + 116] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $40 // movdqu xmm1, [esp + 64] + db $F3, $0F, $6F, $56, $64 // movdqu xmm2, [esi + 100] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $44, $24, $60 // movdqu [esp + 96], xmm0 + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $F3, $0F, $6F, $4E, $04 // movdqu xmm1, [esi + 4] + db $66, $0F, $F4, $C1 // pmuludq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $10 // movdqu xmm1, [esp + 16] + db $F3, $0F, $6F, $96, $84, $00, $00, $00 // movdqu xmm2, [esi + 132] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $20 // movdqu xmm1, [esp + 32] + db $F3, $0F, $6F, $56, $74 // movdqu xmm2, [esi + 116] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $30 // movdqu xmm1, [esp + 48] + db $F3, $0F, $6F, $56, $64 // movdqu xmm2, [esi + 100] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $6F, $4C, $24, $40 // movdqu xmm1, [esp + 64] + db $F3, $0F, $6F, $56, $54 // movdqu xmm2, [esi + 84] + db $66, $0F, $F4, $CA // pmuludq xmm1, xmm2 + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $44, $24, $50 // movdqu [esp + 80], xmm0 + db $F3, $0F, $6F, $44, $24, $50 // movdqu xmm0, [esp + 80] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $04, $24 // movdqu [esp], xmm0 + db $F3, $0F, $6F, $54, $24, $60 // movdqu xmm2, [esp + 96] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $54, $24, $60 // movdqu [esp + 96], xmm2 + db $F3, $0F, $6F, $44, $24, $60 // movdqu xmm0, [esp + 96] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $44, $24, $10 // movdqu [esp + 16], xmm0 + db $F3, $0F, $6F, $54, $24, $70 // movdqu xmm2, [esp + 112] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $54, $24, $70 // movdqu [esp + 112], xmm2 + db $F3, $0F, $6F, $44, $24, $70 // movdqu xmm0, [esp + 112] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $44, $24, $20 // movdqu [esp + 32], xmm0 + db $F3, $0F, $6F, $94, $24, $80, $00, $00, $00 // movdqu xmm2, [esp + 128] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $94, $24, $80, $00, $00, $00 // movdqu [esp + 128], xmm2 + db $F3, $0F, $6F, $84, $24, $80, $00, $00, $00 // movdqu xmm0, [esp + 128] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $44, $24, $30 // movdqu [esp + 48], xmm0 + db $F3, $0F, $6F, $94, $24, $90, $00, $00, $00 // movdqu xmm2, [esp + 144] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $94, $24, $90, $00, $00, $00 // movdqu [esp + 144], xmm2 + db $F3, $0F, $6F, $84, $24, $90, $00, $00, $00 // movdqu xmm0, [esp + 144] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $44, $24, $40 // movdqu [esp + 64], xmm0 + db $66, $0F, $6F, $D1 // movdqa xmm2, xmm1 + db $66, $0F, $73, $F2, $02 // psllq xmm2, 2 + db $66, $0F, $D4, $CA // paddq xmm1, xmm2 + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $04, $24 // movdqu [esp], xmm0 + db $F3, $0F, $6F, $54, $24, $10 // movdqu xmm2, [esp + 16] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $54, $24, $10 // movdqu [esp + 16], xmm2 + // ---- Horizontal fold 2 lanes -> 1, final reduce, store ---- + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $66, $0F, $70, $C8, $4E // pshufd xmm1, xmm0, 0x4E + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $04, $24 // movdqu [esp], xmm0 + db $F3, $0F, $6F, $44, $24, $10 // movdqu xmm0, [esp + 16] + db $66, $0F, $70, $C8, $4E // pshufd xmm1, xmm0, 0x4E + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $44, $24, $10 // movdqu [esp + 16], xmm0 + db $F3, $0F, $6F, $44, $24, $20 // movdqu xmm0, [esp + 32] + db $66, $0F, $70, $C8, $4E // pshufd xmm1, xmm0, 0x4E + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $44, $24, $20 // movdqu [esp + 32], xmm0 + db $F3, $0F, $6F, $44, $24, $30 // movdqu xmm0, [esp + 48] + db $66, $0F, $70, $C8, $4E // pshufd xmm1, xmm0, 0x4E + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $44, $24, $30 // movdqu [esp + 48], xmm0 + db $F3, $0F, $6F, $44, $24, $40 // movdqu xmm0, [esp + 64] + db $66, $0F, $70, $C8, $4E // pshufd xmm1, xmm0, 0x4E + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $F3, $0F, $7F, $44, $24, $40 // movdqu [esp + 64], xmm0 + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $04, $24 // movdqu [esp], xmm0 + db $F3, $0F, $6F, $54, $24, $10 // movdqu xmm2, [esp + 16] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $54, $24, $10 // movdqu [esp + 16], xmm2 + db $F3, $0F, $6F, $44, $24, $10 // movdqu xmm0, [esp + 16] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $44, $24, $10 // movdqu [esp + 16], xmm0 + db $F3, $0F, $6F, $54, $24, $20 // movdqu xmm2, [esp + 32] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $54, $24, $20 // movdqu [esp + 32], xmm2 + db $F3, $0F, $6F, $44, $24, $20 // movdqu xmm0, [esp + 32] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $44, $24, $20 // movdqu [esp + 32], xmm0 + db $F3, $0F, $6F, $54, $24, $30 // movdqu xmm2, [esp + 48] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $54, $24, $30 // movdqu [esp + 48], xmm2 + db $F3, $0F, $6F, $44, $24, $30 // movdqu xmm0, [esp + 48] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $44, $24, $30 // movdqu [esp + 48], xmm0 + db $F3, $0F, $6F, $54, $24, $40 // movdqu xmm2, [esp + 64] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $54, $24, $40 // movdqu [esp + 64], xmm2 + db $F3, $0F, $6F, $44, $24, $40 // movdqu xmm0, [esp + 64] + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $44, $24, $40 // movdqu [esp + 64], xmm0 + db $66, $0F, $6F, $D1 // movdqa xmm2, xmm1 + db $66, $0F, $73, $F2, $02 // psllq xmm2, 2 + db $66, $0F, $D4, $CA // paddq xmm1, xmm2 + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $66, $0F, $D4, $C1 // paddq xmm0, xmm1 + db $66, $0F, $6F, $C8 // movdqa xmm1, xmm0 + db $66, $0F, $73, $D1, $1A // psrlq xmm1, 26 + db $66, $0F, $DB, $C7 // pand xmm0, xmm7 + db $F3, $0F, $7F, $04, $24 // movdqu [esp], xmm0 + db $F3, $0F, $6F, $54, $24, $10 // movdqu xmm2, [esp + 16] + db $66, $0F, $D4, $D1 // paddq xmm2, xmm1 + db $F3, $0F, $7F, $54, $24, $10 // movdqu [esp + 16], xmm2 + db $F3, $0F, $6F, $04, $24 // movdqu xmm0, [esp] + db $66, $0F, $7E, $43, $24 // movd dword ptr [ebx + 36], xmm0 + db $F3, $0F, $6F, $44, $24, $10 // movdqu xmm0, [esp + 16] + db $66, $0F, $7E, $43, $28 // movd dword ptr [ebx + 40], xmm0 + db $F3, $0F, $6F, $44, $24, $20 // movdqu xmm0, [esp + 32] + db $66, $0F, $7E, $43, $2C // movd dword ptr [ebx + 44], xmm0 + db $F3, $0F, $6F, $44, $24, $30 // movdqu xmm0, [esp + 48] + db $66, $0F, $7E, $43, $30 // movd dword ptr [ebx + 48], xmm0 + db $F3, $0F, $6F, $44, $24, $40 // movdqu xmm0, [esp + 64] + db $66, $0F, $7E, $43, $34 // movd dword ptr [ebx + 52], xmm0 + add esp, 160 + pop edi + pop esi + pop ebx diff --git a/CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkSse2Core_x86_64.inc b/CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkSse2Core_x86_64.inc new file mode 100644 index 00000000..e8172d0b --- /dev/null +++ b/CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkSse2Core_x86_64.inc @@ -0,0 +1,394 @@ +// Poly1305 2-way SSE2 bulk MAC kernel (x86-64). +// ------------------------------------------------------------------- +// 2-lane (128-bit xmm) radix-2^26 narrowing of the 4-way AVX2 kernel: +// same 5x5 schoolbook multiply mod 2^130-5 (with the 5*r wraparound), +// 2 blocks per iteration against an r/r^2 power table, then a single +// pshufd-based horizontal fold of the 2 lanes. Every instruction is +// db-encoded with its mnemonic beside it for broad assembler compatibility. +// +// On entry (after ClpSimdProc5Begin_x86_64.inc): +// rcx = ACtx (72-byte R/S/H/K state); rdx = APowTable (160-byte r/r^2) +// r8 = AInp; r9 = ALen (multiple of 32, >= 32); r10 = APad (ignored) +// +// Power table: row j at [rdx + 16*j]; rows 0..4 r-limbs [r2,r2,r2,r1], +// rows 5..8 s-limbs (5*r), row 9 pad. Bulk reads [+16*j] (broadcast r^2); +// tail reads [+16*j+4] ([r^2,r^1]). + +{$I ..\..\Include\Simd\Common\ClpSimdNonVolatileSave_x86_64.inc} + // ---- Prologue: mask26 (xmm5), padbit (xmm6) ---- + db $66, $0F, $76, $ED // pcmpeqd xmm5, xmm5 + db $66, $0F, $73, $D5, $26 // psrlq xmm5, 38 + db $66, $0F, $76, $F6 // pcmpeqd xmm6, xmm6 + db $66, $0F, $73, $D6, $3F // psrlq xmm6, 63 + db $66, $0F, $73, $F6, $18 // psllq xmm6, 24 + // ---- Load H0..H4 into lane 0 ---- + db $66, $0F, $6E, $41, $24 // movd xmm0, dword ptr [rcx + 36] + db $66, $0F, $6E, $49, $28 // movd xmm1, dword ptr [rcx + 40] + db $66, $0F, $6E, $51, $2C // movd xmm2, dword ptr [rcx + 44] + db $66, $0F, $6E, $59, $30 // movd xmm3, dword ptr [rcx + 48] + db $66, $0F, $6E, $61, $34 // movd xmm4, dword ptr [rcx + 52] + // ---- Pre-loop: absorb first 2 blocks ---- + db $F3, $45, $0F, $6F, $20 // movdqu xmm12, [r8] + db $F3, $45, $0F, $6F, $68, $10 // movdqu xmm13, [r8 + 16] + add r8, 32 + db $66, $45, $0F, $6F, $F4 // movdqa xmm14, xmm12 + db $66, $41, $0F, $73, $DE, $06 // psrldq xmm14, 6 + db $66, $45, $0F, $6F, $FD // movdqa xmm15, xmm13 + db $66, $41, $0F, $73, $DF, $06 // psrldq xmm15, 6 + db $66, $41, $0F, $6F, $FC // movdqa xmm7, xmm12 + db $66, $41, $0F, $6D, $FD // punpckhqdq xmm7, xmm13 + db $66, $45, $0F, $6C, $E5 // punpcklqdq xmm12, xmm13 + db $66, $45, $0F, $6C, $F7 // punpcklqdq xmm14, xmm15 + db $66, $45, $0F, $6F, $FE // movdqa xmm15, xmm14 + db $66, $41, $0F, $73, $D7, $1E // psrlq xmm15, 30 + db $66, $41, $0F, $73, $D6, $04 // psrlq xmm14, 4 + db $66, $45, $0F, $6F, $EC // movdqa xmm13, xmm12 + db $66, $41, $0F, $73, $D5, $1A // psrlq xmm13, 26 + db $66, $0F, $73, $D7, $28 // psrlq xmm7, 40 + db $66, $44, $0F, $DB, $E5 // pand xmm12, xmm5 + db $66, $44, $0F, $DB, $ED // pand xmm13, xmm5 + db $66, $44, $0F, $DB, $F5 // pand xmm14, xmm5 + db $66, $44, $0F, $DB, $FD // pand xmm15, xmm5 + db $66, $0F, $EB, $FE // por xmm7, xmm6 + db $66, $41, $0F, $D4, $C4 // paddq xmm0, xmm12 + db $66, $41, $0F, $D4, $CD // paddq xmm1, xmm13 + db $66, $41, $0F, $D4, $D6 // paddq xmm2, xmm14 + db $66, $41, $0F, $D4, $DF // paddq xmm3, xmm15 + db $66, $0F, $D4, $E7 // paddq xmm4, xmm7 + sub r9, 32 + jz @@poly1305_sse2_tail + +@@poly1305_sse2_loop: + // ---- Bulk: H *= r^2 (broadcast) ---- + db $66, $44, $0F, $6F, $D8 // movdqa xmm11, xmm0 + db $F3, $44, $0F, $6F, $6A, $40 // movdqu xmm13, [rdx + 64] + db $66, $45, $0F, $F4, $DD // pmuludq xmm11, xmm13 + db $66, $44, $0F, $6F, $E1 // movdqa xmm12, xmm1 + db $F3, $44, $0F, $6F, $6A, $30 // movdqu xmm13, [rdx + 48] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $DC // paddq xmm11, xmm12 + db $66, $44, $0F, $6F, $E2 // movdqa xmm12, xmm2 + db $F3, $44, $0F, $6F, $6A, $20 // movdqu xmm13, [rdx + 32] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $DC // paddq xmm11, xmm12 + db $66, $44, $0F, $6F, $E3 // movdqa xmm12, xmm3 + db $F3, $44, $0F, $6F, $6A, $10 // movdqu xmm13, [rdx + 16] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $DC // paddq xmm11, xmm12 + db $66, $44, $0F, $6F, $E4 // movdqa xmm12, xmm4 + db $F3, $44, $0F, $6F, $2A // movdqu xmm13, [rdx] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $DC // paddq xmm11, xmm12 + db $66, $44, $0F, $6F, $D0 // movdqa xmm10, xmm0 + db $F3, $44, $0F, $6F, $6A, $30 // movdqu xmm13, [rdx + 48] + db $66, $45, $0F, $F4, $D5 // pmuludq xmm10, xmm13 + db $66, $44, $0F, $6F, $E1 // movdqa xmm12, xmm1 + db $F3, $44, $0F, $6F, $6A, $20 // movdqu xmm13, [rdx + 32] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $D4 // paddq xmm10, xmm12 + db $66, $44, $0F, $6F, $E2 // movdqa xmm12, xmm2 + db $F3, $44, $0F, $6F, $6A, $10 // movdqu xmm13, [rdx + 16] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $D4 // paddq xmm10, xmm12 + db $66, $44, $0F, $6F, $E3 // movdqa xmm12, xmm3 + db $F3, $44, $0F, $6F, $2A // movdqu xmm13, [rdx] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $D4 // paddq xmm10, xmm12 + db $66, $44, $0F, $6F, $E4 // movdqa xmm12, xmm4 + db $F3, $44, $0F, $6F, $AA, $80, $00, $00, $00 // movdqu xmm13, [rdx + 128] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $D4 // paddq xmm10, xmm12 + db $66, $44, $0F, $6F, $C8 // movdqa xmm9, xmm0 + db $F3, $44, $0F, $6F, $6A, $20 // movdqu xmm13, [rdx + 32] + db $66, $45, $0F, $F4, $CD // pmuludq xmm9, xmm13 + db $66, $44, $0F, $6F, $E1 // movdqa xmm12, xmm1 + db $F3, $44, $0F, $6F, $6A, $10 // movdqu xmm13, [rdx + 16] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $CC // paddq xmm9, xmm12 + db $66, $44, $0F, $6F, $E2 // movdqa xmm12, xmm2 + db $F3, $44, $0F, $6F, $2A // movdqu xmm13, [rdx] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $CC // paddq xmm9, xmm12 + db $66, $44, $0F, $6F, $E3 // movdqa xmm12, xmm3 + db $F3, $44, $0F, $6F, $AA, $80, $00, $00, $00 // movdqu xmm13, [rdx + 128] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $CC // paddq xmm9, xmm12 + db $66, $44, $0F, $6F, $E4 // movdqa xmm12, xmm4 + db $F3, $44, $0F, $6F, $6A, $70 // movdqu xmm13, [rdx + 112] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $CC // paddq xmm9, xmm12 + db $66, $44, $0F, $6F, $C0 // movdqa xmm8, xmm0 + db $F3, $44, $0F, $6F, $6A, $10 // movdqu xmm13, [rdx + 16] + db $66, $45, $0F, $F4, $C5 // pmuludq xmm8, xmm13 + db $66, $44, $0F, $6F, $E1 // movdqa xmm12, xmm1 + db $F3, $44, $0F, $6F, $2A // movdqu xmm13, [rdx] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $C4 // paddq xmm8, xmm12 + db $66, $44, $0F, $6F, $E2 // movdqa xmm12, xmm2 + db $F3, $44, $0F, $6F, $AA, $80, $00, $00, $00 // movdqu xmm13, [rdx + 128] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $C4 // paddq xmm8, xmm12 + db $66, $44, $0F, $6F, $E3 // movdqa xmm12, xmm3 + db $F3, $44, $0F, $6F, $6A, $70 // movdqu xmm13, [rdx + 112] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $C4 // paddq xmm8, xmm12 + db $66, $44, $0F, $6F, $E4 // movdqa xmm12, xmm4 + db $F3, $44, $0F, $6F, $6A, $60 // movdqu xmm13, [rdx + 96] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $C4 // paddq xmm8, xmm12 + db $66, $0F, $6F, $F8 // movdqa xmm7, xmm0 + db $F3, $44, $0F, $6F, $2A // movdqu xmm13, [rdx] + db $66, $41, $0F, $F4, $FD // pmuludq xmm7, xmm13 + db $66, $44, $0F, $6F, $E1 // movdqa xmm12, xmm1 + db $F3, $44, $0F, $6F, $AA, $80, $00, $00, $00 // movdqu xmm13, [rdx + 128] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $41, $0F, $D4, $FC // paddq xmm7, xmm12 + db $66, $44, $0F, $6F, $E2 // movdqa xmm12, xmm2 + db $F3, $44, $0F, $6F, $6A, $70 // movdqu xmm13, [rdx + 112] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $41, $0F, $D4, $FC // paddq xmm7, xmm12 + db $66, $44, $0F, $6F, $E3 // movdqa xmm12, xmm3 + db $F3, $44, $0F, $6F, $6A, $60 // movdqu xmm13, [rdx + 96] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $41, $0F, $D4, $FC // paddq xmm7, xmm12 + db $66, $44, $0F, $6F, $E4 // movdqa xmm12, xmm4 + db $F3, $44, $0F, $6F, $6A, $50 // movdqu xmm13, [rdx + 80] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $41, $0F, $D4, $FC // paddq xmm7, xmm12 + // ---- Lazy reduce D -> H ---- + db $66, $44, $0F, $6F, $EF // movdqa xmm13, xmm7 + db $66, $41, $0F, $73, $D5, $1A // psrlq xmm13, 26 + db $66, $0F, $DB, $FD // pand xmm7, xmm5 + db $66, $0F, $6F, $C7 // movdqa xmm0, xmm7 + db $66, $45, $0F, $D4, $C5 // paddq xmm8, xmm13 + db $66, $45, $0F, $6F, $E8 // movdqa xmm13, xmm8 + db $66, $41, $0F, $73, $D5, $1A // psrlq xmm13, 26 + db $66, $44, $0F, $DB, $C5 // pand xmm8, xmm5 + db $66, $41, $0F, $6F, $C8 // movdqa xmm1, xmm8 + db $66, $45, $0F, $D4, $CD // paddq xmm9, xmm13 + db $66, $45, $0F, $6F, $E9 // movdqa xmm13, xmm9 + db $66, $41, $0F, $73, $D5, $1A // psrlq xmm13, 26 + db $66, $44, $0F, $DB, $CD // pand xmm9, xmm5 + db $66, $41, $0F, $6F, $D1 // movdqa xmm2, xmm9 + db $66, $45, $0F, $D4, $D5 // paddq xmm10, xmm13 + db $66, $45, $0F, $6F, $EA // movdqa xmm13, xmm10 + db $66, $41, $0F, $73, $D5, $1A // psrlq xmm13, 26 + db $66, $44, $0F, $DB, $D5 // pand xmm10, xmm5 + db $66, $41, $0F, $6F, $DA // movdqa xmm3, xmm10 + db $66, $45, $0F, $D4, $DD // paddq xmm11, xmm13 + db $66, $45, $0F, $6F, $EB // movdqa xmm13, xmm11 + db $66, $41, $0F, $73, $D5, $1A // psrlq xmm13, 26 + db $66, $44, $0F, $DB, $DD // pand xmm11, xmm5 + db $66, $41, $0F, $6F, $E3 // movdqa xmm4, xmm11 + db $66, $45, $0F, $6F, $E5 // movdqa xmm12, xmm13 + db $66, $41, $0F, $73, $F4, $02 // psllq xmm12, 2 + db $66, $45, $0F, $D4, $EC // paddq xmm13, xmm12 + db $66, $41, $0F, $D4, $C5 // paddq xmm0, xmm13 + db $66, $44, $0F, $6F, $E8 // movdqa xmm13, xmm0 + db $66, $41, $0F, $73, $D5, $1A // psrlq xmm13, 26 + db $66, $0F, $DB, $C5 // pand xmm0, xmm5 + db $66, $41, $0F, $D4, $CD // paddq xmm1, xmm13 + // ---- Absorb next 2 blocks ---- + db $F3, $45, $0F, $6F, $20 // movdqu xmm12, [r8] + db $F3, $45, $0F, $6F, $68, $10 // movdqu xmm13, [r8 + 16] + add r8, 32 + db $66, $45, $0F, $6F, $F4 // movdqa xmm14, xmm12 + db $66, $41, $0F, $73, $DE, $06 // psrldq xmm14, 6 + db $66, $45, $0F, $6F, $FD // movdqa xmm15, xmm13 + db $66, $41, $0F, $73, $DF, $06 // psrldq xmm15, 6 + db $66, $41, $0F, $6F, $FC // movdqa xmm7, xmm12 + db $66, $41, $0F, $6D, $FD // punpckhqdq xmm7, xmm13 + db $66, $45, $0F, $6C, $E5 // punpcklqdq xmm12, xmm13 + db $66, $45, $0F, $6C, $F7 // punpcklqdq xmm14, xmm15 + db $66, $45, $0F, $6F, $FE // movdqa xmm15, xmm14 + db $66, $41, $0F, $73, $D7, $1E // psrlq xmm15, 30 + db $66, $41, $0F, $73, $D6, $04 // psrlq xmm14, 4 + db $66, $45, $0F, $6F, $EC // movdqa xmm13, xmm12 + db $66, $41, $0F, $73, $D5, $1A // psrlq xmm13, 26 + db $66, $0F, $73, $D7, $28 // psrlq xmm7, 40 + db $66, $44, $0F, $DB, $E5 // pand xmm12, xmm5 + db $66, $44, $0F, $DB, $ED // pand xmm13, xmm5 + db $66, $44, $0F, $DB, $F5 // pand xmm14, xmm5 + db $66, $44, $0F, $DB, $FD // pand xmm15, xmm5 + db $66, $0F, $EB, $FE // por xmm7, xmm6 + db $66, $41, $0F, $D4, $C4 // paddq xmm0, xmm12 + db $66, $41, $0F, $D4, $CD // paddq xmm1, xmm13 + db $66, $41, $0F, $D4, $D6 // paddq xmm2, xmm14 + db $66, $41, $0F, $D4, $DF // paddq xmm3, xmm15 + db $66, $0F, $D4, $E7 // paddq xmm4, xmm7 + sub r9, 32 + jnz @@poly1305_sse2_loop + +@@poly1305_sse2_tail: + // ---- Tail: H *= [r^2, r^1] (shifted table read) ---- + db $66, $44, $0F, $6F, $D8 // movdqa xmm11, xmm0 + db $F3, $44, $0F, $6F, $6A, $44 // movdqu xmm13, [rdx + 68] + db $66, $45, $0F, $F4, $DD // pmuludq xmm11, xmm13 + db $66, $44, $0F, $6F, $E1 // movdqa xmm12, xmm1 + db $F3, $44, $0F, $6F, $6A, $34 // movdqu xmm13, [rdx + 52] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $DC // paddq xmm11, xmm12 + db $66, $44, $0F, $6F, $E2 // movdqa xmm12, xmm2 + db $F3, $44, $0F, $6F, $6A, $24 // movdqu xmm13, [rdx + 36] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $DC // paddq xmm11, xmm12 + db $66, $44, $0F, $6F, $E3 // movdqa xmm12, xmm3 + db $F3, $44, $0F, $6F, $6A, $14 // movdqu xmm13, [rdx + 20] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $DC // paddq xmm11, xmm12 + db $66, $44, $0F, $6F, $E4 // movdqa xmm12, xmm4 + db $F3, $44, $0F, $6F, $6A, $04 // movdqu xmm13, [rdx + 4] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $DC // paddq xmm11, xmm12 + db $66, $44, $0F, $6F, $D0 // movdqa xmm10, xmm0 + db $F3, $44, $0F, $6F, $6A, $34 // movdqu xmm13, [rdx + 52] + db $66, $45, $0F, $F4, $D5 // pmuludq xmm10, xmm13 + db $66, $44, $0F, $6F, $E1 // movdqa xmm12, xmm1 + db $F3, $44, $0F, $6F, $6A, $24 // movdqu xmm13, [rdx + 36] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $D4 // paddq xmm10, xmm12 + db $66, $44, $0F, $6F, $E2 // movdqa xmm12, xmm2 + db $F3, $44, $0F, $6F, $6A, $14 // movdqu xmm13, [rdx + 20] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $D4 // paddq xmm10, xmm12 + db $66, $44, $0F, $6F, $E3 // movdqa xmm12, xmm3 + db $F3, $44, $0F, $6F, $6A, $04 // movdqu xmm13, [rdx + 4] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $D4 // paddq xmm10, xmm12 + db $66, $44, $0F, $6F, $E4 // movdqa xmm12, xmm4 + db $F3, $44, $0F, $6F, $AA, $84, $00, $00, $00 // movdqu xmm13, [rdx + 132] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $D4 // paddq xmm10, xmm12 + db $66, $44, $0F, $6F, $C8 // movdqa xmm9, xmm0 + db $F3, $44, $0F, $6F, $6A, $24 // movdqu xmm13, [rdx + 36] + db $66, $45, $0F, $F4, $CD // pmuludq xmm9, xmm13 + db $66, $44, $0F, $6F, $E1 // movdqa xmm12, xmm1 + db $F3, $44, $0F, $6F, $6A, $14 // movdqu xmm13, [rdx + 20] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $CC // paddq xmm9, xmm12 + db $66, $44, $0F, $6F, $E2 // movdqa xmm12, xmm2 + db $F3, $44, $0F, $6F, $6A, $04 // movdqu xmm13, [rdx + 4] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $CC // paddq xmm9, xmm12 + db $66, $44, $0F, $6F, $E3 // movdqa xmm12, xmm3 + db $F3, $44, $0F, $6F, $AA, $84, $00, $00, $00 // movdqu xmm13, [rdx + 132] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $CC // paddq xmm9, xmm12 + db $66, $44, $0F, $6F, $E4 // movdqa xmm12, xmm4 + db $F3, $44, $0F, $6F, $6A, $74 // movdqu xmm13, [rdx + 116] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $CC // paddq xmm9, xmm12 + db $66, $44, $0F, $6F, $C0 // movdqa xmm8, xmm0 + db $F3, $44, $0F, $6F, $6A, $14 // movdqu xmm13, [rdx + 20] + db $66, $45, $0F, $F4, $C5 // pmuludq xmm8, xmm13 + db $66, $44, $0F, $6F, $E1 // movdqa xmm12, xmm1 + db $F3, $44, $0F, $6F, $6A, $04 // movdqu xmm13, [rdx + 4] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $C4 // paddq xmm8, xmm12 + db $66, $44, $0F, $6F, $E2 // movdqa xmm12, xmm2 + db $F3, $44, $0F, $6F, $AA, $84, $00, $00, $00 // movdqu xmm13, [rdx + 132] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $C4 // paddq xmm8, xmm12 + db $66, $44, $0F, $6F, $E3 // movdqa xmm12, xmm3 + db $F3, $44, $0F, $6F, $6A, $74 // movdqu xmm13, [rdx + 116] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $C4 // paddq xmm8, xmm12 + db $66, $44, $0F, $6F, $E4 // movdqa xmm12, xmm4 + db $F3, $44, $0F, $6F, $6A, $64 // movdqu xmm13, [rdx + 100] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $45, $0F, $D4, $C4 // paddq xmm8, xmm12 + db $66, $0F, $6F, $F8 // movdqa xmm7, xmm0 + db $F3, $44, $0F, $6F, $6A, $04 // movdqu xmm13, [rdx + 4] + db $66, $41, $0F, $F4, $FD // pmuludq xmm7, xmm13 + db $66, $44, $0F, $6F, $E1 // movdqa xmm12, xmm1 + db $F3, $44, $0F, $6F, $AA, $84, $00, $00, $00 // movdqu xmm13, [rdx + 132] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $41, $0F, $D4, $FC // paddq xmm7, xmm12 + db $66, $44, $0F, $6F, $E2 // movdqa xmm12, xmm2 + db $F3, $44, $0F, $6F, $6A, $74 // movdqu xmm13, [rdx + 116] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $41, $0F, $D4, $FC // paddq xmm7, xmm12 + db $66, $44, $0F, $6F, $E3 // movdqa xmm12, xmm3 + db $F3, $44, $0F, $6F, $6A, $64 // movdqu xmm13, [rdx + 100] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $41, $0F, $D4, $FC // paddq xmm7, xmm12 + db $66, $44, $0F, $6F, $E4 // movdqa xmm12, xmm4 + db $F3, $44, $0F, $6F, $6A, $54 // movdqu xmm13, [rdx + 84] + db $66, $45, $0F, $F4, $E5 // pmuludq xmm12, xmm13 + db $66, $41, $0F, $D4, $FC // paddq xmm7, xmm12 + db $66, $44, $0F, $6F, $EF // movdqa xmm13, xmm7 + db $66, $41, $0F, $73, $D5, $1A // psrlq xmm13, 26 + db $66, $0F, $DB, $FD // pand xmm7, xmm5 + db $66, $0F, $6F, $C7 // movdqa xmm0, xmm7 + db $66, $45, $0F, $D4, $C5 // paddq xmm8, xmm13 + db $66, $45, $0F, $6F, $E8 // movdqa xmm13, xmm8 + db $66, $41, $0F, $73, $D5, $1A // psrlq xmm13, 26 + db $66, $44, $0F, $DB, $C5 // pand xmm8, xmm5 + db $66, $41, $0F, $6F, $C8 // movdqa xmm1, xmm8 + db $66, $45, $0F, $D4, $CD // paddq xmm9, xmm13 + db $66, $45, $0F, $6F, $E9 // movdqa xmm13, xmm9 + db $66, $41, $0F, $73, $D5, $1A // psrlq xmm13, 26 + db $66, $44, $0F, $DB, $CD // pand xmm9, xmm5 + db $66, $41, $0F, $6F, $D1 // movdqa xmm2, xmm9 + db $66, $45, $0F, $D4, $D5 // paddq xmm10, xmm13 + db $66, $45, $0F, $6F, $EA // movdqa xmm13, xmm10 + db $66, $41, $0F, $73, $D5, $1A // psrlq xmm13, 26 + db $66, $44, $0F, $DB, $D5 // pand xmm10, xmm5 + db $66, $41, $0F, $6F, $DA // movdqa xmm3, xmm10 + db $66, $45, $0F, $D4, $DD // paddq xmm11, xmm13 + db $66, $45, $0F, $6F, $EB // movdqa xmm13, xmm11 + db $66, $41, $0F, $73, $D5, $1A // psrlq xmm13, 26 + db $66, $44, $0F, $DB, $DD // pand xmm11, xmm5 + db $66, $41, $0F, $6F, $E3 // movdqa xmm4, xmm11 + db $66, $45, $0F, $6F, $E5 // movdqa xmm12, xmm13 + db $66, $41, $0F, $73, $F4, $02 // psllq xmm12, 2 + db $66, $45, $0F, $D4, $EC // paddq xmm13, xmm12 + db $66, $41, $0F, $D4, $C5 // paddq xmm0, xmm13 + db $66, $44, $0F, $6F, $E8 // movdqa xmm13, xmm0 + db $66, $41, $0F, $73, $D5, $1A // psrlq xmm13, 26 + db $66, $0F, $DB, $C5 // pand xmm0, xmm5 + db $66, $41, $0F, $D4, $CD // paddq xmm1, xmm13 + // ---- Horizontal fold 2 lanes -> 1, final reduce, store ---- + db $66, $0F, $70, $F8, $4E // pshufd xmm7, xmm0, 0x4E + db $66, $0F, $D4, $C7 // paddq xmm0, xmm7 + db $66, $0F, $70, $F9, $4E // pshufd xmm7, xmm1, 0x4E + db $66, $0F, $D4, $CF // paddq xmm1, xmm7 + db $66, $0F, $70, $FA, $4E // pshufd xmm7, xmm2, 0x4E + db $66, $0F, $D4, $D7 // paddq xmm2, xmm7 + db $66, $0F, $70, $FB, $4E // pshufd xmm7, xmm3, 0x4E + db $66, $0F, $D4, $DF // paddq xmm3, xmm7 + db $66, $0F, $70, $FC, $4E // pshufd xmm7, xmm4, 0x4E + db $66, $0F, $D4, $E7 // paddq xmm4, xmm7 + db $66, $0F, $6F, $F8 // movdqa xmm7, xmm0 + db $66, $0F, $73, $D7, $1A // psrlq xmm7, 26 + db $66, $0F, $DB, $C5 // pand xmm0, xmm5 + db $66, $0F, $D4, $CF // paddq xmm1, xmm7 + db $66, $0F, $6F, $F9 // movdqa xmm7, xmm1 + db $66, $0F, $73, $D7, $1A // psrlq xmm7, 26 + db $66, $0F, $DB, $CD // pand xmm1, xmm5 + db $66, $0F, $D4, $D7 // paddq xmm2, xmm7 + db $66, $0F, $6F, $FA // movdqa xmm7, xmm2 + db $66, $0F, $73, $D7, $1A // psrlq xmm7, 26 + db $66, $0F, $DB, $D5 // pand xmm2, xmm5 + db $66, $0F, $D4, $DF // paddq xmm3, xmm7 + db $66, $0F, $6F, $FB // movdqa xmm7, xmm3 + db $66, $0F, $73, $D7, $1A // psrlq xmm7, 26 + db $66, $0F, $DB, $DD // pand xmm3, xmm5 + db $66, $0F, $D4, $E7 // paddq xmm4, xmm7 + db $66, $0F, $6F, $FC // movdqa xmm7, xmm4 + db $66, $0F, $73, $D7, $1A // psrlq xmm7, 26 + db $66, $0F, $DB, $E5 // pand xmm4, xmm5 + db $66, $44, $0F, $6F, $E7 // movdqa xmm12, xmm7 + db $66, $41, $0F, $73, $F4, $02 // psllq xmm12, 2 + db $66, $41, $0F, $D4, $FC // paddq xmm7, xmm12 + db $66, $0F, $D4, $C7 // paddq xmm0, xmm7 + db $66, $0F, $6F, $F8 // movdqa xmm7, xmm0 + db $66, $0F, $73, $D7, $1A // psrlq xmm7, 26 + db $66, $0F, $DB, $C5 // pand xmm0, xmm5 + db $66, $0F, $D4, $CF // paddq xmm1, xmm7 + db $66, $0F, $7E, $41, $24 // movd dword ptr [rcx + 36], xmm0 + db $66, $0F, $7E, $49, $28 // movd dword ptr [rcx + 40], xmm1 + db $66, $0F, $7E, $51, $2C // movd dword ptr [rcx + 44], xmm2 + db $66, $0F, $7E, $59, $30 // movd dword ptr [rcx + 48], xmm3 + db $66, $0F, $7E, $61, $34 // movd dword ptr [rcx + 52], xmm4 +{$I ..\..\Include\Simd\Common\ClpSimdNonVolatileRestore_x86_64.inc} From 768aafd49a237ba5cb8e879770796db1ae420e71 Mon Sep 17 00:00:00 2001 From: Ugochukwu Mmaduekwe Date: Thu, 9 Jul 2026 21:32:39 +0100 Subject: [PATCH 5/6] Restructure the AVX2 Poly1305 bulk carry-reduce (x86_64 two-chain) - x86_64: the bulk-loop carry-reduce is restructured into two interleaved chains (low D0->D1->D2->D3->H4, high D3->D4->H0->H1) to shorten the serial critical path. Measured ~+2.5% MAC / ~+2% AEAD; the run-once tail and final reduces stay serial. - i386: the reduce stays serial. The two-chain schedule was benched ~4-12% SLOWER on i386 -- its 8-ymm register file (D0..D4 plus an H backup spill to a 320-byte esp frame, and the multiply spills each accumulator per term) is throughput-bound, and the second carry temp would clobber padbit, forcing a rebuild each iteration. Both arches emit identical MACs. Both AVX2 kernels are re-emitted with canonical minimal-displacement VEX encodings (~20% fewer bytes than before) and plain mnemonic comments. Verified by KAT on both arches plus a displacement-insensitive byte diff against the previous kernels: i386 matches instruction-for-instruction; x86_64 differs only in the reduce and in disp widths. --- .../Poly1305BlocksBulkAvx2Core_i386.inc | 744 ++++++++---------- .../Poly1305BlocksBulkAvx2Core_x86_64.inc | 572 ++++++-------- 2 files changed, 597 insertions(+), 719 deletions(-) diff --git a/CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkAvx2Core_i386.inc b/CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkAvx2Core_i386.inc index 851e1b50..89324967 100644 --- a/CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkAvx2Core_i386.inc +++ b/CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkAvx2Core_i386.inc @@ -1,417 +1,351 @@ // Poly1305 4-way AVX2 bulk MAC kernel (i386). // ------------------------------------------------------------------- -// Algorithm: Goll-Gueron 2015 / Polyakov OpenSSL `poly1305_blocks_avx2`. -// Sibling of the x86-64 kernel; same 4-way design, same precomputed -// r^1..r^4 power table consumed at row offset (broadcast r^4 in the -// bulk loop) and row offset+4 (shifted [r^1,r^2,r^3,r^4] in the tail -// iteration). The Pascal dispatcher rounds the SIMD count down to a -// multiple of 4 and forwards 0..3 leftover blocks to the scalar path. -// -// VEX-encoded AVX2 instructions are db-encoded for broad assembler compatibility. -// Each db line carries a mnemonic comment. The encoding uses ymm0..ymm7 only -// (i386 has no ymm8..ymm15) so all VEX prefixes are 2-byte / 3-byte -// without REX.{R,X,B}; the bytes of the inner kernel are therefore -// identical to the equivalent ymm0..ymm7 sequences in the x86-64 -// sibling - only the base register names change to match the i386 -// argument map. +// Goll-Gueron / Polyakov: 4 blocks per iteration in 4 ymm lanes against an +// r^1..r^4 power table (320 bytes, 32-byte rows). radix-2^26 schoolbook +// multiply mod 2^130-5 (5*r wraparound); VEX tolerates unaligned memory so +// the table is read straight into vpmuludq. The bulk-loop carry-reduce uses +// the carry-reduce stays serial: i386 has only ymm0..7, and the two-chain +// schedule the x86-64 kernel uses needs a second carry temp that would +// clobber padbit (rebuild each iter) - measured slower on this +// throughput-bound, spill-heavy loop. D0..D4 and an H backup live in a +// 320-byte esp frame; the multiply spills each product accumulator per term. // // On entry (after ClpSimdProc5Begin_i386.inc): -// ebx = ACtx (PTPoly1305State; 72-byte R/S/H/K record) -// esi = APowTable (PByte; 320-byte 10x8 power table; layout below) -// edi = AInp (PByte) -// eax = ALen (NativeUInt; multiple of 64; >= 64) -// ecx = APad (always 1; ignored - padbit unconditional in bulk) -// -// TPoly1305State byte offsets (no SIMD member): -// R0..R4 : 0..16 (5 dwords) -// S1..S4 : 20..32 (4 dwords) -// H0..H4 : 36..52 (5 dwords) <- loaded into ymm0..ymm4 lane 0 -// K0..K3 : 56..68 (4 dwords; not read by this kernel) -// -// Power-table byte offsets (separate 320-byte buffer; esi-based loads): -// row j at [esi + 32*j]; bulk loop reads at row offset (broadcast -// r^4), tail iteration reads at row offset+4 (shifted [r^4,r^3,r^2,r^1]). -// Row 0..4 = r-limbs 0..4; row 5..8 = s-limbs 1..4 (s = 5*r); row 9 pad. +// ebx = ACtx (72-byte R/S/H/K state); esi = APowTable (320-byte r^1..r^4) +// edi = AInp; eax = ALen (multiple of 64, >= 64); ecx = APad (ignored) // -// Register allocation (uses ymm0..ymm7 only): -// ymm0..ymm4 : H0..H4 (4-lane radix-2^26 accumulator) -// ymm5 : mask26 (0x3FFFFFF per 64-bit lane low half) -// ymm6 : padbit (0x1000000 per 64-bit lane low half) -// ymm7 : scratch (D0..D4 / M0..M4 transient via stack spills) -// -// Stack frame (320 bytes): -// [esp + 0..159] = D0..D4 (5 x 32 bytes; product accumulators) -// [esp + 160..319] = H backup (5 x 32 bytes; spilled while loading M) +// Power table: row j at [esi + 32*j]; rows 0..4 r-limbs, rows 5..8 s-limbs +// (5*r), row 9 pad. Bulk reads [+32*j] (broadcast r^4); tail reads +// [+32*j+4] ([r^4,r^3,r^2,r^1]). sub esp, 320 - - // ---- Prologue: build mask26 (ymm5) and padbit (ymm6) constants ---- - db $C5, $D5, $76, $ED // vpcmpeqd ymm5, ymm5, ymm5 - db $C5, $D5, $73, $D5, $26 // vpsrlq ymm5, ymm5, 38 ; mask26 - db $C5, $CD, $76, $F6 // vpcmpeqd ymm6, ymm6, ymm6 - db $C5, $CD, $73, $D6, $3F // vpsrlq ymm6, ymm6, 63 - db $C5, $CD, $73, $F6, $18 // vpsllq ymm6, ymm6, 24 ; padbit = 1<<24 - - // ---- Load h0..h4 from ctx into lane 0 of ymm0..ymm4 ---- - db $C5, $F9, $6E, $43, $24 // vmovd xmm0, dword ptr [ebx + 36] ; H0 - db $C5, $F9, $6E, $4B, $28 // vmovd xmm1, dword ptr [ebx + 40] ; H1 - db $C5, $F9, $6E, $53, $2C // vmovd xmm2, dword ptr [ebx + 44] ; H2 - db $C5, $F9, $6E, $5B, $30 // vmovd xmm3, dword ptr [ebx + 48] ; H3 - db $C5, $F9, $6E, $63, $34 // vmovd xmm4, dword ptr [ebx + 52] ; H4 - - // ---- Pre-loop: spill H, load+decompress 4 blocks, absorb H back ---- - db $C5, $FE, $7F, $84, $24, $A0, $00, $00, $00 // vmovdqu ymmword ptr [esp + 160], ymm0 - db $C5, $FE, $7F, $8C, $24, $C0, $00, $00, $00 // vmovdqu ymmword ptr [esp + 192], ymm1 - db $C5, $FE, $7F, $94, $24, $E0, $00, $00, $00 // vmovdqu ymmword ptr [esp + 224], ymm2 - db $C5, $FE, $7F, $9C, $24, $00, $01, $00, $00 // vmovdqu ymmword ptr [esp + 256], ymm3 - db $C5, $FE, $7F, $A4, $24, $20, $01, $00, $00 // vmovdqu ymmword ptr [esp + 288], ymm4 - - db $C5, $FA, $6F, $07 // vmovdqu xmm0, xmmword ptr [edi] - db $C5, $FA, $6F, $4F, $10 // vmovdqu xmm1, xmmword ptr [edi + 16] - db $C4, $E3, $7D, $38, $47, $20, $01 // vinserti128 ymm0, ymm0, xmmword ptr [edi + 32], 1 - db $C4, $E3, $75, $38, $4F, $30, $01 // vinserti128 ymm1, ymm1, xmmword ptr [edi + 48], 1 - add edi, 64 - - // Decompress 4 blocks into limbs M0..M4 (ymm0, ymm1, ymm2, ymm3, ymm4) - db $C5, $ED, $73, $D8, $06 // vpsrldq ymm2, ymm0, 6 - db $C5, $E5, $73, $D9, $06 // vpsrldq ymm3, ymm1, 6 - db $C5, $FD, $6D, $E1 // vpunpckhqdq ymm4, ymm0, ymm1 ; T4 (high 64) - db $C5, $FD, $6C, $C1 // vpunpcklqdq ymm0, ymm0, ymm1 ; T0 (low 64) - db $C5, $ED, $6C, $D3 // vpunpcklqdq ymm2, ymm2, ymm3 ; T2 (limbs 2/3) - db $C5, $E5, $73, $D2, $1E // vpsrlq ymm3, ymm2, 30 ; limb3 raw - db $C5, $ED, $73, $D2, $04 // vpsrlq ymm2, ymm2, 4 ; limb2 raw - db $C5, $F5, $73, $D0, $1A // vpsrlq ymm1, ymm0, 26 ; limb1 raw - db $C5, $DD, $73, $D4, $28 // vpsrlq ymm4, ymm4, 40 ; limb4 raw - db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 ; M0 - db $C5, $F5, $DB, $CD // vpand ymm1, ymm1, ymm5 ; M1 - db $C5, $ED, $DB, $D5 // vpand ymm2, ymm2, ymm5 ; M2 - db $C5, $E5, $DB, $DD // vpand ymm3, ymm3, ymm5 ; M3 - db $C5, $DD, $EB, $E6 // vpor ymm4, ymm4, ymm6 ; M4 |= padbit - - // Absorb: H += M (H reload from stack since it was spilled) - db $C5, $FD, $D4, $84, $24, $A0, $00, $00, $00 // vpaddq ymm0, ymm0, ymmword ptr [esp + 160] - db $C5, $F5, $D4, $8C, $24, $C0, $00, $00, $00 // vpaddq ymm1, ymm1, ymmword ptr [esp + 192] - db $C5, $ED, $D4, $94, $24, $E0, $00, $00, $00 // vpaddq ymm2, ymm2, ymmword ptr [esp + 224] - db $C5, $E5, $D4, $9C, $24, $00, $01, $00, $00 // vpaddq ymm3, ymm3, ymmword ptr [esp + 256] - db $C5, $DD, $D4, $A4, $24, $20, $01, $00, $00 // vpaddq ymm4, ymm4, ymmword ptr [esp + 288] - - sub eax, 64 - jz @@poly1305_avx2_i386_tail + // ---- Prologue: mask26 (ymm5), padbit (ymm6) ---- + db $C5, $D5, $76, $ED // vpcmpeqd ymm5, ymm5, ymm5 + db $C5, $D5, $73, $D5, $26 // vpsrlq ymm5, ymm5, 38 + db $C5, $CD, $76, $F6 // vpcmpeqd ymm6, ymm6, ymm6 + db $C5, $CD, $73, $D6, $3F // vpsrlq ymm6, ymm6, 63 + db $C5, $CD, $73, $F6, $18 // vpsllq ymm6, ymm6, 24 + // ---- Load H0..H4 into lane 0 ---- + db $C5, $F9, $6E, $43, $24 // vmovd xmm0, dword ptr [ebx + 36] + db $C5, $F9, $6E, $4B, $28 // vmovd xmm1, dword ptr [ebx + 40] + db $C5, $F9, $6E, $53, $2C // vmovd xmm2, dword ptr [ebx + 44] + db $C5, $F9, $6E, $5B, $30 // vmovd xmm3, dword ptr [ebx + 48] + db $C5, $F9, $6E, $63, $34 // vmovd xmm4, dword ptr [ebx + 52] + // ---- Pre-loop: spill H, absorb first 4 blocks ---- + db $C5, $FE, $7F, $84, $24, $A0, $00, $00, $00 // vmovdqu [esp + 160], ymm0 + db $C5, $FE, $7F, $8C, $24, $C0, $00, $00, $00 // vmovdqu [esp + 192], ymm1 + db $C5, $FE, $7F, $94, $24, $E0, $00, $00, $00 // vmovdqu [esp + 224], ymm2 + db $C5, $FE, $7F, $9C, $24, $00, $01, $00, $00 // vmovdqu [esp + 256], ymm3 + db $C5, $FE, $7F, $A4, $24, $20, $01, $00, $00 // vmovdqu [esp + 288], ymm4 + db $C5, $FA, $6F, $07 // vmovdqu xmm0, [edi] + db $C5, $FA, $6F, $4F, $10 // vmovdqu xmm1, [edi + 16] + db $C4, $E3, $7D, $38, $47, $20, $01 // vinserti128 ymm0, ymm0, [edi + 32], 1 + db $C4, $E3, $75, $38, $4F, $30, $01 // vinserti128 ymm1, ymm1, [edi + 48], 1 + add edi, 64 + db $C5, $ED, $73, $D8, $06 // vpsrldq ymm2, ymm0, 6 + db $C5, $E5, $73, $D9, $06 // vpsrldq ymm3, ymm1, 6 + db $C5, $FD, $6D, $E1 // vpunpckhqdq ymm4, ymm0, ymm1 + db $C5, $FD, $6C, $C1 // vpunpcklqdq ymm0, ymm0, ymm1 + db $C5, $ED, $6C, $D3 // vpunpcklqdq ymm2, ymm2, ymm3 + db $C5, $E5, $73, $D2, $1E // vpsrlq ymm3, ymm2, 30 + db $C5, $ED, $73, $D2, $04 // vpsrlq ymm2, ymm2, 4 + db $C5, $F5, $73, $D0, $1A // vpsrlq ymm1, ymm0, 26 + db $C5, $DD, $73, $D4, $28 // vpsrlq ymm4, ymm4, 40 + db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 + db $C5, $F5, $DB, $CD // vpand ymm1, ymm1, ymm5 + db $C5, $ED, $DB, $D5 // vpand ymm2, ymm2, ymm5 + db $C5, $E5, $DB, $DD // vpand ymm3, ymm3, ymm5 + db $C5, $DD, $EB, $E6 // vpor ymm4, ymm4, ymm6 + db $C5, $FD, $D4, $84, $24, $A0, $00, $00, $00 // vpaddq ymm0, ymm0, [esp + 160] + db $C5, $F5, $D4, $8C, $24, $C0, $00, $00, $00 // vpaddq ymm1, ymm1, [esp + 192] + db $C5, $ED, $D4, $94, $24, $E0, $00, $00, $00 // vpaddq ymm2, ymm2, [esp + 224] + db $C5, $E5, $D4, $9C, $24, $00, $01, $00, $00 // vpaddq ymm3, ymm3, [esp + 256] + db $C5, $DD, $D4, $A4, $24, $20, $01, $00, $00 // vpaddq ymm4, ymm4, [esp + 288] + sub eax, 64 + jz @@poly1305_avx2_i386_tail @@poly1305_avx2_i386_loop: - // ---- Bulk multiply: H *= r^4 (broadcast row form, base offset +0) ---- - // D4 spilled at [esp + 128] - db $C5, $FD, $F4, $BE, $80, $00, $00, $00 // vpmuludq ymm7, ymm0, ymmword ptr [esi + 128] ; H0 * R4 - db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu ymmword ptr [esp + 128], ymm7 - db $C5, $F5, $F4, $BE, $60, $00, $00, $00 // vpmuludq ymm7, ymm1, ymmword ptr [esi + 96] ; H1 * R3 - db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, ymmword ptr [esp + 128] - db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu ymmword ptr [esp + 128], ymm7 - db $C5, $ED, $F4, $BE, $40, $00, $00, $00 // vpmuludq ymm7, ymm2, ymmword ptr [esi + 64] ; H2 * R2 - db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, ymmword ptr [esp + 128] - db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu ymmword ptr [esp + 128], ymm7 - db $C5, $E5, $F4, $7E, $20 // vpmuludq ymm7, ymm3, ymmword ptr [esi + 32] ; H3 * R1 - db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, ymmword ptr [esp + 128] - db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu ymmword ptr [esp + 128], ymm7 - db $C5, $DD, $F4, $7E, $00 // vpmuludq ymm7, ymm4, ymmword ptr [esi] ; H4 * R0 - db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, ymmword ptr [esp + 128] - db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu ymmword ptr [esp + 128], ymm7 - - // D3 spilled at [esp + 96] - db $C5, $FD, $F4, $BE, $60, $00, $00, $00 // vpmuludq ymm7, ymm0, ymmword ptr [esi + 96] - db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu ymmword ptr [esp + 96], ymm7 - db $C5, $F5, $F4, $BE, $40, $00, $00, $00 // vpmuludq ymm7, ymm1, ymmword ptr [esi + 64] - db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, ymmword ptr [esp + 96] - db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu ymmword ptr [esp + 96], ymm7 - db $C5, $ED, $F4, $7E, $20 // vpmuludq ymm7, ymm2, ymmword ptr [esi + 32] - db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, ymmword ptr [esp + 96] - db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu ymmword ptr [esp + 96], ymm7 - db $C5, $E5, $F4, $7E, $00 // vpmuludq ymm7, ymm3, ymmword ptr [esi] - db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, ymmword ptr [esp + 96] - db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu ymmword ptr [esp + 96], ymm7 - db $C5, $DD, $F4, $BE, $00, $01, $00, $00 // vpmuludq ymm7, ymm4, ymmword ptr [esi + 256] ; S4 - db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, ymmword ptr [esp + 96] - db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu ymmword ptr [esp + 96], ymm7 - - // D2 spilled at [esp + 64] - db $C5, $FD, $F4, $BE, $40, $00, $00, $00 // vpmuludq ymm7, ymm0, ymmword ptr [esi + 64] - db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu ymmword ptr [esp + 64], ymm7 - db $C5, $F5, $F4, $7E, $20 // vpmuludq ymm7, ymm1, ymmword ptr [esi + 32] - db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, ymmword ptr [esp + 64] - db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu ymmword ptr [esp + 64], ymm7 - db $C5, $ED, $F4, $7E, $00 // vpmuludq ymm7, ymm2, ymmword ptr [esi] - db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, ymmword ptr [esp + 64] - db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu ymmword ptr [esp + 64], ymm7 - db $C5, $E5, $F4, $BE, $00, $01, $00, $00 // vpmuludq ymm7, ymm3, ymmword ptr [esi + 256] - db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, ymmword ptr [esp + 64] - db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu ymmword ptr [esp + 64], ymm7 - db $C5, $DD, $F4, $BE, $E0, $00, $00, $00 // vpmuludq ymm7, ymm4, ymmword ptr [esi + 224] ; S3 - db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, ymmword ptr [esp + 64] - db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu ymmword ptr [esp + 64], ymm7 - - // D1 spilled at [esp + 32] - db $C5, $FD, $F4, $7E, $20 // vpmuludq ymm7, ymm0, ymmword ptr [esi + 32] - db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu ymmword ptr [esp + 32], ymm7 - db $C5, $F5, $F4, $7E, $00 // vpmuludq ymm7, ymm1, ymmword ptr [esi] - db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, ymmword ptr [esp + 32] - db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu ymmword ptr [esp + 32], ymm7 - db $C5, $ED, $F4, $BE, $00, $01, $00, $00 // vpmuludq ymm7, ymm2, ymmword ptr [esi + 256] - db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, ymmword ptr [esp + 32] - db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu ymmword ptr [esp + 32], ymm7 - db $C5, $E5, $F4, $BE, $E0, $00, $00, $00 // vpmuludq ymm7, ymm3, ymmword ptr [esi + 224] - db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, ymmword ptr [esp + 32] - db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu ymmword ptr [esp + 32], ymm7 - db $C5, $DD, $F4, $BE, $C0, $00, $00, $00 // vpmuludq ymm7, ymm4, ymmword ptr [esi + 192] ; S2 - db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, ymmword ptr [esp + 32] - db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu ymmword ptr [esp + 32], ymm7 - - // D0 spilled at [esp + 0] - db $C5, $FD, $F4, $7E, $00 // vpmuludq ymm7, ymm0, ymmword ptr [esi] - db $C5, $FE, $7F, $3C, $24 // vmovdqu ymmword ptr [esp], ymm7 - db $C5, $F5, $F4, $BE, $00, $01, $00, $00 // vpmuludq ymm7, ymm1, ymmword ptr [esi + 256] - db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, ymmword ptr [esp] - db $C5, $FE, $7F, $3C, $24 // vmovdqu ymmword ptr [esp], ymm7 - db $C5, $ED, $F4, $BE, $E0, $00, $00, $00 // vpmuludq ymm7, ymm2, ymmword ptr [esi + 224] - db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, ymmword ptr [esp] - db $C5, $FE, $7F, $3C, $24 // vmovdqu ymmword ptr [esp], ymm7 - db $C5, $E5, $F4, $BE, $C0, $00, $00, $00 // vpmuludq ymm7, ymm3, ymmword ptr [esi + 192] - db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, ymmword ptr [esp] - db $C5, $FE, $7F, $3C, $24 // vmovdqu ymmword ptr [esp], ymm7 - db $C5, $DD, $F4, $BE, $A0, $00, $00, $00 // vpmuludq ymm7, ymm4, ymmword ptr [esi + 160] ; S1 - db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, ymmword ptr [esp] - db $C5, $FE, $7F, $3C, $24 // vmovdqu ymmword ptr [esp], ymm7 - - // ---- Lazy reduce: D0..D4 (stack) -> H0..H4 (ymm0..ymm4) ---- - db $C5, $FE, $6F, $04, $24 // vmovdqu ymm0, ymmword ptr [esp] - db $C5, $FE, $6F, $4C, $24, $20 // vmovdqu ymm1, ymmword ptr [esp + 32] - db $C5, $FE, $6F, $54, $24, $40 // vmovdqu ymm2, ymmword ptr [esp + 64] - db $C5, $FE, $6F, $5C, $24, $60 // vmovdqu ymm3, ymmword ptr [esp + 96] - db $C5, $FE, $6F, $A4, $24, $80, $00, $00, $00 // vmovdqu ymm4, ymmword ptr [esp + 128] - - db $C5, $C5, $73, $D0, $1A // vpsrlq ymm7, ymm0, 26 - db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 - db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 - db $C5, $C5, $73, $D1, $1A // vpsrlq ymm7, ymm1, 26 - db $C5, $F5, $DB, $CD // vpand ymm1, ymm1, ymm5 - db $C5, $ED, $D4, $D7 // vpaddq ymm2, ymm2, ymm7 - db $C5, $C5, $73, $D2, $1A // vpsrlq ymm7, ymm2, 26 - db $C5, $ED, $DB, $D5 // vpand ymm2, ymm2, ymm5 - db $C5, $E5, $D4, $DF // vpaddq ymm3, ymm3, ymm7 - db $C5, $C5, $73, $D3, $1A // vpsrlq ymm7, ymm3, 26 - db $C5, $E5, $DB, $DD // vpand ymm3, ymm3, ymm5 - db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 - db $C5, $C5, $73, $D4, $1A // vpsrlq ymm7, ymm4, 26 - db $C5, $DD, $DB, $E5 // vpand ymm4, ymm4, ymm5 - db $C5, $FE, $7F, $3C, $24 // vmovdqu ymmword ptr [esp], ymm7 ; (D4>>26) backup - db $C5, $C5, $73, $F7, $02 // vpsllq ymm7, ymm7, 2 - db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, ymmword ptr [esp] ; *5 - db $C5, $FD, $D4, $C7 // vpaddq ymm0, ymm0, ymm7 - db $C5, $C5, $73, $D0, $1A // vpsrlq ymm7, ymm0, 26 - db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 - db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 - - // ---- Spill H, load + decompress + absorb next 4 blocks ---- - db $C5, $FE, $7F, $84, $24, $A0, $00, $00, $00 // vmovdqu ymmword ptr [esp + 160], ymm0 - db $C5, $FE, $7F, $8C, $24, $C0, $00, $00, $00 // vmovdqu ymmword ptr [esp + 192], ymm1 - db $C5, $FE, $7F, $94, $24, $E0, $00, $00, $00 // vmovdqu ymmword ptr [esp + 224], ymm2 - db $C5, $FE, $7F, $9C, $24, $00, $01, $00, $00 // vmovdqu ymmword ptr [esp + 256], ymm3 - db $C5, $FE, $7F, $A4, $24, $20, $01, $00, $00 // vmovdqu ymmword ptr [esp + 288], ymm4 - - db $C5, $FA, $6F, $07 // vmovdqu xmm0, xmmword ptr [edi] - db $C5, $FA, $6F, $4F, $10 // vmovdqu xmm1, xmmword ptr [edi + 16] - db $C4, $E3, $7D, $38, $47, $20, $01 // vinserti128 ymm0, ymm0, xmmword ptr [edi + 32], 1 - db $C4, $E3, $75, $38, $4F, $30, $01 // vinserti128 ymm1, ymm1, xmmword ptr [edi + 48], 1 - add edi, 64 - - db $C5, $ED, $73, $D8, $06 // vpsrldq ymm2, ymm0, 6 - db $C5, $E5, $73, $D9, $06 // vpsrldq ymm3, ymm1, 6 - db $C5, $FD, $6D, $E1 // vpunpckhqdq ymm4, ymm0, ymm1 - db $C5, $FD, $6C, $C1 // vpunpcklqdq ymm0, ymm0, ymm1 - db $C5, $ED, $6C, $D3 // vpunpcklqdq ymm2, ymm2, ymm3 - db $C5, $E5, $73, $D2, $1E // vpsrlq ymm3, ymm2, 30 - db $C5, $ED, $73, $D2, $04 // vpsrlq ymm2, ymm2, 4 - db $C5, $F5, $73, $D0, $1A // vpsrlq ymm1, ymm0, 26 - db $C5, $DD, $73, $D4, $28 // vpsrlq ymm4, ymm4, 40 - db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 - db $C5, $F5, $DB, $CD // vpand ymm1, ymm1, ymm5 - db $C5, $ED, $DB, $D5 // vpand ymm2, ymm2, ymm5 - db $C5, $E5, $DB, $DD // vpand ymm3, ymm3, ymm5 - db $C5, $DD, $EB, $E6 // vpor ymm4, ymm4, ymm6 - - db $C5, $FD, $D4, $84, $24, $A0, $00, $00, $00 // vpaddq ymm0, ymm0, ymmword ptr [esp + 160] - db $C5, $F5, $D4, $8C, $24, $C0, $00, $00, $00 // vpaddq ymm1, ymm1, ymmword ptr [esp + 192] - db $C5, $ED, $D4, $94, $24, $E0, $00, $00, $00 // vpaddq ymm2, ymm2, ymmword ptr [esp + 224] - db $C5, $E5, $D4, $9C, $24, $00, $01, $00, $00 // vpaddq ymm3, ymm3, ymmword ptr [esp + 256] - db $C5, $DD, $D4, $A4, $24, $20, $01, $00, $00 // vpaddq ymm4, ymm4, ymmword ptr [esp + 288] - - sub eax, 64 - jnz @@poly1305_avx2_i386_loop + // ---- Bulk: H *= r^4 (broadcast), D0..D4 spilled ---- + db $C5, $FD, $F4, $BE, $80, $00, $00, $00 // vpmuludq ymm7, ymm0, [esi + 128] + db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu [esp + 128], ymm7 + db $C5, $F5, $F4, $7E, $60 // vpmuludq ymm7, ymm1, [esi + 96] + db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, [esp + 128] + db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu [esp + 128], ymm7 + db $C5, $ED, $F4, $7E, $40 // vpmuludq ymm7, ymm2, [esi + 64] + db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, [esp + 128] + db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu [esp + 128], ymm7 + db $C5, $E5, $F4, $7E, $20 // vpmuludq ymm7, ymm3, [esi + 32] + db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, [esp + 128] + db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu [esp + 128], ymm7 + db $C5, $DD, $F4, $3E // vpmuludq ymm7, ymm4, [esi] + db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, [esp + 128] + db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu [esp + 128], ymm7 + db $C5, $FD, $F4, $7E, $60 // vpmuludq ymm7, ymm0, [esi + 96] + db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu [esp + 96], ymm7 + db $C5, $F5, $F4, $7E, $40 // vpmuludq ymm7, ymm1, [esi + 64] + db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, [esp + 96] + db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu [esp + 96], ymm7 + db $C5, $ED, $F4, $7E, $20 // vpmuludq ymm7, ymm2, [esi + 32] + db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, [esp + 96] + db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu [esp + 96], ymm7 + db $C5, $E5, $F4, $3E // vpmuludq ymm7, ymm3, [esi] + db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, [esp + 96] + db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu [esp + 96], ymm7 + db $C5, $DD, $F4, $BE, $00, $01, $00, $00 // vpmuludq ymm7, ymm4, [esi + 256] + db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, [esp + 96] + db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu [esp + 96], ymm7 + db $C5, $FD, $F4, $7E, $40 // vpmuludq ymm7, ymm0, [esi + 64] + db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu [esp + 64], ymm7 + db $C5, $F5, $F4, $7E, $20 // vpmuludq ymm7, ymm1, [esi + 32] + db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, [esp + 64] + db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu [esp + 64], ymm7 + db $C5, $ED, $F4, $3E // vpmuludq ymm7, ymm2, [esi] + db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, [esp + 64] + db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu [esp + 64], ymm7 + db $C5, $E5, $F4, $BE, $00, $01, $00, $00 // vpmuludq ymm7, ymm3, [esi + 256] + db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, [esp + 64] + db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu [esp + 64], ymm7 + db $C5, $DD, $F4, $BE, $E0, $00, $00, $00 // vpmuludq ymm7, ymm4, [esi + 224] + db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, [esp + 64] + db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu [esp + 64], ymm7 + db $C5, $FD, $F4, $7E, $20 // vpmuludq ymm7, ymm0, [esi + 32] + db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu [esp + 32], ymm7 + db $C5, $F5, $F4, $3E // vpmuludq ymm7, ymm1, [esi] + db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, [esp + 32] + db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu [esp + 32], ymm7 + db $C5, $ED, $F4, $BE, $00, $01, $00, $00 // vpmuludq ymm7, ymm2, [esi + 256] + db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, [esp + 32] + db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu [esp + 32], ymm7 + db $C5, $E5, $F4, $BE, $E0, $00, $00, $00 // vpmuludq ymm7, ymm3, [esi + 224] + db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, [esp + 32] + db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu [esp + 32], ymm7 + db $C5, $DD, $F4, $BE, $C0, $00, $00, $00 // vpmuludq ymm7, ymm4, [esi + 192] + db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, [esp + 32] + db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu [esp + 32], ymm7 + db $C5, $FD, $F4, $3E // vpmuludq ymm7, ymm0, [esi] + db $C5, $FE, $7F, $3C, $24 // vmovdqu [esp], ymm7 + db $C5, $F5, $F4, $BE, $00, $01, $00, $00 // vpmuludq ymm7, ymm1, [esi + 256] + db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, [esp] + db $C5, $FE, $7F, $3C, $24 // vmovdqu [esp], ymm7 + db $C5, $ED, $F4, $BE, $E0, $00, $00, $00 // vpmuludq ymm7, ymm2, [esi + 224] + db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, [esp] + db $C5, $FE, $7F, $3C, $24 // vmovdqu [esp], ymm7 + db $C5, $E5, $F4, $BE, $C0, $00, $00, $00 // vpmuludq ymm7, ymm3, [esi + 192] + db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, [esp] + db $C5, $FE, $7F, $3C, $24 // vmovdqu [esp], ymm7 + db $C5, $DD, $F4, $BE, $A0, $00, $00, $00 // vpmuludq ymm7, ymm4, [esi + 160] + db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, [esp] + db $C5, $FE, $7F, $3C, $24 // vmovdqu [esp], ymm7 + // ---- Lazy reduce ---- + db $C5, $FE, $6F, $04, $24 // vmovdqu ymm0, [esp] + db $C5, $FE, $6F, $4C, $24, $20 // vmovdqu ymm1, [esp + 32] + db $C5, $FE, $6F, $54, $24, $40 // vmovdqu ymm2, [esp + 64] + db $C5, $FE, $6F, $5C, $24, $60 // vmovdqu ymm3, [esp + 96] + db $C5, $FE, $6F, $A4, $24, $80, $00, $00, $00 // vmovdqu ymm4, [esp + 128] + db $C5, $C5, $73, $D0, $1A // vpsrlq ymm7, ymm0, 26 + db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 + db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 + db $C5, $C5, $73, $D1, $1A // vpsrlq ymm7, ymm1, 26 + db $C5, $F5, $DB, $CD // vpand ymm1, ymm1, ymm5 + db $C5, $ED, $D4, $D7 // vpaddq ymm2, ymm2, ymm7 + db $C5, $C5, $73, $D2, $1A // vpsrlq ymm7, ymm2, 26 + db $C5, $ED, $DB, $D5 // vpand ymm2, ymm2, ymm5 + db $C5, $E5, $D4, $DF // vpaddq ymm3, ymm3, ymm7 + db $C5, $C5, $73, $D3, $1A // vpsrlq ymm7, ymm3, 26 + db $C5, $E5, $DB, $DD // vpand ymm3, ymm3, ymm5 + db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 + db $C5, $C5, $73, $D4, $1A // vpsrlq ymm7, ymm4, 26 + db $C5, $DD, $DB, $E5 // vpand ymm4, ymm4, ymm5 + db $C5, $FE, $7F, $3C, $24 // vmovdqu [esp], ymm7 + db $C5, $C5, $73, $F7, $02 // vpsllq ymm7, ymm7, 2 + db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, [esp] + db $C5, $FD, $D4, $C7 // vpaddq ymm0, ymm0, ymm7 + db $C5, $C5, $73, $D0, $1A // vpsrlq ymm7, ymm0, 26 + db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 + db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 + // ---- Absorb next 4 blocks ---- + db $C5, $FE, $7F, $84, $24, $A0, $00, $00, $00 // vmovdqu [esp + 160], ymm0 + db $C5, $FE, $7F, $8C, $24, $C0, $00, $00, $00 // vmovdqu [esp + 192], ymm1 + db $C5, $FE, $7F, $94, $24, $E0, $00, $00, $00 // vmovdqu [esp + 224], ymm2 + db $C5, $FE, $7F, $9C, $24, $00, $01, $00, $00 // vmovdqu [esp + 256], ymm3 + db $C5, $FE, $7F, $A4, $24, $20, $01, $00, $00 // vmovdqu [esp + 288], ymm4 + db $C5, $FA, $6F, $07 // vmovdqu xmm0, [edi] + db $C5, $FA, $6F, $4F, $10 // vmovdqu xmm1, [edi + 16] + db $C4, $E3, $7D, $38, $47, $20, $01 // vinserti128 ymm0, ymm0, [edi + 32], 1 + db $C4, $E3, $75, $38, $4F, $30, $01 // vinserti128 ymm1, ymm1, [edi + 48], 1 + add edi, 64 + db $C5, $ED, $73, $D8, $06 // vpsrldq ymm2, ymm0, 6 + db $C5, $E5, $73, $D9, $06 // vpsrldq ymm3, ymm1, 6 + db $C5, $FD, $6D, $E1 // vpunpckhqdq ymm4, ymm0, ymm1 + db $C5, $FD, $6C, $C1 // vpunpcklqdq ymm0, ymm0, ymm1 + db $C5, $ED, $6C, $D3 // vpunpcklqdq ymm2, ymm2, ymm3 + db $C5, $E5, $73, $D2, $1E // vpsrlq ymm3, ymm2, 30 + db $C5, $ED, $73, $D2, $04 // vpsrlq ymm2, ymm2, 4 + db $C5, $F5, $73, $D0, $1A // vpsrlq ymm1, ymm0, 26 + db $C5, $DD, $73, $D4, $28 // vpsrlq ymm4, ymm4, 40 + db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 + db $C5, $F5, $DB, $CD // vpand ymm1, ymm1, ymm5 + db $C5, $ED, $DB, $D5 // vpand ymm2, ymm2, ymm5 + db $C5, $E5, $DB, $DD // vpand ymm3, ymm3, ymm5 + db $C5, $DD, $EB, $E6 // vpor ymm4, ymm4, ymm6 + db $C5, $FD, $D4, $84, $24, $A0, $00, $00, $00 // vpaddq ymm0, ymm0, [esp + 160] + db $C5, $F5, $D4, $8C, $24, $C0, $00, $00, $00 // vpaddq ymm1, ymm1, [esp + 192] + db $C5, $ED, $D4, $94, $24, $E0, $00, $00, $00 // vpaddq ymm2, ymm2, [esp + 224] + db $C5, $E5, $D4, $9C, $24, $00, $01, $00, $00 // vpaddq ymm3, ymm3, [esp + 256] + db $C5, $DD, $D4, $A4, $24, $20, $01, $00, $00 // vpaddq ymm4, ymm4, [esp + 288] + sub eax, 64 + jnz @@poly1305_avx2_i386_loop @@poly1305_avx2_i386_tail: - // ---- Tail: H *= [r^1, r^2, r^3, r^4] (offset+4 = shifted form) ---- - // D4 spilled at [esp + 128] - table loads at +4 over the bulk offsets - db $C5, $FD, $F4, $BE, $84, $00, $00, $00 // vpmuludq ymm7, ymm0, ymmword ptr [esi + 132] - db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu ymmword ptr [esp + 128], ymm7 - db $C5, $F5, $F4, $BE, $64, $00, $00, $00 // vpmuludq ymm7, ymm1, ymmword ptr [esi + 100] - db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, ymmword ptr [esp + 128] - db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu ymmword ptr [esp + 128], ymm7 - db $C5, $ED, $F4, $BE, $44, $00, $00, $00 // vpmuludq ymm7, ymm2, ymmword ptr [esi + 68] - db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, ymmword ptr [esp + 128] - db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu ymmword ptr [esp + 128], ymm7 - db $C5, $E5, $F4, $7E, $24 // vpmuludq ymm7, ymm3, ymmword ptr [esi + 36] - db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, ymmword ptr [esp + 128] - db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu ymmword ptr [esp + 128], ymm7 - db $C5, $DD, $F4, $7E, $04 // vpmuludq ymm7, ymm4, ymmword ptr [esi + 4] - db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, ymmword ptr [esp + 128] - db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu ymmword ptr [esp + 128], ymm7 - - // D3 spilled at [esp + 96] - db $C5, $FD, $F4, $BE, $64, $00, $00, $00 // vpmuludq ymm7, ymm0, ymmword ptr [esi + 100] - db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu ymmword ptr [esp + 96], ymm7 - db $C5, $F5, $F4, $BE, $44, $00, $00, $00 // vpmuludq ymm7, ymm1, ymmword ptr [esi + 68] - db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, ymmword ptr [esp + 96] - db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu ymmword ptr [esp + 96], ymm7 - db $C5, $ED, $F4, $7E, $24 // vpmuludq ymm7, ymm2, ymmword ptr [esi + 36] - db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, ymmword ptr [esp + 96] - db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu ymmword ptr [esp + 96], ymm7 - db $C5, $E5, $F4, $7E, $04 // vpmuludq ymm7, ymm3, ymmword ptr [esi + 4] - db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, ymmword ptr [esp + 96] - db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu ymmword ptr [esp + 96], ymm7 - db $C5, $DD, $F4, $BE, $04, $01, $00, $00 // vpmuludq ymm7, ymm4, ymmword ptr [esi + 260] ; S4 shifted - db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, ymmword ptr [esp + 96] - db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu ymmword ptr [esp + 96], ymm7 - - // D2 spilled at [esp + 64] - db $C5, $FD, $F4, $BE, $44, $00, $00, $00 // vpmuludq ymm7, ymm0, ymmword ptr [esi + 68] - db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu ymmword ptr [esp + 64], ymm7 - db $C5, $F5, $F4, $7E, $24 // vpmuludq ymm7, ymm1, ymmword ptr [esi + 36] - db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, ymmword ptr [esp + 64] - db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu ymmword ptr [esp + 64], ymm7 - db $C5, $ED, $F4, $7E, $04 // vpmuludq ymm7, ymm2, ymmword ptr [esi + 4] - db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, ymmword ptr [esp + 64] - db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu ymmword ptr [esp + 64], ymm7 - db $C5, $E5, $F4, $BE, $04, $01, $00, $00 // vpmuludq ymm7, ymm3, ymmword ptr [esi + 260] - db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, ymmword ptr [esp + 64] - db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu ymmword ptr [esp + 64], ymm7 - db $C5, $DD, $F4, $BE, $E4, $00, $00, $00 // vpmuludq ymm7, ymm4, ymmword ptr [esi + 228] ; S3 shifted - db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, ymmword ptr [esp + 64] - db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu ymmword ptr [esp + 64], ymm7 - - // D1 spilled at [esp + 32] - db $C5, $FD, $F4, $7E, $24 // vpmuludq ymm7, ymm0, ymmword ptr [esi + 36] - db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu ymmword ptr [esp + 32], ymm7 - db $C5, $F5, $F4, $7E, $04 // vpmuludq ymm7, ymm1, ymmword ptr [esi + 4] - db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, ymmword ptr [esp + 32] - db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu ymmword ptr [esp + 32], ymm7 - db $C5, $ED, $F4, $BE, $04, $01, $00, $00 // vpmuludq ymm7, ymm2, ymmword ptr [esi + 260] - db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, ymmword ptr [esp + 32] - db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu ymmword ptr [esp + 32], ymm7 - db $C5, $E5, $F4, $BE, $E4, $00, $00, $00 // vpmuludq ymm7, ymm3, ymmword ptr [esi + 228] - db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, ymmword ptr [esp + 32] - db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu ymmword ptr [esp + 32], ymm7 - db $C5, $DD, $F4, $BE, $C4, $00, $00, $00 // vpmuludq ymm7, ymm4, ymmword ptr [esi + 196] ; S2 shifted - db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, ymmword ptr [esp + 32] - db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu ymmword ptr [esp + 32], ymm7 - - // D0 spilled at [esp + 0] - db $C5, $FD, $F4, $7E, $04 // vpmuludq ymm7, ymm0, ymmword ptr [esi + 4] - db $C5, $FE, $7F, $3C, $24 // vmovdqu ymmword ptr [esp], ymm7 - db $C5, $F5, $F4, $BE, $04, $01, $00, $00 // vpmuludq ymm7, ymm1, ymmword ptr [esi + 260] - db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, ymmword ptr [esp] - db $C5, $FE, $7F, $3C, $24 // vmovdqu ymmword ptr [esp], ymm7 - db $C5, $ED, $F4, $BE, $E4, $00, $00, $00 // vpmuludq ymm7, ymm2, ymmword ptr [esi + 228] - db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, ymmword ptr [esp] - db $C5, $FE, $7F, $3C, $24 // vmovdqu ymmword ptr [esp], ymm7 - db $C5, $E5, $F4, $BE, $C4, $00, $00, $00 // vpmuludq ymm7, ymm3, ymmword ptr [esi + 196] - db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, ymmword ptr [esp] - db $C5, $FE, $7F, $3C, $24 // vmovdqu ymmword ptr [esp], ymm7 - db $C5, $DD, $F4, $BE, $A4, $00, $00, $00 // vpmuludq ymm7, ymm4, ymmword ptr [esi + 164] ; S1 shifted - db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, ymmword ptr [esp] - db $C5, $FE, $7F, $3C, $24 // vmovdqu ymmword ptr [esp], ymm7 - + // ---- Tail: H *= [r^1, r^2, r^3, r^4] (shifted table read) ---- + db $C5, $FD, $F4, $BE, $84, $00, $00, $00 // vpmuludq ymm7, ymm0, [esi + 132] + db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu [esp + 128], ymm7 + db $C5, $F5, $F4, $7E, $64 // vpmuludq ymm7, ymm1, [esi + 100] + db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, [esp + 128] + db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu [esp + 128], ymm7 + db $C5, $ED, $F4, $7E, $44 // vpmuludq ymm7, ymm2, [esi + 68] + db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, [esp + 128] + db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu [esp + 128], ymm7 + db $C5, $E5, $F4, $7E, $24 // vpmuludq ymm7, ymm3, [esi + 36] + db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, [esp + 128] + db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu [esp + 128], ymm7 + db $C5, $DD, $F4, $7E, $04 // vpmuludq ymm7, ymm4, [esi + 4] + db $C5, $C5, $D4, $BC, $24, $80, $00, $00, $00 // vpaddq ymm7, ymm7, [esp + 128] + db $C5, $FE, $7F, $BC, $24, $80, $00, $00, $00 // vmovdqu [esp + 128], ymm7 + db $C5, $FD, $F4, $7E, $64 // vpmuludq ymm7, ymm0, [esi + 100] + db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu [esp + 96], ymm7 + db $C5, $F5, $F4, $7E, $44 // vpmuludq ymm7, ymm1, [esi + 68] + db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, [esp + 96] + db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu [esp + 96], ymm7 + db $C5, $ED, $F4, $7E, $24 // vpmuludq ymm7, ymm2, [esi + 36] + db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, [esp + 96] + db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu [esp + 96], ymm7 + db $C5, $E5, $F4, $7E, $04 // vpmuludq ymm7, ymm3, [esi + 4] + db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, [esp + 96] + db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu [esp + 96], ymm7 + db $C5, $DD, $F4, $BE, $04, $01, $00, $00 // vpmuludq ymm7, ymm4, [esi + 260] + db $C5, $C5, $D4, $7C, $24, $60 // vpaddq ymm7, ymm7, [esp + 96] + db $C5, $FE, $7F, $7C, $24, $60 // vmovdqu [esp + 96], ymm7 + db $C5, $FD, $F4, $7E, $44 // vpmuludq ymm7, ymm0, [esi + 68] + db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu [esp + 64], ymm7 + db $C5, $F5, $F4, $7E, $24 // vpmuludq ymm7, ymm1, [esi + 36] + db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, [esp + 64] + db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu [esp + 64], ymm7 + db $C5, $ED, $F4, $7E, $04 // vpmuludq ymm7, ymm2, [esi + 4] + db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, [esp + 64] + db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu [esp + 64], ymm7 + db $C5, $E5, $F4, $BE, $04, $01, $00, $00 // vpmuludq ymm7, ymm3, [esi + 260] + db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, [esp + 64] + db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu [esp + 64], ymm7 + db $C5, $DD, $F4, $BE, $E4, $00, $00, $00 // vpmuludq ymm7, ymm4, [esi + 228] + db $C5, $C5, $D4, $7C, $24, $40 // vpaddq ymm7, ymm7, [esp + 64] + db $C5, $FE, $7F, $7C, $24, $40 // vmovdqu [esp + 64], ymm7 + db $C5, $FD, $F4, $7E, $24 // vpmuludq ymm7, ymm0, [esi + 36] + db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu [esp + 32], ymm7 + db $C5, $F5, $F4, $7E, $04 // vpmuludq ymm7, ymm1, [esi + 4] + db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, [esp + 32] + db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu [esp + 32], ymm7 + db $C5, $ED, $F4, $BE, $04, $01, $00, $00 // vpmuludq ymm7, ymm2, [esi + 260] + db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, [esp + 32] + db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu [esp + 32], ymm7 + db $C5, $E5, $F4, $BE, $E4, $00, $00, $00 // vpmuludq ymm7, ymm3, [esi + 228] + db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, [esp + 32] + db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu [esp + 32], ymm7 + db $C5, $DD, $F4, $BE, $C4, $00, $00, $00 // vpmuludq ymm7, ymm4, [esi + 196] + db $C5, $C5, $D4, $7C, $24, $20 // vpaddq ymm7, ymm7, [esp + 32] + db $C5, $FE, $7F, $7C, $24, $20 // vmovdqu [esp + 32], ymm7 + db $C5, $FD, $F4, $7E, $04 // vpmuludq ymm7, ymm0, [esi + 4] + db $C5, $FE, $7F, $3C, $24 // vmovdqu [esp], ymm7 + db $C5, $F5, $F4, $BE, $04, $01, $00, $00 // vpmuludq ymm7, ymm1, [esi + 260] + db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, [esp] + db $C5, $FE, $7F, $3C, $24 // vmovdqu [esp], ymm7 + db $C5, $ED, $F4, $BE, $E4, $00, $00, $00 // vpmuludq ymm7, ymm2, [esi + 228] + db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, [esp] + db $C5, $FE, $7F, $3C, $24 // vmovdqu [esp], ymm7 + db $C5, $E5, $F4, $BE, $C4, $00, $00, $00 // vpmuludq ymm7, ymm3, [esi + 196] + db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, [esp] + db $C5, $FE, $7F, $3C, $24 // vmovdqu [esp], ymm7 + db $C5, $DD, $F4, $BE, $A4, $00, $00, $00 // vpmuludq ymm7, ymm4, [esi + 164] + db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, [esp] + db $C5, $FE, $7F, $3C, $24 // vmovdqu [esp], ymm7 // ---- Tail lazy reduce ---- - db $C5, $FE, $6F, $04, $24 // vmovdqu ymm0, ymmword ptr [esp] - db $C5, $FE, $6F, $4C, $24, $20 // vmovdqu ymm1, ymmword ptr [esp + 32] - db $C5, $FE, $6F, $54, $24, $40 // vmovdqu ymm2, ymmword ptr [esp + 64] - db $C5, $FE, $6F, $5C, $24, $60 // vmovdqu ymm3, ymmword ptr [esp + 96] - db $C5, $FE, $6F, $A4, $24, $80, $00, $00, $00 // vmovdqu ymm4, ymmword ptr [esp + 128] - - db $C5, $C5, $73, $D0, $1A // vpsrlq ymm7, ymm0, 26 - db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 - db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 - db $C5, $C5, $73, $D1, $1A // vpsrlq ymm7, ymm1, 26 - db $C5, $F5, $DB, $CD // vpand ymm1, ymm1, ymm5 - db $C5, $ED, $D4, $D7 // vpaddq ymm2, ymm2, ymm7 - db $C5, $C5, $73, $D2, $1A // vpsrlq ymm7, ymm2, 26 - db $C5, $ED, $DB, $D5 // vpand ymm2, ymm2, ymm5 - db $C5, $E5, $D4, $DF // vpaddq ymm3, ymm3, ymm7 - db $C5, $C5, $73, $D3, $1A // vpsrlq ymm7, ymm3, 26 - db $C5, $E5, $DB, $DD // vpand ymm3, ymm3, ymm5 - db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 - db $C5, $C5, $73, $D4, $1A // vpsrlq ymm7, ymm4, 26 - db $C5, $DD, $DB, $E5 // vpand ymm4, ymm4, ymm5 - db $C5, $FE, $7F, $3C, $24 // vmovdqu ymmword ptr [esp], ymm7 - db $C5, $C5, $73, $F7, $02 // vpsllq ymm7, ymm7, 2 - db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, ymmword ptr [esp] - db $C5, $FD, $D4, $C7 // vpaddq ymm0, ymm0, ymm7 - db $C5, $C5, $73, $D0, $1A // vpsrlq ymm7, ymm0, 26 - db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 - db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 - - // ---- Horizontal sum across 4 lanes for ymm0..ymm4 ---- - db $C5, $C5, $73, $D8, $08 // vpsrldq ymm7, ymm0, 8 - db $C5, $FD, $D4, $C7 // vpaddq ymm0, ymm0, ymm7 - db $C4, $E3, $FD, $00, $F8, $4E // vpermq ymm7, ymm0, 0x4E - db $C5, $FD, $D4, $C7 // vpaddq ymm0, ymm0, ymm7 - db $C5, $C5, $73, $D9, $08 // vpsrldq ymm7, ymm1, 8 - db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 - db $C4, $E3, $FD, $00, $F9, $4E // vpermq ymm7, ymm1, 0x4E - db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 - db $C5, $C5, $73, $DA, $08 // vpsrldq ymm7, ymm2, 8 - db $C5, $ED, $D4, $D7 // vpaddq ymm2, ymm2, ymm7 - db $C4, $E3, $FD, $00, $FA, $4E // vpermq ymm7, ymm2, 0x4E - db $C5, $ED, $D4, $D7 // vpaddq ymm2, ymm2, ymm7 - db $C5, $C5, $73, $DB, $08 // vpsrldq ymm7, ymm3, 8 - db $C5, $E5, $D4, $DF // vpaddq ymm3, ymm3, ymm7 - db $C4, $E3, $FD, $00, $FB, $4E // vpermq ymm7, ymm3, 0x4E - db $C5, $E5, $D4, $DF // vpaddq ymm3, ymm3, ymm7 - db $C5, $C5, $73, $DC, $08 // vpsrldq ymm7, ymm4, 8 - db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 - db $C4, $E3, $FD, $00, $FC, $4E // vpermq ymm7, ymm4, 0x4E - db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 - - // ---- Final lazy reduce on the now-scalar limbs (lane 0) ---- - db $C5, $C5, $73, $D0, $1A // vpsrlq ymm7, ymm0, 26 - db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 - db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 - db $C5, $C5, $73, $D1, $1A // vpsrlq ymm7, ymm1, 26 - db $C5, $F5, $DB, $CD // vpand ymm1, ymm1, ymm5 - db $C5, $ED, $D4, $D7 // vpaddq ymm2, ymm2, ymm7 - db $C5, $C5, $73, $D2, $1A // vpsrlq ymm7, ymm2, 26 - db $C5, $ED, $DB, $D5 // vpand ymm2, ymm2, ymm5 - db $C5, $E5, $D4, $DF // vpaddq ymm3, ymm3, ymm7 - db $C5, $C5, $73, $D3, $1A // vpsrlq ymm7, ymm3, 26 - db $C5, $E5, $DB, $DD // vpand ymm3, ymm3, ymm5 - db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 - db $C5, $C5, $73, $D4, $1A // vpsrlq ymm7, ymm4, 26 - db $C5, $DD, $DB, $E5 // vpand ymm4, ymm4, ymm5 - db $C5, $FE, $7F, $3C, $24 // vmovdqu ymmword ptr [esp], ymm7 - db $C5, $C5, $73, $F7, $02 // vpsllq ymm7, ymm7, 2 - db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, ymmword ptr [esp] - db $C5, $FD, $D4, $C7 // vpaddq ymm0, ymm0, ymm7 - db $C5, $C5, $73, $D0, $1A // vpsrlq ymm7, ymm0, 26 - db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 - db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 - - // ---- Store h0..h4 back to ctx ---- - db $C5, $F9, $7E, $43, $24 // vmovd dword ptr [ebx + 36], xmm0 - db $C5, $F9, $7E, $4B, $28 // vmovd dword ptr [ebx + 40], xmm1 - db $C5, $F9, $7E, $53, $2C // vmovd dword ptr [ebx + 44], xmm2 - db $C5, $F9, $7E, $5B, $30 // vmovd dword ptr [ebx + 48], xmm3 - db $C5, $F9, $7E, $63, $34 // vmovd dword ptr [ebx + 52], xmm4 - - db $C5, $F8, $77 // vzeroupper - add esp, 320 - - pop edi - pop esi - pop ebx + db $C5, $FE, $6F, $04, $24 // vmovdqu ymm0, [esp] + db $C5, $FE, $6F, $4C, $24, $20 // vmovdqu ymm1, [esp + 32] + db $C5, $FE, $6F, $54, $24, $40 // vmovdqu ymm2, [esp + 64] + db $C5, $FE, $6F, $5C, $24, $60 // vmovdqu ymm3, [esp + 96] + db $C5, $FE, $6F, $A4, $24, $80, $00, $00, $00 // vmovdqu ymm4, [esp + 128] + db $C5, $C5, $73, $D0, $1A // vpsrlq ymm7, ymm0, 26 + db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 + db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 + db $C5, $C5, $73, $D1, $1A // vpsrlq ymm7, ymm1, 26 + db $C5, $F5, $DB, $CD // vpand ymm1, ymm1, ymm5 + db $C5, $ED, $D4, $D7 // vpaddq ymm2, ymm2, ymm7 + db $C5, $C5, $73, $D2, $1A // vpsrlq ymm7, ymm2, 26 + db $C5, $ED, $DB, $D5 // vpand ymm2, ymm2, ymm5 + db $C5, $E5, $D4, $DF // vpaddq ymm3, ymm3, ymm7 + db $C5, $C5, $73, $D3, $1A // vpsrlq ymm7, ymm3, 26 + db $C5, $E5, $DB, $DD // vpand ymm3, ymm3, ymm5 + db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 + db $C5, $C5, $73, $D4, $1A // vpsrlq ymm7, ymm4, 26 + db $C5, $DD, $DB, $E5 // vpand ymm4, ymm4, ymm5 + db $C5, $FE, $7F, $3C, $24 // vmovdqu [esp], ymm7 + db $C5, $C5, $73, $F7, $02 // vpsllq ymm7, ymm7, 2 + db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, [esp] + db $C5, $FD, $D4, $C7 // vpaddq ymm0, ymm0, ymm7 + db $C5, $C5, $73, $D0, $1A // vpsrlq ymm7, ymm0, 26 + db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 + db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 + // ---- Horizontal sum 4 lanes -> lane 0 ---- + db $C5, $C5, $73, $D8, $08 // vpsrldq ymm7, ymm0, 8 + db $C5, $FD, $D4, $C7 // vpaddq ymm0, ymm0, ymm7 + db $C4, $E3, $FD, $00, $F8, $4E // vpermq ymm7, ymm0, 0x4E + db $C5, $FD, $D4, $C7 // vpaddq ymm0, ymm0, ymm7 + db $C5, $C5, $73, $D9, $08 // vpsrldq ymm7, ymm1, 8 + db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 + db $C4, $E3, $FD, $00, $F9, $4E // vpermq ymm7, ymm1, 0x4E + db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 + db $C5, $C5, $73, $DA, $08 // vpsrldq ymm7, ymm2, 8 + db $C5, $ED, $D4, $D7 // vpaddq ymm2, ymm2, ymm7 + db $C4, $E3, $FD, $00, $FA, $4E // vpermq ymm7, ymm2, 0x4E + db $C5, $ED, $D4, $D7 // vpaddq ymm2, ymm2, ymm7 + db $C5, $C5, $73, $DB, $08 // vpsrldq ymm7, ymm3, 8 + db $C5, $E5, $D4, $DF // vpaddq ymm3, ymm3, ymm7 + db $C4, $E3, $FD, $00, $FB, $4E // vpermq ymm7, ymm3, 0x4E + db $C5, $E5, $D4, $DF // vpaddq ymm3, ymm3, ymm7 + db $C5, $C5, $73, $DC, $08 // vpsrldq ymm7, ymm4, 8 + db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 + db $C4, $E3, $FD, $00, $FC, $4E // vpermq ymm7, ymm4, 0x4E + db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 + // ---- Final lazy reduce (lane 0 scalars) ---- + db $C5, $C5, $73, $D0, $1A // vpsrlq ymm7, ymm0, 26 + db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 + db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 + db $C5, $C5, $73, $D1, $1A // vpsrlq ymm7, ymm1, 26 + db $C5, $F5, $DB, $CD // vpand ymm1, ymm1, ymm5 + db $C5, $ED, $D4, $D7 // vpaddq ymm2, ymm2, ymm7 + db $C5, $C5, $73, $D2, $1A // vpsrlq ymm7, ymm2, 26 + db $C5, $ED, $DB, $D5 // vpand ymm2, ymm2, ymm5 + db $C5, $E5, $D4, $DF // vpaddq ymm3, ymm3, ymm7 + db $C5, $C5, $73, $D3, $1A // vpsrlq ymm7, ymm3, 26 + db $C5, $E5, $DB, $DD // vpand ymm3, ymm3, ymm5 + db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 + db $C5, $C5, $73, $D4, $1A // vpsrlq ymm7, ymm4, 26 + db $C5, $DD, $DB, $E5 // vpand ymm4, ymm4, ymm5 + db $C5, $FE, $7F, $3C, $24 // vmovdqu [esp], ymm7 + db $C5, $C5, $73, $F7, $02 // vpsllq ymm7, ymm7, 2 + db $C5, $C5, $D4, $3C, $24 // vpaddq ymm7, ymm7, [esp] + db $C5, $FD, $D4, $C7 // vpaddq ymm0, ymm0, ymm7 + db $C5, $C5, $73, $D0, $1A // vpsrlq ymm7, ymm0, 26 + db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 + db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 + // ---- Store H0..H4 back to ctx ---- + db $C5, $F9, $7E, $43, $24 // vmovd dword ptr [ebx + 36], xmm0 + db $C5, $F9, $7E, $4B, $28 // vmovd dword ptr [ebx + 40], xmm1 + db $C5, $F9, $7E, $53, $2C // vmovd dword ptr [ebx + 44], xmm2 + db $C5, $F9, $7E, $5B, $30 // vmovd dword ptr [ebx + 48], xmm3 + db $C5, $F9, $7E, $63, $34 // vmovd dword ptr [ebx + 52], xmm4 + db $C5, $F8, $77 // vzeroupper + add esp, 320 + pop edi + pop esi + pop ebx diff --git a/CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkAvx2Core_x86_64.inc b/CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkAvx2Core_x86_64.inc index dd2429b6..50df2c65 100644 --- a/CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkAvx2Core_x86_64.inc +++ b/CryptoLib/src/Include/Simd/Poly1305/Poly1305BlocksBulkAvx2Core_x86_64.inc @@ -1,332 +1,276 @@ // Poly1305 4-way AVX2 bulk MAC kernel (x86-64). // ------------------------------------------------------------------- -// Algorithm: Goll-Gueron 2015 / Polyakov OpenSSL `poly1305_blocks_avx2`. -// Processes 4 16-byte blocks per iteration in 4-way SIMD with a precomputed -// r^1..r^4 power table (rebuilt at SetKey when AVX2 is the chosen path). -// The bulk loop multiplies the 4-lane accumulator H by r^4 broadcast in all -// lanes; the final tail iteration uses the same table read at +4 byte -// offset, giving lanes [r^1, r^2, r^3, r^4] for a branch-free fold-back via -// a horizontal sum. No scalar-tail block from the SIMD kernel; the Pascal -// dispatcher rounds the SIMD count down to a multiple of 4 and forwards -// 0..3 leftover blocks to the scalar code path. -// -// VEX-encoded AVX2 instructions are db-encoded for broad assembler compatibility. -// Each db line carries a mnemonic comment. Most VEX bytes are shared across IA-32 -// and x86-64 since the inner kernel uses ymm0..ymm15 / r-class registers -// addressable in both modes via 2-/3-byte VEX prefixes; the i386 sibling -// include shares the same algorithm but uses a different register mapping -// (ebx/esi/edi/eax instead of rcx/rdx/r8/r9) and stays inside ymm0..ymm7. +// Goll-Gueron / Polyakov: 4 blocks per iteration in 4 ymm lanes against an +// r^1..r^4 power table (320 bytes, 32-byte rows). radix-2^26 schoolbook +// multiply mod 2^130-5 (5*r wraparound); VEX tolerates unaligned memory so +// the table is read straight into vpmuludq. The bulk-loop carry-reduce uses +// two interleaved chains (low D0->D1->D2->D3->H4, high D3->D4->H0->H1) to +// shorten the serial critical path; the run-once tail/final reduces stay +// serial. A vpermq-based horizontal sum folds the 4 lanes at the end. // // On entry (after ClpSimdProc5Begin_x86_64.inc): -// rcx = ACtx (PTPoly1305State; 72-byte R/S/H/K record) -// rdx = APowTable (PByte; 320-byte 10x8 power table; layout below) -// r8 = AInp (PByte; 16-byte aligned-or-not) -// r9 = ALen (NativeUInt; multiple of 64; >= 64) -// r10 = APad (always 1; ignored - padbit unconditional in bulk) -// -// TPoly1305State byte offsets (no SIMD member): -// R0..R4 : 0..16 (5 dwords) -// S1..S4 : 20..32 (4 dwords) -// H0..H4 : 36..52 (5 dwords) <- loaded into ymm0..ymm4 lane 0 -// K0..K3 : 56..68 (4 dwords; not read by this kernel) -// -// Power-table byte offsets (separate 320-byte buffer; rdx-based loads): -// row j at [rdx + 32*j]; bulk loop reads at row offset (broadcast r^4), -// tail iteration reads at row offset+4 (shifted [r^4,r^3,r^2,r^1]). -// Row 0..4 = r-limbs 0..4; row 5..8 = s-limbs 1..4 (s = 5*r); row 9 pad. -// -// Register allocation (uses ymm0..ymm15): -// ymm0..ymm4 : H0..H4 (4-lane radix-2^26 accumulator, persistent) -// ymm5 : mask26 (0x3FFFFFF per 64-bit lane low half) -// ymm6 : padbit (0x1000000 per 64-bit lane low half) -// ymm7..ymm15: D0..D4 / M0..M4 / scratch (transient) +// rcx = ACtx (72-byte R/S/H/K state); rdx = APowTable (320-byte r^1..r^4) +// r8 = AInp; r9 = ALen (multiple of 64, >= 64); r10 = APad (ignored) // -{$I ..\..\Include\Simd\Common\ClpSimdNonVolatileSave_x86_64.inc} - // ---- Prologue: build mask26 (ymm5) and padbit (ymm6) constants ---- - db $C5, $D5, $76, $ED // vpcmpeqd ymm5, ymm5, ymm5 - db $C5, $D5, $73, $D5, $26 // vpsrlq ymm5, ymm5, 38 ; mask26 = 0x3FFFFFF per lane - db $C5, $CD, $76, $F6 // vpcmpeqd ymm6, ymm6, ymm6 - db $C5, $CD, $73, $D6, $3F // vpsrlq ymm6, ymm6, 63 - db $C5, $CD, $73, $F6, $18 // vpsllq ymm6, ymm6, 24 ; padbit = 1<<24 per lane - - // ---- Load h0..h4 from ctx into lane 0 of ymm0..ymm4 ---- - db $C5, $F9, $6E, $41, $24 // vmovd xmm0, dword ptr [rcx + 36] ; H0 - db $C5, $F9, $6E, $49, $28 // vmovd xmm1, dword ptr [rcx + 40] ; H1 - db $C5, $F9, $6E, $51, $2C // vmovd xmm2, dword ptr [rcx + 44] ; H2 - db $C5, $F9, $6E, $59, $30 // vmovd xmm3, dword ptr [rcx + 48] ; H3 - db $C5, $F9, $6E, $61, $34 // vmovd xmm4, dword ptr [rcx + 52] ; H4 +// Power table: row j at [rdx + 32*j]; rows 0..4 r-limbs, rows 5..8 s-limbs +// (5*r), row 9 pad. Bulk reads [+32*j] (broadcast r^4); tail reads +// [+32*j+4] ([r^4,r^3,r^2,r^1]). - // ---- Pre-loop: load + decompress + absorb first 4 blocks ---- - db $C4, $41, $7A, $6F, $20 // vmovdqu xmm12, xmmword ptr [r8] - db $C4, $41, $7A, $6F, $68, $10 // vmovdqu xmm13, xmmword ptr [r8 + 16] - db $C4, $43, $1D, $38, $60, $20, $01 // vinserti128 ymm12, ymm12, xmmword ptr [r8 + 32], 1 - db $C4, $43, $15, $38, $68, $30, $01 // vinserti128 ymm13, ymm13, xmmword ptr [r8 + 48], 1 +{$I ..\..\Include\Simd\Common\ClpSimdNonVolatileSave_x86_64.inc} + // ---- Prologue: mask26 (ymm5), padbit (ymm6) ---- + db $C5, $D5, $76, $ED // vpcmpeqd ymm5, ymm5, ymm5 + db $C5, $D5, $73, $D5, $26 // vpsrlq ymm5, ymm5, 38 + db $C5, $CD, $76, $F6 // vpcmpeqd ymm6, ymm6, ymm6 + db $C5, $CD, $73, $D6, $3F // vpsrlq ymm6, ymm6, 63 + db $C5, $CD, $73, $F6, $18 // vpsllq ymm6, ymm6, 24 + // ---- Load H0..H4 into lane 0 ---- + db $C5, $F9, $6E, $41, $24 // vmovd xmm0, dword ptr [rcx + 36] + db $C5, $F9, $6E, $49, $28 // vmovd xmm1, dword ptr [rcx + 40] + db $C5, $F9, $6E, $51, $2C // vmovd xmm2, dword ptr [rcx + 44] + db $C5, $F9, $6E, $59, $30 // vmovd xmm3, dword ptr [rcx + 48] + db $C5, $F9, $6E, $61, $34 // vmovd xmm4, dword ptr [rcx + 52] + // ---- Pre-loop: absorb first 4 blocks ---- + db $C4, $41, $7A, $6F, $20 // vmovdqu xmm12, [r8] + db $C4, $41, $7A, $6F, $68, $10 // vmovdqu xmm13, [r8 + 16] + db $C4, $43, $1D, $38, $60, $20, $01 // vinserti128 ymm12, ymm12, [r8 + 32], 1 + db $C4, $43, $15, $38, $68, $30, $01 // vinserti128 ymm13, ymm13, [r8 + 48], 1 add r8, 64 - - // Decompress 4 blocks into limbs M0..M4 in (ymm12, ymm13, ymm14, ymm15, ymm7) - db $C4, $C1, $0D, $73, $DC, $06 // vpsrldq ymm14, ymm12, 6 - db $C4, $C1, $05, $73, $DD, $06 // vpsrldq ymm15, ymm13, 6 - db $C4, $C1, $1D, $6D, $FD // vpunpckhqdq ymm7, ymm12, ymm13 ; T4 (high 64) - db $C4, $41, $1D, $6C, $E5 // vpunpcklqdq ymm12, ymm12, ymm13 ; T0 (low 64) - db $C4, $41, $0D, $6C, $F7 // vpunpcklqdq ymm14, ymm14, ymm15 ; T2 (limbs 2/3) - db $C4, $C1, $05, $73, $D6, $1E // vpsrlq ymm15, ymm14, 30 ; limb3 raw - db $C4, $C1, $0D, $73, $D6, $04 // vpsrlq ymm14, ymm14, 4 ; limb2 raw - db $C4, $C1, $15, $73, $D4, $1A // vpsrlq ymm13, ymm12, 26 ; limb1 raw - db $C5, $C5, $73, $D7, $28 // vpsrlq ymm7, ymm7, 40 ; limb4 raw - db $C5, $1D, $DB, $E5 // vpand ymm12, ymm12, ymm5 ; M0 = limb0 - db $C5, $15, $DB, $ED // vpand ymm13, ymm13, ymm5 ; M1 = limb1 - db $C5, $0D, $DB, $F5 // vpand ymm14, ymm14, ymm5 ; M2 = limb2 - db $C5, $05, $DB, $FD // vpand ymm15, ymm15, ymm5 ; M3 = limb3 - db $C5, $C5, $EB, $FE // vpor ymm7, ymm7, ymm6 ; M4 = limb4 | padbit - - // Absorb: H += M - db $C4, $C1, $7D, $D4, $C4 // vpaddq ymm0, ymm0, ymm12 ; H0 += M0 - db $C4, $C1, $75, $D4, $CD // vpaddq ymm1, ymm1, ymm13 ; H1 += M1 - db $C4, $C1, $6D, $D4, $D6 // vpaddq ymm2, ymm2, ymm14 ; H2 += M2 - db $C4, $C1, $65, $D4, $DF // vpaddq ymm3, ymm3, ymm15 ; H3 += M3 - db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 ; H4 += M4 - + db $C4, $C1, $0D, $73, $DC, $06 // vpsrldq ymm14, ymm12, 6 + db $C4, $C1, $05, $73, $DD, $06 // vpsrldq ymm15, ymm13, 6 + db $C4, $C1, $1D, $6D, $FD // vpunpckhqdq ymm7, ymm12, ymm13 + db $C4, $41, $1D, $6C, $E5 // vpunpcklqdq ymm12, ymm12, ymm13 + db $C4, $41, $0D, $6C, $F7 // vpunpcklqdq ymm14, ymm14, ymm15 + db $C4, $C1, $05, $73, $D6, $1E // vpsrlq ymm15, ymm14, 30 + db $C4, $C1, $0D, $73, $D6, $04 // vpsrlq ymm14, ymm14, 4 + db $C4, $C1, $15, $73, $D4, $1A // vpsrlq ymm13, ymm12, 26 + db $C5, $C5, $73, $D7, $28 // vpsrlq ymm7, ymm7, 40 + db $C5, $1D, $DB, $E5 // vpand ymm12, ymm12, ymm5 + db $C5, $15, $DB, $ED // vpand ymm13, ymm13, ymm5 + db $C5, $0D, $DB, $F5 // vpand ymm14, ymm14, ymm5 + db $C5, $05, $DB, $FD // vpand ymm15, ymm15, ymm5 + db $C5, $C5, $EB, $FE // vpor ymm7, ymm7, ymm6 + db $C4, $C1, $7D, $D4, $C4 // vpaddq ymm0, ymm0, ymm12 + db $C4, $C1, $75, $D4, $CD // vpaddq ymm1, ymm1, ymm13 + db $C4, $C1, $6D, $D4, $D6 // vpaddq ymm2, ymm2, ymm14 + db $C4, $C1, $65, $D4, $DF // vpaddq ymm3, ymm3, ymm15 + db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 sub r9, 64 jz @@poly1305_avx2_tail @@poly1305_avx2_loop: - // ---- Bulk multiply: H *= r^4 (broadcast row form, base offset +0) ---- - // D4 (ymm12) = H0*R4 + H1*R3 + H2*R2 + H3*R1 + H4*R0 - db $C5, $7D, $F4, $A2, $80, $00, $00, $00 // vpmuludq ymm12, ymm0, ymmword ptr [rdx + 128] ; H0 * R4 - db $C5, $75, $F4, $AA, $60, $00, $00, $00 // vpmuludq ymm13, ymm1, ymmword ptr [rdx + 96] ; H1 * R3 - db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 - db $C5, $6D, $F4, $AA, $40, $00, $00, $00 // vpmuludq ymm13, ymm2, ymmword ptr [rdx + 64] ; H2 * R2 - db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 - db $C5, $65, $F4, $6A, $20 // vpmuludq ymm13, ymm3, ymmword ptr [rdx + 32] ; H3 * R1 - db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 - db $C5, $5D, $F4, $6A, $00 // vpmuludq ymm13, ymm4, ymmword ptr [rdx] ; H4 * R0 - db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 - - // D3 (ymm11) = H0*R3 + H1*R2 + H2*R1 + H3*R0 + H4*S4 - db $C5, $7D, $F4, $9A, $60, $00, $00, $00 // vpmuludq ymm11, ymm0, ymmword ptr [rdx + 96] - db $C5, $75, $F4, $AA, $40, $00, $00, $00 // vpmuludq ymm13, ymm1, ymmword ptr [rdx + 64] - db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 - db $C5, $6D, $F4, $6A, $20 // vpmuludq ymm13, ymm2, ymmword ptr [rdx + 32] - db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 - db $C5, $65, $F4, $6A, $00 // vpmuludq ymm13, ymm3, ymmword ptr [rdx] - db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 - db $C5, $5D, $F4, $AA, $00, $01, $00, $00 // vpmuludq ymm13, ymm4, ymmword ptr [rdx + 256] ; S4 - db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 - - // D2 (ymm10) = H0*R2 + H1*R1 + H2*R0 + H3*S4 + H4*S3 - db $C5, $7D, $F4, $92, $40, $00, $00, $00 // vpmuludq ymm10, ymm0, ymmword ptr [rdx + 64] - db $C5, $75, $F4, $6A, $20 // vpmuludq ymm13, ymm1, ymmword ptr [rdx + 32] - db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 - db $C5, $6D, $F4, $6A, $00 // vpmuludq ymm13, ymm2, ymmword ptr [rdx] - db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 - db $C5, $65, $F4, $AA, $00, $01, $00, $00 // vpmuludq ymm13, ymm3, ymmword ptr [rdx + 256] - db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 - db $C5, $5D, $F4, $AA, $E0, $00, $00, $00 // vpmuludq ymm13, ymm4, ymmword ptr [rdx + 224] ; S3 - db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 - - // D1 (ymm9) = H0*R1 + H1*R0 + H2*S4 + H3*S3 + H4*S2 - db $C5, $7D, $F4, $4A, $20 // vpmuludq ymm9, ymm0, ymmword ptr [rdx + 32] - db $C5, $75, $F4, $6A, $00 // vpmuludq ymm13, ymm1, ymmword ptr [rdx] - db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 - db $C5, $6D, $F4, $AA, $00, $01, $00, $00 // vpmuludq ymm13, ymm2, ymmword ptr [rdx + 256] - db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 - db $C5, $65, $F4, $AA, $E0, $00, $00, $00 // vpmuludq ymm13, ymm3, ymmword ptr [rdx + 224] - db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 - db $C5, $5D, $F4, $AA, $C0, $00, $00, $00 // vpmuludq ymm13, ymm4, ymmword ptr [rdx + 192] ; S2 - db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 - - // D0 (ymm8) = H0*R0 + H1*S4 + H2*S3 + H3*S2 + H4*S1 - db $C5, $7D, $F4, $42, $00 // vpmuludq ymm8, ymm0, ymmword ptr [rdx] - db $C5, $75, $F4, $AA, $00, $01, $00, $00 // vpmuludq ymm13, ymm1, ymmword ptr [rdx + 256] - db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 - db $C5, $6D, $F4, $AA, $E0, $00, $00, $00 // vpmuludq ymm13, ymm2, ymmword ptr [rdx + 224] - db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 - db $C5, $65, $F4, $AA, $C0, $00, $00, $00 // vpmuludq ymm13, ymm3, ymmword ptr [rdx + 192] - db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 - db $C5, $5D, $F4, $AA, $A0, $00, $00, $00 // vpmuludq ymm13, ymm4, ymmword ptr [rdx + 160] ; S1 - db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 - - // ---- Lazy reduce D0..D4 (ymm8..ymm12) -> H0..H4 (ymm0..ymm4) ---- - db $C4, $C1, $15, $73, $D0, $1A // vpsrlq ymm13, ymm8, 26 - db $C5, $BD, $DB, $C5 // vpand ymm0, ymm8, ymm5 - db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 ; D1 += D0>>26 - db $C4, $C1, $15, $73, $D1, $1A // vpsrlq ymm13, ymm9, 26 - db $C5, $B5, $DB, $CD // vpand ymm1, ymm9, ymm5 - db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 ; D2 += D1>>26 - db $C4, $C1, $15, $73, $D2, $1A // vpsrlq ymm13, ymm10, 26 - db $C5, $AD, $DB, $D5 // vpand ymm2, ymm10, ymm5 - db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 ; D3 += D2>>26 - db $C4, $C1, $15, $73, $D3, $1A // vpsrlq ymm13, ymm11, 26 - db $C5, $A5, $DB, $DD // vpand ymm3, ymm11, ymm5 - db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 ; D4 += D3>>26 - db $C4, $C1, $15, $73, $D4, $1A // vpsrlq ymm13, ymm12, 26 - db $C5, $9D, $DB, $E5 // vpand ymm4, ymm12, ymm5 - db $C4, $C1, $05, $73, $F5, $02 // vpsllq ymm15, ymm13, 2 - db $C4, $41, $15, $D4, $EF // vpaddq ymm13, ymm13, ymm15 ; (D4>>26) *= 5 - db $C4, $C1, $7D, $D4, $C5 // vpaddq ymm0, ymm0, ymm13 ; H0 += (D4>>26)*5 - db $C5, $95, $73, $D0, $1A // vpsrlq ymm13, ymm0, 26 - db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 - db $C4, $C1, $75, $D4, $CD // vpaddq ymm1, ymm1, ymm13 ; H1 += H0>>26 - - // ---- Load + decompress + absorb next 4 blocks ---- - db $C4, $41, $7A, $6F, $20 // vmovdqu xmm12, xmmword ptr [r8] - db $C4, $41, $7A, $6F, $68, $10 // vmovdqu xmm13, xmmword ptr [r8 + 16] - db $C4, $43, $1D, $38, $60, $20, $01 // vinserti128 ymm12, ymm12, xmmword ptr [r8 + 32], 1 - db $C4, $43, $15, $38, $68, $30, $01 // vinserti128 ymm13, ymm13, xmmword ptr [r8 + 48], 1 + // ---- Bulk: H *= r^4 (broadcast) ---- + db $C5, $7D, $F4, $A2, $80, $00, $00, $00 // vpmuludq ymm12, ymm0, [rdx + 128] + db $C5, $75, $F4, $6A, $60 // vpmuludq ymm13, ymm1, [rdx + 96] + db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 + db $C5, $6D, $F4, $6A, $40 // vpmuludq ymm13, ymm2, [rdx + 64] + db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 + db $C5, $65, $F4, $6A, $20 // vpmuludq ymm13, ymm3, [rdx + 32] + db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 + db $C5, $5D, $F4, $2A // vpmuludq ymm13, ymm4, [rdx] + db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 + db $C5, $7D, $F4, $5A, $60 // vpmuludq ymm11, ymm0, [rdx + 96] + db $C5, $75, $F4, $6A, $40 // vpmuludq ymm13, ymm1, [rdx + 64] + db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 + db $C5, $6D, $F4, $6A, $20 // vpmuludq ymm13, ymm2, [rdx + 32] + db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 + db $C5, $65, $F4, $2A // vpmuludq ymm13, ymm3, [rdx] + db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 + db $C5, $5D, $F4, $AA, $00, $01, $00, $00 // vpmuludq ymm13, ymm4, [rdx + 256] + db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 + db $C5, $7D, $F4, $52, $40 // vpmuludq ymm10, ymm0, [rdx + 64] + db $C5, $75, $F4, $6A, $20 // vpmuludq ymm13, ymm1, [rdx + 32] + db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 + db $C5, $6D, $F4, $2A // vpmuludq ymm13, ymm2, [rdx] + db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 + db $C5, $65, $F4, $AA, $00, $01, $00, $00 // vpmuludq ymm13, ymm3, [rdx + 256] + db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 + db $C5, $5D, $F4, $AA, $E0, $00, $00, $00 // vpmuludq ymm13, ymm4, [rdx + 224] + db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 + db $C5, $7D, $F4, $4A, $20 // vpmuludq ymm9, ymm0, [rdx + 32] + db $C5, $75, $F4, $2A // vpmuludq ymm13, ymm1, [rdx] + db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 + db $C5, $6D, $F4, $AA, $00, $01, $00, $00 // vpmuludq ymm13, ymm2, [rdx + 256] + db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 + db $C5, $65, $F4, $AA, $E0, $00, $00, $00 // vpmuludq ymm13, ymm3, [rdx + 224] + db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 + db $C5, $5D, $F4, $AA, $C0, $00, $00, $00 // vpmuludq ymm13, ymm4, [rdx + 192] + db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 + db $C5, $7D, $F4, $02 // vpmuludq ymm8, ymm0, [rdx] + db $C5, $75, $F4, $AA, $00, $01, $00, $00 // vpmuludq ymm13, ymm1, [rdx + 256] + db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 + db $C5, $6D, $F4, $AA, $E0, $00, $00, $00 // vpmuludq ymm13, ymm2, [rdx + 224] + db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 + db $C5, $65, $F4, $AA, $C0, $00, $00, $00 // vpmuludq ymm13, ymm3, [rdx + 192] + db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 + db $C5, $5D, $F4, $AA, $A0, $00, $00, $00 // vpmuludq ymm13, ymm4, [rdx + 160] + db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 + // ---- Lazy reduce (two interleaved carry chains) ---- + db $C4, $C1, $15, $73, $D0, $1A // vpsrlq ymm13, ymm8, 26 + db $C4, $C1, $0D, $73, $D3, $1A // vpsrlq ymm14, ymm11, 26 + db $C5, $BD, $DB, $C5 // vpand ymm0, ymm8, ymm5 + db $C5, $25, $DB, $DD // vpand ymm11, ymm11, ymm5 + db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 + db $C4, $41, $1D, $D4, $E6 // vpaddq ymm12, ymm12, ymm14 + db $C4, $C1, $15, $73, $D1, $1A // vpsrlq ymm13, ymm9, 26 + db $C4, $C1, $0D, $73, $D4, $1A // vpsrlq ymm14, ymm12, 26 + db $C5, $B5, $DB, $CD // vpand ymm1, ymm9, ymm5 + db $C5, $9D, $DB, $E5 // vpand ymm4, ymm12, ymm5 + db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 + db $C4, $C1, $05, $73, $F6, $02 // vpsllq ymm15, ymm14, 2 + db $C4, $41, $0D, $D4, $F7 // vpaddq ymm14, ymm14, ymm15 + db $C4, $C1, $7D, $D4, $C6 // vpaddq ymm0, ymm0, ymm14 + db $C4, $C1, $15, $73, $D2, $1A // vpsrlq ymm13, ymm10, 26 + db $C5, $8D, $73, $D0, $1A // vpsrlq ymm14, ymm0, 26 + db $C5, $AD, $DB, $D5 // vpand ymm2, ymm10, ymm5 + db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 + db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 + db $C4, $C1, $75, $D4, $CE // vpaddq ymm1, ymm1, ymm14 + db $C4, $C1, $15, $73, $D3, $1A // vpsrlq ymm13, ymm11, 26 + db $C5, $A5, $DB, $DD // vpand ymm3, ymm11, ymm5 + db $C4, $C1, $5D, $D4, $E5 // vpaddq ymm4, ymm4, ymm13 + // ---- Absorb next 4 blocks ---- + db $C4, $41, $7A, $6F, $20 // vmovdqu xmm12, [r8] + db $C4, $41, $7A, $6F, $68, $10 // vmovdqu xmm13, [r8 + 16] + db $C4, $43, $1D, $38, $60, $20, $01 // vinserti128 ymm12, ymm12, [r8 + 32], 1 + db $C4, $43, $15, $38, $68, $30, $01 // vinserti128 ymm13, ymm13, [r8 + 48], 1 add r8, 64 - db $C4, $C1, $0D, $73, $DC, $06 // vpsrldq ymm14, ymm12, 6 - db $C4, $C1, $05, $73, $DD, $06 // vpsrldq ymm15, ymm13, 6 - db $C4, $C1, $1D, $6D, $FD // vpunpckhqdq ymm7, ymm12, ymm13 - db $C4, $41, $1D, $6C, $E5 // vpunpcklqdq ymm12, ymm12, ymm13 - db $C4, $41, $0D, $6C, $F7 // vpunpcklqdq ymm14, ymm14, ymm15 - db $C4, $C1, $05, $73, $D6, $1E // vpsrlq ymm15, ymm14, 30 - db $C4, $C1, $0D, $73, $D6, $04 // vpsrlq ymm14, ymm14, 4 - db $C4, $C1, $15, $73, $D4, $1A // vpsrlq ymm13, ymm12, 26 - db $C5, $C5, $73, $D7, $28 // vpsrlq ymm7, ymm7, 40 - db $C5, $1D, $DB, $E5 // vpand ymm12, ymm12, ymm5 - db $C5, $15, $DB, $ED // vpand ymm13, ymm13, ymm5 - db $C5, $0D, $DB, $F5 // vpand ymm14, ymm14, ymm5 - db $C5, $05, $DB, $FD // vpand ymm15, ymm15, ymm5 - db $C5, $C5, $EB, $FE // vpor ymm7, ymm7, ymm6 - db $C4, $C1, $7D, $D4, $C4 // vpaddq ymm0, ymm0, ymm12 - db $C4, $C1, $75, $D4, $CD // vpaddq ymm1, ymm1, ymm13 - db $C4, $C1, $6D, $D4, $D6 // vpaddq ymm2, ymm2, ymm14 - db $C4, $C1, $65, $D4, $DF // vpaddq ymm3, ymm3, ymm15 - db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 - + db $C4, $C1, $0D, $73, $DC, $06 // vpsrldq ymm14, ymm12, 6 + db $C4, $C1, $05, $73, $DD, $06 // vpsrldq ymm15, ymm13, 6 + db $C4, $C1, $1D, $6D, $FD // vpunpckhqdq ymm7, ymm12, ymm13 + db $C4, $41, $1D, $6C, $E5 // vpunpcklqdq ymm12, ymm12, ymm13 + db $C4, $41, $0D, $6C, $F7 // vpunpcklqdq ymm14, ymm14, ymm15 + db $C4, $C1, $05, $73, $D6, $1E // vpsrlq ymm15, ymm14, 30 + db $C4, $C1, $0D, $73, $D6, $04 // vpsrlq ymm14, ymm14, 4 + db $C4, $C1, $15, $73, $D4, $1A // vpsrlq ymm13, ymm12, 26 + db $C5, $C5, $73, $D7, $28 // vpsrlq ymm7, ymm7, 40 + db $C5, $1D, $DB, $E5 // vpand ymm12, ymm12, ymm5 + db $C5, $15, $DB, $ED // vpand ymm13, ymm13, ymm5 + db $C5, $0D, $DB, $F5 // vpand ymm14, ymm14, ymm5 + db $C5, $05, $DB, $FD // vpand ymm15, ymm15, ymm5 + db $C5, $C5, $EB, $FE // vpor ymm7, ymm7, ymm6 + db $C4, $C1, $7D, $D4, $C4 // vpaddq ymm0, ymm0, ymm12 + db $C4, $C1, $75, $D4, $CD // vpaddq ymm1, ymm1, ymm13 + db $C4, $C1, $6D, $D4, $D6 // vpaddq ymm2, ymm2, ymm14 + db $C4, $C1, $65, $D4, $DF // vpaddq ymm3, ymm3, ymm15 + db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 sub r9, 64 jnz @@poly1305_avx2_loop @@poly1305_avx2_tail: - // ---- Tail: H *= [r^1, r^2, r^3, r^4] (offset+4 = shifted form) ---- - // D4 (ymm12) - table loads at +4 over the bulk offsets - db $C5, $7D, $F4, $A2, $84, $00, $00, $00 // vpmuludq ymm12, ymm0, ymmword ptr [rdx + 132] - db $C5, $75, $F4, $AA, $64, $00, $00, $00 // vpmuludq ymm13, ymm1, ymmword ptr [rdx + 100] - db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 - db $C5, $6D, $F4, $AA, $44, $00, $00, $00 // vpmuludq ymm13, ymm2, ymmword ptr [rdx + 68] - db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 - db $C5, $65, $F4, $6A, $24 // vpmuludq ymm13, ymm3, ymmword ptr [rdx + 36] - db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 - db $C5, $5D, $F4, $6A, $04 // vpmuludq ymm13, ymm4, ymmword ptr [rdx + 4] - db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 - - // D3 (ymm11) - db $C5, $7D, $F4, $9A, $64, $00, $00, $00 // vpmuludq ymm11, ymm0, ymmword ptr [rdx + 100] - db $C5, $75, $F4, $AA, $44, $00, $00, $00 // vpmuludq ymm13, ymm1, ymmword ptr [rdx + 68] - db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 - db $C5, $6D, $F4, $6A, $24 // vpmuludq ymm13, ymm2, ymmword ptr [rdx + 36] - db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 - db $C5, $65, $F4, $6A, $04 // vpmuludq ymm13, ymm3, ymmword ptr [rdx + 4] - db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 - db $C5, $5D, $F4, $AA, $04, $01, $00, $00 // vpmuludq ymm13, ymm4, ymmword ptr [rdx + 260] ; S4 shifted - db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 - - // D2 (ymm10) - db $C5, $7D, $F4, $92, $44, $00, $00, $00 // vpmuludq ymm10, ymm0, ymmword ptr [rdx + 68] - db $C5, $75, $F4, $6A, $24 // vpmuludq ymm13, ymm1, ymmword ptr [rdx + 36] - db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 - db $C5, $6D, $F4, $6A, $04 // vpmuludq ymm13, ymm2, ymmword ptr [rdx + 4] - db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 - db $C5, $65, $F4, $AA, $04, $01, $00, $00 // vpmuludq ymm13, ymm3, ymmword ptr [rdx + 260] - db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 - db $C5, $5D, $F4, $AA, $E4, $00, $00, $00 // vpmuludq ymm13, ymm4, ymmword ptr [rdx + 228] ; S3 shifted - db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 - - // D1 (ymm9) - db $C5, $7D, $F4, $4A, $24 // vpmuludq ymm9, ymm0, ymmword ptr [rdx + 36] - db $C5, $75, $F4, $6A, $04 // vpmuludq ymm13, ymm1, ymmword ptr [rdx + 4] - db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 - db $C5, $6D, $F4, $AA, $04, $01, $00, $00 // vpmuludq ymm13, ymm2, ymmword ptr [rdx + 260] - db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 - db $C5, $65, $F4, $AA, $E4, $00, $00, $00 // vpmuludq ymm13, ymm3, ymmword ptr [rdx + 228] - db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 - db $C5, $5D, $F4, $AA, $C4, $00, $00, $00 // vpmuludq ymm13, ymm4, ymmword ptr [rdx + 196] ; S2 shifted - db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 - - // D0 (ymm8) - db $C5, $7D, $F4, $42, $04 // vpmuludq ymm8, ymm0, ymmword ptr [rdx + 4] - db $C5, $75, $F4, $AA, $04, $01, $00, $00 // vpmuludq ymm13, ymm1, ymmword ptr [rdx + 260] - db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 - db $C5, $6D, $F4, $AA, $E4, $00, $00, $00 // vpmuludq ymm13, ymm2, ymmword ptr [rdx + 228] - db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 - db $C5, $65, $F4, $AA, $C4, $00, $00, $00 // vpmuludq ymm13, ymm3, ymmword ptr [rdx + 196] - db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 - db $C5, $5D, $F4, $AA, $A4, $00, $00, $00 // vpmuludq ymm13, ymm4, ymmword ptr [rdx + 164] ; S1 shifted - db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 - + // ---- Tail: H *= [r^1, r^2, r^3, r^4] (shifted table read) ---- + db $C5, $7D, $F4, $A2, $84, $00, $00, $00 // vpmuludq ymm12, ymm0, [rdx + 132] + db $C5, $75, $F4, $6A, $64 // vpmuludq ymm13, ymm1, [rdx + 100] + db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 + db $C5, $6D, $F4, $6A, $44 // vpmuludq ymm13, ymm2, [rdx + 68] + db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 + db $C5, $65, $F4, $6A, $24 // vpmuludq ymm13, ymm3, [rdx + 36] + db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 + db $C5, $5D, $F4, $6A, $04 // vpmuludq ymm13, ymm4, [rdx + 4] + db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 + db $C5, $7D, $F4, $5A, $64 // vpmuludq ymm11, ymm0, [rdx + 100] + db $C5, $75, $F4, $6A, $44 // vpmuludq ymm13, ymm1, [rdx + 68] + db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 + db $C5, $6D, $F4, $6A, $24 // vpmuludq ymm13, ymm2, [rdx + 36] + db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 + db $C5, $65, $F4, $6A, $04 // vpmuludq ymm13, ymm3, [rdx + 4] + db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 + db $C5, $5D, $F4, $AA, $04, $01, $00, $00 // vpmuludq ymm13, ymm4, [rdx + 260] + db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 + db $C5, $7D, $F4, $52, $44 // vpmuludq ymm10, ymm0, [rdx + 68] + db $C5, $75, $F4, $6A, $24 // vpmuludq ymm13, ymm1, [rdx + 36] + db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 + db $C5, $6D, $F4, $6A, $04 // vpmuludq ymm13, ymm2, [rdx + 4] + db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 + db $C5, $65, $F4, $AA, $04, $01, $00, $00 // vpmuludq ymm13, ymm3, [rdx + 260] + db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 + db $C5, $5D, $F4, $AA, $E4, $00, $00, $00 // vpmuludq ymm13, ymm4, [rdx + 228] + db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 + db $C5, $7D, $F4, $4A, $24 // vpmuludq ymm9, ymm0, [rdx + 36] + db $C5, $75, $F4, $6A, $04 // vpmuludq ymm13, ymm1, [rdx + 4] + db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 + db $C5, $6D, $F4, $AA, $04, $01, $00, $00 // vpmuludq ymm13, ymm2, [rdx + 260] + db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 + db $C5, $65, $F4, $AA, $E4, $00, $00, $00 // vpmuludq ymm13, ymm3, [rdx + 228] + db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 + db $C5, $5D, $F4, $AA, $C4, $00, $00, $00 // vpmuludq ymm13, ymm4, [rdx + 196] + db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 + db $C5, $7D, $F4, $42, $04 // vpmuludq ymm8, ymm0, [rdx + 4] + db $C5, $75, $F4, $AA, $04, $01, $00, $00 // vpmuludq ymm13, ymm1, [rdx + 260] + db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 + db $C5, $6D, $F4, $AA, $E4, $00, $00, $00 // vpmuludq ymm13, ymm2, [rdx + 228] + db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 + db $C5, $65, $F4, $AA, $C4, $00, $00, $00 // vpmuludq ymm13, ymm3, [rdx + 196] + db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 + db $C5, $5D, $F4, $AA, $A4, $00, $00, $00 // vpmuludq ymm13, ymm4, [rdx + 164] + db $C4, $41, $3D, $D4, $C5 // vpaddq ymm8, ymm8, ymm13 // ---- Tail lazy reduce ---- - db $C4, $C1, $15, $73, $D0, $1A // vpsrlq ymm13, ymm8, 26 - db $C5, $BD, $DB, $C5 // vpand ymm0, ymm8, ymm5 - db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 - db $C4, $C1, $15, $73, $D1, $1A // vpsrlq ymm13, ymm9, 26 - db $C5, $B5, $DB, $CD // vpand ymm1, ymm9, ymm5 - db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 - db $C4, $C1, $15, $73, $D2, $1A // vpsrlq ymm13, ymm10, 26 - db $C5, $AD, $DB, $D5 // vpand ymm2, ymm10, ymm5 - db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 - db $C4, $C1, $15, $73, $D3, $1A // vpsrlq ymm13, ymm11, 26 - db $C5, $A5, $DB, $DD // vpand ymm3, ymm11, ymm5 - db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 - db $C4, $C1, $15, $73, $D4, $1A // vpsrlq ymm13, ymm12, 26 - db $C5, $9D, $DB, $E5 // vpand ymm4, ymm12, ymm5 - db $C4, $C1, $05, $73, $F5, $02 // vpsllq ymm15, ymm13, 2 - db $C4, $41, $15, $D4, $EF // vpaddq ymm13, ymm13, ymm15 - db $C4, $C1, $7D, $D4, $C5 // vpaddq ymm0, ymm0, ymm13 - db $C5, $95, $73, $D0, $1A // vpsrlq ymm13, ymm0, 26 - db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 - db $C4, $C1, $75, $D4, $CD // vpaddq ymm1, ymm1, ymm13 - - // ---- Horizontal sum across 4 lanes for ymm0..ymm4 ---- - db $C5, $C5, $73, $D8, $08 // vpsrldq ymm7, ymm0, 8 - db $C5, $FD, $D4, $C7 // vpaddq ymm0, ymm0, ymm7 - db $C4, $E3, $FD, $00, $F8, $4E // vpermq ymm7, ymm0, 0x4E - db $C5, $FD, $D4, $C7 // vpaddq ymm0, ymm0, ymm7 - db $C5, $C5, $73, $D9, $08 // vpsrldq ymm7, ymm1, 8 - db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 - db $C4, $E3, $FD, $00, $F9, $4E // vpermq ymm7, ymm1, 0x4E - db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 - db $C5, $C5, $73, $DA, $08 // vpsrldq ymm7, ymm2, 8 - db $C5, $ED, $D4, $D7 // vpaddq ymm2, ymm2, ymm7 - db $C4, $E3, $FD, $00, $FA, $4E // vpermq ymm7, ymm2, 0x4E - db $C5, $ED, $D4, $D7 // vpaddq ymm2, ymm2, ymm7 - db $C5, $C5, $73, $DB, $08 // vpsrldq ymm7, ymm3, 8 - db $C5, $E5, $D4, $DF // vpaddq ymm3, ymm3, ymm7 - db $C4, $E3, $FD, $00, $FB, $4E // vpermq ymm7, ymm3, 0x4E - db $C5, $E5, $D4, $DF // vpaddq ymm3, ymm3, ymm7 - db $C5, $C5, $73, $DC, $08 // vpsrldq ymm7, ymm4, 8 - db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 - db $C4, $E3, $FD, $00, $FC, $4E // vpermq ymm7, ymm4, 0x4E - db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 - - // ---- Final lazy reduce on the now-scalar limbs (lane 0) ---- - db $C5, $95, $73, $D0, $1A // vpsrlq ymm13, ymm0, 26 - db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 - db $C4, $C1, $75, $D4, $CD // vpaddq ymm1, ymm1, ymm13 - db $C5, $95, $73, $D1, $1A // vpsrlq ymm13, ymm1, 26 - db $C5, $F5, $DB, $CD // vpand ymm1, ymm1, ymm5 - db $C4, $C1, $6D, $D4, $D5 // vpaddq ymm2, ymm2, ymm13 - db $C5, $95, $73, $D2, $1A // vpsrlq ymm13, ymm2, 26 - db $C5, $ED, $DB, $D5 // vpand ymm2, ymm2, ymm5 - db $C4, $C1, $65, $D4, $DD // vpaddq ymm3, ymm3, ymm13 - db $C5, $95, $73, $D3, $1A // vpsrlq ymm13, ymm3, 26 - db $C5, $E5, $DB, $DD // vpand ymm3, ymm3, ymm5 - db $C4, $C1, $5D, $D4, $E5 // vpaddq ymm4, ymm4, ymm13 - db $C5, $95, $73, $D4, $1A // vpsrlq ymm13, ymm4, 26 - db $C5, $DD, $DB, $E5 // vpand ymm4, ymm4, ymm5 - db $C4, $C1, $05, $73, $F5, $02 // vpsllq ymm15, ymm13, 2 - db $C4, $41, $15, $D4, $EF // vpaddq ymm13, ymm13, ymm15 - db $C4, $C1, $7D, $D4, $C5 // vpaddq ymm0, ymm0, ymm13 - db $C5, $95, $73, $D0, $1A // vpsrlq ymm13, ymm0, 26 - db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 - db $C4, $C1, $75, $D4, $CD // vpaddq ymm1, ymm1, ymm13 - - // ---- Store h0..h4 back to ctx ---- - db $C5, $F9, $7E, $41, $24 // vmovd dword ptr [rcx + 36], xmm0 - db $C5, $F9, $7E, $49, $28 // vmovd dword ptr [rcx + 40], xmm1 - db $C5, $F9, $7E, $51, $2C // vmovd dword ptr [rcx + 44], xmm2 - db $C5, $F9, $7E, $59, $30 // vmovd dword ptr [rcx + 48], xmm3 - db $C5, $F9, $7E, $61, $34 // vmovd dword ptr [rcx + 52], xmm4 - - db $C5, $F8, $77 // vzeroupper - // restore caller xmm6..15 (legacy SSE moves are safe after vzeroupper) + db $C4, $C1, $15, $73, $D0, $1A // vpsrlq ymm13, ymm8, 26 + db $C5, $BD, $DB, $C5 // vpand ymm0, ymm8, ymm5 + db $C4, $41, $35, $D4, $CD // vpaddq ymm9, ymm9, ymm13 + db $C4, $C1, $15, $73, $D1, $1A // vpsrlq ymm13, ymm9, 26 + db $C5, $B5, $DB, $CD // vpand ymm1, ymm9, ymm5 + db $C4, $41, $2D, $D4, $D5 // vpaddq ymm10, ymm10, ymm13 + db $C4, $C1, $15, $73, $D2, $1A // vpsrlq ymm13, ymm10, 26 + db $C5, $AD, $DB, $D5 // vpand ymm2, ymm10, ymm5 + db $C4, $41, $25, $D4, $DD // vpaddq ymm11, ymm11, ymm13 + db $C4, $C1, $15, $73, $D3, $1A // vpsrlq ymm13, ymm11, 26 + db $C5, $A5, $DB, $DD // vpand ymm3, ymm11, ymm5 + db $C4, $41, $1D, $D4, $E5 // vpaddq ymm12, ymm12, ymm13 + db $C4, $C1, $15, $73, $D4, $1A // vpsrlq ymm13, ymm12, 26 + db $C5, $9D, $DB, $E5 // vpand ymm4, ymm12, ymm5 + db $C4, $C1, $05, $73, $F5, $02 // vpsllq ymm15, ymm13, 2 + db $C4, $41, $15, $D4, $EF // vpaddq ymm13, ymm13, ymm15 + db $C4, $C1, $7D, $D4, $C5 // vpaddq ymm0, ymm0, ymm13 + db $C5, $95, $73, $D0, $1A // vpsrlq ymm13, ymm0, 26 + db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 + db $C4, $C1, $75, $D4, $CD // vpaddq ymm1, ymm1, ymm13 + // ---- Horizontal sum 4 lanes -> lane 0 ---- + db $C5, $C5, $73, $D8, $08 // vpsrldq ymm7, ymm0, 8 + db $C5, $FD, $D4, $C7 // vpaddq ymm0, ymm0, ymm7 + db $C4, $E3, $FD, $00, $F8, $4E // vpermq ymm7, ymm0, 0x4E + db $C5, $FD, $D4, $C7 // vpaddq ymm0, ymm0, ymm7 + db $C5, $C5, $73, $D9, $08 // vpsrldq ymm7, ymm1, 8 + db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 + db $C4, $E3, $FD, $00, $F9, $4E // vpermq ymm7, ymm1, 0x4E + db $C5, $F5, $D4, $CF // vpaddq ymm1, ymm1, ymm7 + db $C5, $C5, $73, $DA, $08 // vpsrldq ymm7, ymm2, 8 + db $C5, $ED, $D4, $D7 // vpaddq ymm2, ymm2, ymm7 + db $C4, $E3, $FD, $00, $FA, $4E // vpermq ymm7, ymm2, 0x4E + db $C5, $ED, $D4, $D7 // vpaddq ymm2, ymm2, ymm7 + db $C5, $C5, $73, $DB, $08 // vpsrldq ymm7, ymm3, 8 + db $C5, $E5, $D4, $DF // vpaddq ymm3, ymm3, ymm7 + db $C4, $E3, $FD, $00, $FB, $4E // vpermq ymm7, ymm3, 0x4E + db $C5, $E5, $D4, $DF // vpaddq ymm3, ymm3, ymm7 + db $C5, $C5, $73, $DC, $08 // vpsrldq ymm7, ymm4, 8 + db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 + db $C4, $E3, $FD, $00, $FC, $4E // vpermq ymm7, ymm4, 0x4E + db $C5, $DD, $D4, $E7 // vpaddq ymm4, ymm4, ymm7 + // ---- Final lazy reduce (lane 0 scalars) ---- + db $C5, $95, $73, $D0, $1A // vpsrlq ymm13, ymm0, 26 + db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 + db $C4, $C1, $75, $D4, $CD // vpaddq ymm1, ymm1, ymm13 + db $C5, $95, $73, $D1, $1A // vpsrlq ymm13, ymm1, 26 + db $C5, $F5, $DB, $CD // vpand ymm1, ymm1, ymm5 + db $C4, $C1, $6D, $D4, $D5 // vpaddq ymm2, ymm2, ymm13 + db $C5, $95, $73, $D2, $1A // vpsrlq ymm13, ymm2, 26 + db $C5, $ED, $DB, $D5 // vpand ymm2, ymm2, ymm5 + db $C4, $C1, $65, $D4, $DD // vpaddq ymm3, ymm3, ymm13 + db $C5, $95, $73, $D3, $1A // vpsrlq ymm13, ymm3, 26 + db $C5, $E5, $DB, $DD // vpand ymm3, ymm3, ymm5 + db $C4, $C1, $5D, $D4, $E5 // vpaddq ymm4, ymm4, ymm13 + db $C5, $95, $73, $D4, $1A // vpsrlq ymm13, ymm4, 26 + db $C5, $DD, $DB, $E5 // vpand ymm4, ymm4, ymm5 + db $C4, $C1, $05, $73, $F5, $02 // vpsllq ymm15, ymm13, 2 + db $C4, $41, $15, $D4, $EF // vpaddq ymm13, ymm13, ymm15 + db $C4, $C1, $7D, $D4, $C5 // vpaddq ymm0, ymm0, ymm13 + db $C5, $95, $73, $D0, $1A // vpsrlq ymm13, ymm0, 26 + db $C5, $FD, $DB, $C5 // vpand ymm0, ymm0, ymm5 + db $C4, $C1, $75, $D4, $CD // vpaddq ymm1, ymm1, ymm13 + // ---- Store H0..H4 back to ctx ---- + db $C5, $F9, $7E, $41, $24 // vmovd dword ptr [rcx + 36], xmm0 + db $C5, $F9, $7E, $49, $28 // vmovd dword ptr [rcx + 40], xmm1 + db $C5, $F9, $7E, $51, $2C // vmovd dword ptr [rcx + 44], xmm2 + db $C5, $F9, $7E, $59, $30 // vmovd dword ptr [rcx + 48], xmm3 + db $C5, $F9, $7E, $61, $34 // vmovd dword ptr [rcx + 52], xmm4 + db $C5, $F8, $77 // vzeroupper {$I ..\..\Include\Simd\Common\ClpSimdNonVolatileRestore_x86_64.inc} From 4a59b0ff00a426bc391b603dec282a422f3ea1d6 Mon Sep 17 00:00:00 2001 From: Ugochukwu Mmaduekwe Date: Thu, 9 Jul 2026 22:42:42 +0100 Subject: [PATCH 6/6] Hoist the AVX2 8-way ChaCha rot masks out of the per-quarter-round loads The rot16/rot8 rotations used vpshufb ymm, ymm, [rsp+mask], reloading the shuffle control from the stack on every quarter-round - ~160 mask loads per 512-byte block, all landing on the load ports that the c-word spills already contend for. At each rotate step the quarter-round temp registers are free, so load the mask into a temp once per rotate phase and use vpshufb ymm, ymm, ymm for all four lanes. The pshufb count (and its port pressure) is unchanged, but mask loads drop to ~40 per 512-byte block - a strict reduction of ~120 load micro-ops per block, relieving the load ports the c-spills bottleneck on. --- .../ChaCha/ChaCha7539Blocks8Avx2_x86_64.inc | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks8Avx2_x86_64.inc b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks8Avx2_x86_64.inc index bd2c7065..0fd47d0c 100644 --- a/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks8Avx2_x86_64.inc +++ b/CryptoLib/src/Include/Simd/ChaCha/ChaCha7539Blocks8Avx2_x86_64.inc @@ -88,10 +88,11 @@ db $C5, $15, $EF, $E9 // vpxor ymm13, ymm13, ymm1 db $C5, $0D, $EF, $F2 // vpxor ymm14, ymm14, ymm2 db $C5, $05, $EF, $FB // vpxor ymm15, ymm15, ymm3 - db $C4, $62, $1D, $00, $A4, $24, $A0, $02, $00, $00 // vpshufb ymm12, ymm12, [rsp + 672] - db $C4, $62, $15, $00, $AC, $24, $A0, $02, $00, $00 // vpshufb ymm13, ymm13, [rsp + 672] - db $C4, $62, $0D, $00, $B4, $24, $A0, $02, $00, $00 // vpshufb ymm14, ymm14, [rsp + 672] - db $C4, $62, $05, $00, $BC, $24, $A0, $02, $00, $00 // vpshufb ymm15, ymm15, [rsp + 672] + db $C5, $7E, $6F, $84, $24, $A0, $02, $00, $00 // vmovdqu ymm8, [rsp + 672] + db $C4, $42, $1D, $00, $E0 // vpshufb ymm12, ymm12, ymm8 + db $C4, $42, $15, $00, $E8 // vpshufb ymm13, ymm13, ymm8 + db $C4, $42, $0D, $00, $F0 // vpshufb ymm14, ymm14, ymm8 + db $C4, $42, $05, $00, $F8 // vpshufb ymm15, ymm15, ymm8 db $C5, $7E, $6F, $04, $24 // vmovdqu ymm8, [rsp] db $C5, $7E, $6F, $4C, $24, $20 // vmovdqu ymm9, [rsp + 32] db $C5, $7E, $6F, $54, $24, $40 // vmovdqu ymm10, [rsp + 64] @@ -128,10 +129,11 @@ db $C5, $15, $EF, $E9 // vpxor ymm13, ymm13, ymm1 db $C5, $0D, $EF, $F2 // vpxor ymm14, ymm14, ymm2 db $C5, $05, $EF, $FB // vpxor ymm15, ymm15, ymm3 - db $C4, $62, $1D, $00, $A4, $24, $C0, $02, $00, $00 // vpshufb ymm12, ymm12, [rsp + 704] - db $C4, $62, $15, $00, $AC, $24, $C0, $02, $00, $00 // vpshufb ymm13, ymm13, [rsp + 704] - db $C4, $62, $0D, $00, $B4, $24, $C0, $02, $00, $00 // vpshufb ymm14, ymm14, [rsp + 704] - db $C4, $62, $05, $00, $BC, $24, $C0, $02, $00, $00 // vpshufb ymm15, ymm15, [rsp + 704] + db $C5, $7E, $6F, $84, $24, $C0, $02, $00, $00 // vmovdqu ymm8, [rsp + 704] + db $C4, $42, $1D, $00, $E0 // vpshufb ymm12, ymm12, ymm8 + db $C4, $42, $15, $00, $E8 // vpshufb ymm13, ymm13, ymm8 + db $C4, $42, $0D, $00, $F0 // vpshufb ymm14, ymm14, ymm8 + db $C4, $42, $05, $00, $F8 // vpshufb ymm15, ymm15, ymm8 db $C5, $7E, $6F, $04, $24 // vmovdqu ymm8, [rsp] db $C5, $7E, $6F, $4C, $24, $20 // vmovdqu ymm9, [rsp + 32] db $C5, $7E, $6F, $54, $24, $40 // vmovdqu ymm10, [rsp + 64] @@ -168,10 +170,11 @@ db $C5, $1D, $EF, $E1 // vpxor ymm12, ymm12, ymm1 db $C5, $15, $EF, $EA // vpxor ymm13, ymm13, ymm2 db $C5, $0D, $EF, $F3 // vpxor ymm14, ymm14, ymm3 - db $C4, $62, $05, $00, $BC, $24, $A0, $02, $00, $00 // vpshufb ymm15, ymm15, [rsp + 672] - db $C4, $62, $1D, $00, $A4, $24, $A0, $02, $00, $00 // vpshufb ymm12, ymm12, [rsp + 672] - db $C4, $62, $15, $00, $AC, $24, $A0, $02, $00, $00 // vpshufb ymm13, ymm13, [rsp + 672] - db $C4, $62, $0D, $00, $B4, $24, $A0, $02, $00, $00 // vpshufb ymm14, ymm14, [rsp + 672] + db $C5, $7E, $6F, $84, $24, $A0, $02, $00, $00 // vmovdqu ymm8, [rsp + 672] + db $C4, $42, $05, $00, $F8 // vpshufb ymm15, ymm15, ymm8 + db $C4, $42, $1D, $00, $E0 // vpshufb ymm12, ymm12, ymm8 + db $C4, $42, $15, $00, $E8 // vpshufb ymm13, ymm13, ymm8 + db $C4, $42, $0D, $00, $F0 // vpshufb ymm14, ymm14, ymm8 db $C5, $7E, $6F, $44, $24, $40 // vmovdqu ymm8, [rsp + 64] db $C5, $7E, $6F, $4C, $24, $60 // vmovdqu ymm9, [rsp + 96] db $C5, $7E, $6F, $14, $24 // vmovdqu ymm10, [rsp] @@ -208,10 +211,11 @@ db $C5, $1D, $EF, $E1 // vpxor ymm12, ymm12, ymm1 db $C5, $15, $EF, $EA // vpxor ymm13, ymm13, ymm2 db $C5, $0D, $EF, $F3 // vpxor ymm14, ymm14, ymm3 - db $C4, $62, $05, $00, $BC, $24, $C0, $02, $00, $00 // vpshufb ymm15, ymm15, [rsp + 704] - db $C4, $62, $1D, $00, $A4, $24, $C0, $02, $00, $00 // vpshufb ymm12, ymm12, [rsp + 704] - db $C4, $62, $15, $00, $AC, $24, $C0, $02, $00, $00 // vpshufb ymm13, ymm13, [rsp + 704] - db $C4, $62, $0D, $00, $B4, $24, $C0, $02, $00, $00 // vpshufb ymm14, ymm14, [rsp + 704] + db $C5, $7E, $6F, $84, $24, $C0, $02, $00, $00 // vmovdqu ymm8, [rsp + 704] + db $C4, $42, $05, $00, $F8 // vpshufb ymm15, ymm15, ymm8 + db $C4, $42, $1D, $00, $E0 // vpshufb ymm12, ymm12, ymm8 + db $C4, $42, $15, $00, $E8 // vpshufb ymm13, ymm13, ymm8 + db $C4, $42, $0D, $00, $F0 // vpshufb ymm14, ymm14, ymm8 db $C5, $7E, $6F, $44, $24, $40 // vmovdqu ymm8, [rsp + 64] db $C5, $7E, $6F, $4C, $24, $60 // vmovdqu ymm9, [rsp + 96] db $C5, $7E, $6F, $14, $24 // vmovdqu ymm10, [rsp]