Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions HashLib/src/Include/Simd/Adler32/Adler32BlocksAvx2_i386.inc
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// AVX2 implementation of Adler-32 block processing (IA-32; 256-bit ymm
// integer ops work in 32-bit mode - only ymm0-7 exist, which this kernel
// fits). Same structure as Adler32BlocksAvx2_x86_64.inc.
// IA-32: after HlpSimdProc4Begin_i386 - ebx = data ptr, esi = num_blocks,
// AVX2 implementation of Adler-32 block processing (num_blocks x 32-byte blocks;
// IA-32: 256-bit ymm integer ops work in 32-bit mode and only ymm0-ymm7 exist,
// which this kernel fits). Same structure as Adler32BlocksAvx2_x86_64.inc.
// Does NOT apply mod 65521 (the caller does).
// ABI (after HlpSimdProc4Begin_i386.inc): ebx = data ptr, esi = num_blocks,
// edi = sums ptr, eax = constants ptr (moved to ecx at entry; eax then
// accumulates SumA). SumB rides xmm1 end-to-end via vmovd memory forms.
// ASums layout: [SumA: UInt32, SumB: UInt32].
// Constants layout: [weights: 32B, ones_16: 32B] at offsets 0 and 32.
// Processes num_blocks x 32-byte blocks. Does NOT apply mod 65521 (caller does it).
// Uses ymm0-ymm5 only (all volatile on IA-32; no saves needed).
// Sums layout: [SumA: UInt32, SumB: UInt32].
// Constants layout: [weights: 32B, ones_16: 32B] at offsets 0 and 32.
// Saves: none (uses ymm0-ymm5 only; all volatile on IA-32).
// AVX/AVX2 instructions are db-encoded for broad assembler compatibility.
// Reference: Chromium zlib adler32_simd.c, HashLib Adler32BlocksAvx2_x86_64.inc.

Expand Down
17 changes: 9 additions & 8 deletions HashLib/src/Include/Simd/Adler32/Adler32BlocksAvx2_x86_64.inc
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// AVX2 implementation of Adler-32 block processing.
// Expects MS x64 ABI: rcx = data ptr, edx = num_blocks, r8 = sums ptr, r9 = constants ptr.
// ASums layout: [SumA: UInt32, SumB: UInt32].
// Constants layout: [weights: 32B, ones_16: 32B] at offsets 0 and 32.
// Processes num_blocks x 32-byte blocks. Does NOT apply mod 65521 (caller does it).
// Uses ymm0-ymm5 only (volatile under both ABIs; no saves needed).
// Weights and ones are reloaded from memory each iteration to avoid
// using non-volatile ymm registers.
// AVX2 implementation of Adler-32 block processing (num_blocks x 32-byte blocks).
// Does NOT apply mod 65521 (the caller does). Weights and ones are reloaded
// from memory each iteration so no non-volatile ymm register is needed.
// ABI (after HlpSimdProc4Begin_x86_64.inc): rcx = data ptr, edx = num_blocks,
// r8 = sums ptr, r9 = constants ptr.
// Sums layout: [SumA: UInt32, SumB: UInt32].
// Constants layout: [weights: 32B, ones_16: 32B] at offsets 0 and 32.
// Saves: none (uses ymm0-ymm5 only; volatile under both ABIs).
// AVX/AVX2 instructions are db-encoded for broad assembler compatibility.
// Reference: Chromium zlib adler32_simd.c.

// Zero register
db $C5, $E5, $EF, $DB // vpxor ymm3, ymm3, ymm3
Expand Down
17 changes: 10 additions & 7 deletions HashLib/src/Include/Simd/Adler32/Adler32BlocksNeon_aarch64.inc
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// Adler-32 ProcessBlocks AArch64 NEON implementation (32-byte blocks).
// Expects AAPCS64: x0 = AData, w1 = ANumBlocks, x2 = ASums, x3 = AConstants.
// ASums layout: [SumA: UInt32, SumB: UInt32]. Does NOT apply mod 65521.
// Constants layout matches Adler32Constants: bytes [32..1] at offset 0..31.
// Leaf nostackframe; caller-saved GPR/vector only.
// Reference: Chromium zlib adler32_simd.c, HashLib Adler32BlocksSsse3_x86_64.inc.
// AArch64 vector instructions are .long-encoded for broad assembler compatibility.
// NEON implementation of Adler-32 block processing (num_blocks x 32-byte blocks).
// Does NOT apply mod 65521 (the caller does).
// ABI (after HlpSimdProc4Begin_aarch64.inc): x0 = data ptr, w1 = num_blocks,
// x2 = sums ptr, x3 = constants ptr.
// Sums layout: [SumA: UInt32, SumB: UInt32].
// Constants layout matches Adler32Constants: bytes [32..1] at offsets 0..31.
// Register map:
// w9 = block counter (from w1)
// w10 = SumA in / SumA out
Expand All @@ -20,6 +19,10 @@
// v24-v27 = widened weight vectors for vmlal
// v28-v29 = weight byte loads from AConstants
// v30 = ext scratch for weight / reduce halves
// Saves: none (leaf nostackframe; caller-saved GPR/vector only).
// AArch64 vector instructions are .long-encoded for broad assembler compatibility.
// Reference: Chromium zlib adler32_simd.c, HashLib Adler32BlocksSsse3_x86_64.inc.

.long 0xb940004a // ldr w10, [x2]
.long 0xb940044b // ldr w11, [x2, #4]
.long 0x1b017d4c // mul w12, w10, w1
Expand Down
32 changes: 15 additions & 17 deletions HashLib/src/Include/Simd/Adler32/Adler32BlocksSse2_i386.inc
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
// SSE2 implementation of Adler-32 block processing (IA-32).
// After HlpSimdProc4Begin_i386: ebx = AData, esi = ANumBlocks, edi = ASums, eax = AConstants.
// ASums: [SumA: UInt32, SumB: UInt32]. Constants: [weights_hi: 16B, weights_lo: 16B] (32 bytes).
// Processes num_blocks x 32-byte blocks; caller applies mod 65521.
//
// x64 uses xmm6-xmm9 for widened weights; IA-32 only has xmm0-xmm7, so widened weights
// live on stack (4 x 16 bytes). xmm6–xmm7 saved/restored defensively (volatile on i386).
//
// Same SSE2 emulation as Adler32BlocksSse2_x86_64.inc (punpcklbw/hbw + pmaddwd).
//
// Stack layout (sub esp, 96):
// [esp + 0..15]: xmm6 save
// [esp + 16..31]: xmm7 save
// [esp + 32..47]: w0 (weights_hi low)
// [esp + 48..63]: w1 (weights_hi high)
// [esp + 64..79]: w2 (weights_lo low)
// [esp + 80..95]: w3 (weights_lo high)
// SSE2 implementation of Adler-32 block processing (num_blocks x 32-byte blocks;
// IA-32). Does NOT apply mod 65521 (the caller does). Same SSE2 pmaddubsw
// emulation as Adler32BlocksSse2_x86_64.inc (punpcklbw/hbw + pmaddwd); x64
// keeps the widened weights in xmm6-xmm9, IA-32 only has xmm0-xmm7 so they
// live on the stack (4 x 16 bytes).
// ABI (after HlpSimdProc4Begin_i386.inc): ebx = data ptr, esi = num_blocks,
// edi = sums ptr, eax = constants ptr.
// Sums layout: [SumA: UInt32, SumB: UInt32].
// Constants layout: [weights_hi: 16B, weights_lo: 16B] (32 bytes).
// Frame (sub esp, 96):
// [esp + 0..15] = xmm6 save [esp + 48..63] = w1 (weights_hi high)
// [esp + 16..31] = xmm7 save [esp + 64..79] = w2 (weights_lo low)
// [esp + 32..47] = w0 (weights_hi low) [esp + 80..95] = w3 (weights_lo high)
// Saves: xmm6-xmm7 saved/restored defensively (volatile on IA-32).
// Reference: Chromium zlib adler32_simd.c, HashLib Adler32BlocksSse2_x86_64.inc.

// Preserve constants pointer (eax) before GPR reloads from ASums
push eax
Expand Down
22 changes: 11 additions & 11 deletions HashLib/src/Include/Simd/Adler32/Adler32BlocksSse2_x86_64.inc
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// SSE2 implementation of Adler-32 block processing.
// Expects MS x64 ABI: rcx = data ptr, edx = num_blocks, r8 = sums ptr, r9 = constants ptr.
// ASums layout: [SumA: UInt32, SumB: UInt32].
// Constants layout: [weights_hi: 16B, weights_lo: 16B] (only first 32 bytes used).
// Processes num_blocks x 32-byte blocks. Does NOT apply mod 65521 (caller does it).
// Uses xmm0-xmm9; xmm6-xmm9 are MS x64 non-volatile (saved/restored).
//
// Emulates SSSE3 pmaddubsw via punpcklbw/punpckhbw + pmaddwd:
// data bytes are zero-extended to i16, then multiplied with pre-widened
// weight bytes via pmaddwd (SSE2), producing the same 4 x i32 weighted
// sums per 16-byte half that pmaddubsw + pmaddwd would yield.
// SSE2 implementation of Adler-32 block processing (num_blocks x 32-byte blocks).
// Does NOT apply mod 65521 (the caller does). Emulates SSSE3 pmaddubsw via
// punpcklbw/punpckhbw + pmaddwd: data bytes are zero-extended to i16, then
// multiplied with pre-widened weight bytes via pmaddwd (SSE2), producing the
// same 4 x i32 weighted sums per 16-byte half that pmaddubsw + pmaddwd yield.
// ABI (after HlpSimdProc4Begin_x86_64.inc): rcx = data ptr, edx = num_blocks,
// r8 = sums ptr, r9 = constants ptr.
// Sums layout: [SumA: UInt32, SumB: UInt32].
// Constants layout: [weights_hi: 16B, weights_lo: 16B] (first 32 bytes used).
// Saves: xmm6-xmm9 (MS x64 non-volatile) in the local frame; uses xmm0-xmm9.
// Reference: Chromium zlib adler32_simd.c.

{$I ..\..\Include\Simd\Common\HlpSimdNonVolatileSave_x86_64.inc}

Expand Down
17 changes: 10 additions & 7 deletions HashLib/src/Include/Simd/Adler32/Adler32BlocksSsse3_i386.inc
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// SSSE3 Adler-32 block processing (IA-32).
// After HlpSimdProc4Begin_i386: ebx = AData, esi = ANumBlocks, edi = ASums, eax = AConstants.
// Constants: [weights_hi: 16B, weights_lo: 16B, ones_16: 16B] (48 bytes; same as x64 SSSE3).
// No xmm8 on IA-32: psadbw uses a copy in xmm5 (first half) or xmm4 (second half), then reload weights.
// Caller applies mod 65521.
//
// xmm6–xmm7 saved/restored defensively (volatile on i386).
// SSSE3 implementation of Adler-32 block processing (num_blocks x 32-byte blocks;
// IA-32). Does NOT apply mod 65521 (the caller does). No xmm8 on IA-32:
// psadbw uses a copy in xmm5 (first half) or xmm4 (second half), then the
// weights are reloaded.
// ABI (after HlpSimdProc4Begin_i386.inc): ebx = data ptr, esi = num_blocks,
// edi = sums ptr, eax = constants ptr.
// Constants layout: [weights_hi: 16B, weights_lo: 16B, ones_16: 16B]
// (48 bytes; same as the x64 SSSE3 kernel).
// Saves: xmm6-xmm7 saved/restored defensively (volatile on IA-32).
// Reference: Chromium zlib adler32_simd.c, HashLib Adler32BlocksSsse3_x86_64.inc.

push eax

Expand Down
14 changes: 8 additions & 6 deletions HashLib/src/Include/Simd/Adler32/Adler32BlocksSsse3_x86_64.inc
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// SSSE3 implementation of Adler-32 block processing.
// Expects MS x64 ABI: rcx = data ptr, edx = num_blocks, r8 = sums ptr, r9 = constants ptr.
// ASums layout: [SumA: UInt32, SumB: UInt32].
// Constants layout: [weights_hi: 16B, weights_lo: 16B, ones_16: 16B].
// Processes num_blocks x 32-byte blocks. Does NOT apply mod 65521 (caller does it).
// Uses xmm0-xmm8; xmm6-xmm8 are MS x64 non-volatile (saved/restored).
// SSSE3 implementation of Adler-32 block processing (num_blocks x 32-byte blocks).
// Does NOT apply mod 65521 (the caller does).
// ABI (after HlpSimdProc4Begin_x86_64.inc): rcx = data ptr, edx = num_blocks,
// r8 = sums ptr, r9 = constants ptr.
// Sums layout: [SumA: UInt32, SumB: UInt32].
// Constants layout: [weights_hi: 16B, weights_lo: 16B, ones_16: 16B].
// Saves: xmm6-xmm8 (MS x64 non-volatile) in the local frame; uses xmm0-xmm8.
// Reference: Chromium zlib adler32_simd.c.

{$I ..\..\Include\Simd\Common\HlpSimdNonVolatileSave_x86_64.inc}

Expand Down
24 changes: 12 additions & 12 deletions HashLib/src/Include/Simd/Argon2/Argon2FillBlockAvx2_i386.inc
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
// AVX2 implementation of Argon2 FillBlock (IA-32). 256-bit ymm integer ops
// work in 32-bit mode; same algorithm and buffer layout as
// Argon2FillBlockAvx2_x86_64.inc, redesigned for the IA-32 register budget:
// AVX2 implementation of Argon2 FillBlock (BlaMka round function; IA-32).
// 256-bit ymm integer ops work in 32-bit mode; same algorithm and buffer
// layout as Argon2FillBlockAvx2_x86_64.inc, redesigned for the IA-32
// register budget:
// - the byte-rotation masks are VEX memory operands (rot24 at [masks],
// rot16 at [masks+$20]; read unaligned, so the Pascal const needs no
// special alignment) - the kernel touches only ymm0-ymm4, all volatile,
// so nothing is saved;
// special alignment) - the kernel touches only ymm0-ymm4;
// - R_buf/Z_buf sit at [esp]/[esp+1024] and are addressed [esp+edx+disp]
// (edx = loop offset) - no buffer pointer registers are needed;
// - Left/Right are dead after step 1's XOR.
// AVX/AVX2 instructions are db-encoded for broad assembler compatibility.
// IA-32: after HlpSimdProc5Begin_i386 - ebx = Left ptr, esi = Right ptr,
// Diagonalize/Undiagonalize via vpermq. vzeroupper required before return.
// ABI (after HlpSimdProc5Begin_i386.inc): ebx = Left ptr, esi = Right ptr,
// edi = Current ptr, eax = WithXor (0 or 1; live until the final step),
// ecx = byte-rotation masks ptr (ARGON2_ROT_MASKS; live throughout).
// Each pointer addresses 128 QWords (1024 bytes).
// Stack layout (sub esp, 2048): [esp+0..1023] R_buf, [esp+1024..2047] Z_buf.
// ARight and ACurrent may alias; R_buf buffering handles this.
// Diagonalize/Undiagonalize via vpermq (cross-lane 64-bit permute).
// vzeroupper required before return.
// Each pointer addresses 128 QWords (1024 bytes). ARight and ACurrent may
// alias; R_buf buffering handles this.
// Frame (sub esp, 2048): [esp+0..1023] R_buf, [esp+1024..2047] Z_buf.
// Saves: none (uses ymm0-ymm4 only; all volatile on IA-32).
// AVX/AVX2 instructions are db-encoded for broad assembler compatibility.
// Reference: official Argon2 AVX2 (blamka-round-opt.h), HashLib
// Argon2FillBlockAvx2_x86_64.inc.

Expand Down
39 changes: 19 additions & 20 deletions HashLib/src/Include/Simd/Argon2/Argon2FillBlockAvx2_x86_64.inc
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
// AVX2 implementation of Argon2 FillBlock.
// AVX/AVX2 instructions are db-encoded for broad assembler compatibility.
// Expects MS x64 ABI (after HlpSimdProc5Begin): rcx = Left ptr, rdx = Right ptr,
// AVX2 implementation of Argon2 FillBlock (BlaMka round function).
// Rotations: rot32 via vpshufd, rot24/16 via vpshufb against the resident
// masks, rot63 via shift+or (not byte-aligned). Diagonalize/Undiagonalize
// via vpermq (cross-lane 64-bit permute). vzeroupper required before return.
// ABI (after HlpSimdProc5Begin_x86_64.inc): rcx = Left ptr, rdx = Right ptr,
// r8 = Current ptr, r9 = WithXor (0 or 1), r10 = byte-rotation masks ptr
// (see ARGON2_ROT_MASKS: rot24 at +0, rot16 at +32; read unaligned, so the
// Pascal const needs no special alignment; consumed by the entry mask loads,
// r10 is scratch afterwards).
// Each pointer addresses 128 QWords (1024 bytes).
// Uses ymm0-ymm11; ymm6-ymm11 are MS x64 non-volatile (saved/restored).
// Register map during G rounds: ymm0 = A(v0..v3), ymm1 = B(v4..v7),
// (ARGON2_ROT_MASKS: rot24 at +0, rot16 at +32; read unaligned, so the
// Pascal const needs no special alignment; consumed by the entry mask
// loads, r10 is scratch afterwards).
// Each pointer addresses 128 QWords (1024 bytes). ARight and ACurrent may
// alias; R_buf buffering handles this. r8/r9 survive all loops.
// Register map (G rounds): ymm0 = A(v0..v3), ymm1 = B(v4..v7),
// ymm2 = C(v8..v11), ymm3 = D(v12..v15), ymm4-ymm5 = temps,
// ymm10 = rot24 mask, ymm11 = rot16 mask.
// Rotations: rot32 via vpshufd, rot24/16 via vpshufb against the resident
// masks, rot63 via shift+or (not byte-aligned).
// Stack layout (sub rsp, 2184):
// [rsp+0..127] ymm6-9 save area (4 * 32 = 128 bytes)
// [rsp+128..1151] R_buf (1024 bytes)
// [rsp+1152..2175] Z_buf (1024 bytes)
// [rsp+2176..2183] alignment padding
// r8 (Current) and r9 (WithXor) survive all loops (not clobbered).
// ARight and ACurrent may alias; R_buf buffering handles this.
// Diagonalize/Undiagonalize via vpermq (cross-lane 64-bit permute).
// vzeroupper required before return.
// Frame (sub rsp, 2184):
// [rsp+0..127] = ymm6-ymm9 save area (4 x 32 bytes)
// [rsp+128..1151] = R_buf (1024 bytes)
// [rsp+1152..2175] = Z_buf (1024 bytes)
// [rsp+2176..2183] = alignment padding
// Saves: ymm6-ymm11 (MS x64 non-volatile); uses ymm0-ymm11.
// AVX/AVX2 instructions are db-encoded for broad assembler compatibility.
// Reference: official Argon2 AVX2 (blamka-round-opt.h).

{$I ..\..\Include\Simd\Common\HlpSimdNonVolatileSave_x86_64.inc}

Expand Down
19 changes: 11 additions & 8 deletions HashLib/src/Include/Simd/Argon2/Argon2FillBlockNeon_aarch64.inc
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
// Argon2 FillBlock AArch64 NEON implementation (BlaMka round function).
// Expects AAPCS64: x0 = Left ptr, x1 = Right ptr, x2 = Current ptr, w3 = WithXor.
// Each pointer addresses 128 UInt64 (1024 bytes).
// Stack frame 2128 bytes; see register map.
// Steps: R=Left XOR Right; Z=copy(R); 8 column + 8 row BlaMka rounds on Z;
// Current = R XOR Z [XOR Current if WithXor]. Diagonalize via vext #8.
// Reference: jedisct1/libsodium argon2-fill-block-neon.c, HashLib Argon2FillBlockSse2_x86_64.inc.
// AArch64 vector instructions are .long-encoded for broad assembler compatibility.
// NEON implementation of Argon2 FillBlock (BlaMka round function).
// Steps: R = Left XOR Right; Z = copy(R); 8 column + 8 row BlaMka rounds on
// Z; Current = R XOR Z [XOR Current if WithXor]. Diagonalize via vext #8.
// ABI (after HlpSimdProc4Begin_aarch64.inc): x0 = Left ptr, x1 = Right ptr,
// x2 = Current ptr, w3 = WithXor (0 or 1).
// Each pointer addresses 128 QWords (1024 bytes).
// Register map:
// v0-v1 = A0, A1
// v2-v3 = B0, B1
Expand All @@ -18,6 +16,11 @@
// x11 = Z_buf base ([sp+1088])
// x12 = Z slice pointer (column/row load/store)
// w3 = WithXor (0 or 1)
// Frame: 2128 bytes (R_buf at [sp+64], Z_buf at [sp+1088], 16-byte SP pad).
// Saves: none (caller-saved GPR/vector only).
// AArch64 vector instructions are .long-encoded for broad assembler compatibility.
// Reference: jedisct1/libsodium argon2-fill-block-neon.c, HashLib
// Argon2FillBlockSse2_x86_64.inc.

sub sp, sp, #2128
add x9, sp, #64
Expand Down
30 changes: 17 additions & 13 deletions HashLib/src/Include/Simd/Argon2/Argon2FillBlockSse2_i386.inc
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
// SSE2 implementation of Argon2 FillBlock.
// IA-32: after HlpSimdProc4Begin_i386 — ebx, esi, edi, eax = Left, Right, Current, WithXor
// (parallel to MS x64 ABI: rcx, rdx, r8, r9).
// Each pointer addresses 128 QWords (1024 bytes).
// Uses xmm0–xmm7; xmm6–xmm7 saved/restored defensively (volatile on i386).
// Register map during G rounds: xmm0-1 = A(0..3), xmm2-3 = B(4..7),
// xmm4-5 = C(8..11), xmm6-7 = D(12..15) / temps (same roles as x64, fewer XMM).
// IA-32 stack (sub esp, 2132): WithXor at [esp+2128]; spill slots [esp+2080],[esp+2096],[esp+2112];
// R_buf at lea eax,[esp+32]; ECX = loop offset; EBX = Z_buf base after copy; EDI = Current.
// r8/r9 analogues (Current, WithXor) are not clobbered across loops. ARight and ACurrent may alias.
//
// Diagonalize/Undiagonalize use shufpd (see x64 header in Argon2FillBlockSse2_x86_64.inc).
// SSE2 implementation of Argon2 FillBlock (BlaMka round function; IA-32).
// Same roles as Argon2FillBlockSse2_x86_64.inc with fewer XMM registers;
// Diagonalize/Undiagonalize use shufpd (see the x64 sibling's header).
// ABI (after HlpSimdProc4Begin_i386.inc): ebx = Left ptr, esi = Right ptr,
// edi = Current ptr, eax = WithXor (0 or 1).
// Each pointer addresses 128 QWords (1024 bytes). ARight and ACurrent may
// alias; R_buf buffering handles this. Current/WithXor analogues are not
// clobbered across loops.
// Register map (G rounds): xmm0-1 = A(0..3), xmm2-3 = B(4..7),
// xmm4-5 = C(8..11), xmm6-7 = D(12..15) / temps.
// Frame (sub esp, 2132): WithXor at [esp+2128]; spill slots [esp+2080],
// [esp+2096], [esp+2112]; R_buf at lea eax,[esp+32]; ecx = loop offset;
// ebx = Z_buf base after the copy; edi = Current.
// Saves: xmm6-xmm7 saved/restored defensively (volatile on IA-32).
// Reference: official Argon2 SSE2 (blamka-round-ref/opt), HashLib
// Argon2FillBlockSse2_x86_64.inc.

sub esp, 2132

Expand Down Expand Up @@ -697,7 +701,7 @@
jb @row_loop

// =========================================================================
// Step 5: Final XOR Current = R_buf XOR Z_buf [XOR Current]
// Step 5: Final XOR - Current = R_buf XOR Z_buf [XOR Current]
// =========================================================================
cmp dword ptr [esp + 2128], 0
jnz @final_with_xor
Expand Down
Loading
Loading