diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index fee5d6516..da891d7ce 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -392,8 +392,9 @@ jobs:
# and SHA-256 and SHA-512 with AVX2; and BMI2 and ADX, so X25519 and
# Ed25519 with them;
# * `hsw` (Haswell): AVX2 and BMI but not AVX-512F or ADX, so ChaCha20
- # and Poly1305 with AVX2 even where this runner has AVX-512F, and
- # X25519's and Ed25519's baselines;
+ # and Poly1305 with AVX2 even where this runner has AVX-512F,
+ # X25519's and Ed25519's baselines, and ML-DSA with its polynomial
+ # arithmetic in AVX2;
# * `p4p` (Pentium 4): nothing beyond x86-64's baseline, not even CPUID
# leaf 7, so the baseline ISA's implementations everywhere;
# * `arl` (Arrow Lake): the SHA512 extension, so SHA-512 with it, which no
@@ -409,7 +410,7 @@ jobs:
fail-fast: false
matrix:
chip: [native, skx, hsw, p4p]
- tests: [sha1 sha256 sha384 sha512 aes_gcm cmac chacha20 poly1305 mlkem x25519 ed25519 cpu]
+ tests: [sha1 sha256 sha384 sha512 aes_gcm cmac chacha20 poly1305 mlkem mldsa x25519 ed25519 cpu]
include:
- chip: arl
tests: sha384 sha512 ed25519 cpu
diff --git a/README.md b/README.md
index 96542a624..02ab01664 100644
--- a/README.md
+++ b/README.md
@@ -827,7 +827,7 @@ yours to keep:
✅ |
-✅ SSE2 polynomial arithmetic |
+✅ AVX2; SSE2 and AVX2 polynomial arithmetic |
✅ SHA extensions |
@@ -843,7 +843,7 @@ yours to keep:
✅ |
-✅ SSE2 polynomial arithmetic |
+✅ AVX2; SSE2 and AVX2 polynomial arithmetic |
✅ SHA extensions |
@@ -859,7 +859,7 @@ yours to keep:
✅ |
-✅ SSE2 polynomial arithmetic |
+✅ AVX2; SSE2 and AVX2 polynomial arithmetic |
✅ SHA extensions |
diff --git a/docs/algorithms/ml-dsa-44.toml b/docs/algorithms/ml-dsa-44.toml
index 854e6670e..766d606c3 100644
--- a/docs/algorithms/ml-dsa-44.toml
+++ b/docs/algorithms/ml-dsa-44.toml
@@ -3,4 +3,4 @@ family = "Signatures"
specs = ["MlDsa"]
modules = ["src/mldsa44.rs"]
asm = ["mldsa44", "mldsa"]
-optimized = { x86_64 = "SSE2 polynomial arithmetic" }
+optimized = { x86_64 = "SSE2 and AVX2 polynomial arithmetic" }
diff --git a/docs/algorithms/ml-dsa-65.toml b/docs/algorithms/ml-dsa-65.toml
index e87725611..8835d083b 100644
--- a/docs/algorithms/ml-dsa-65.toml
+++ b/docs/algorithms/ml-dsa-65.toml
@@ -3,4 +3,4 @@ family = "Signatures"
specs = ["MlDsa"]
modules = ["src/mldsa65.rs"]
asm = ["mldsa65", "mldsa"]
-optimized = { x86_64 = "SSE2 polynomial arithmetic" }
+optimized = { x86_64 = "SSE2 and AVX2 polynomial arithmetic" }
diff --git a/docs/algorithms/ml-dsa-87.toml b/docs/algorithms/ml-dsa-87.toml
index 9cfbc9f3a..9a82d4299 100644
--- a/docs/algorithms/ml-dsa-87.toml
+++ b/docs/algorithms/ml-dsa-87.toml
@@ -3,4 +3,4 @@ family = "Signatures"
specs = ["MlDsa"]
modules = ["src/mldsa87.rs"]
asm = ["mldsa87", "mldsa"]
-optimized = { x86_64 = "SSE2 polynomial arithmetic" }
+optimized = { x86_64 = "SSE2 and AVX2 polynomial arithmetic" }
diff --git a/lean/VerifiedGarbage/Artifacts/MlDsaArith/X86_64.lean b/lean/VerifiedGarbage/Artifacts/MlDsaArith/X86_64.lean
index a3d95256b..12caec852 100644
--- a/lean/VerifiedGarbage/Artifacts/MlDsaArith/X86_64.lean
+++ b/lean/VerifiedGarbage/Artifacts/MlDsaArith/X86_64.lean
@@ -2,6 +2,9 @@ import VerifiedGarbage.TCB.X86_64.Target
import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.AddSub
import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.Mul
import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.NttInv
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.YNtt
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.YMul
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.YAddSub
/-!
# ML-DSA (FIPS 204) on x86-64: the arithmetic of polynomials
@@ -80,6 +83,80 @@ def artifacts : List Artifact := [
code := Impl.MlDsa.X86_64.Arith.sub
contract := Spec.MlDsa.subContract X86_64.abi
verified := Proof.MlDsa.X86_64.Arith.sub_verified
- spSafe := Code.all_of_allInstrs (by lit_decide) }]
+ spSafe := Code.all_of_allInstrs (by lit_decide) },
+ { Spec.MlDsa.nttApi with
+ name := Spec.MlDsa.nttApi.name ++ "_avx2"
+ target := X86_64.target
+ doc := Spec.MlDsa.nttApi.doc
+ (notes := ["The function computes on eight coefficients at a time in AVX2 registers, with a table of \
+ the 256 zetas that it stores in `scratch`. It sets MXCSR to `0x1FBF` around its multiplications \
+ (Intel's mitigation of MXCSR-configuration-dependent timing) and loads the caller's MXCSR back \
+ before returning."])
+ code := Impl.MlDsa.X86_64.Arith.nttAvx2
+ contract := Spec.MlDsa.nttContract X86_64.abi
+ verified := Proof.MlDsa.X86_64.Arith.nttY_verified
+ spSafe := Code.all_of_allInstrs (by lit_decide)
+ features := ["avx", "avx2"]
+ ofSig := ⟨_, _, _, by unfold Spec.MlDsa.nttContract Spec.MlDsa.inPlaceContract; rfl⟩ },
+ { Spec.MlDsa.nttInvApi with
+ name := Spec.MlDsa.nttInvApi.name ++ "_avx2"
+ target := X86_64.target
+ doc := Spec.MlDsa.nttInvApi.doc
+ (notes := ["The function computes on eight coefficients at a time in AVX2 registers, with a table of \
+ the 256 zetas that it stores in `scratch`. It sets MXCSR to `0x1FBF` around its multiplications \
+ (Intel's mitigation of MXCSR-configuration-dependent timing) and loads the caller's MXCSR back \
+ before returning."])
+ code := Impl.MlDsa.X86_64.Arith.nttInvAvx2
+ contract := Spec.MlDsa.nttInvContract X86_64.abi
+ verified := Proof.MlDsa.X86_64.Arith.nttInvY_verified
+ spSafe := Code.all_of_allInstrs (by lit_decide)
+ features := ["avx", "avx2"]
+ ofSig := ⟨_, _, _, by unfold Spec.MlDsa.nttInvContract Spec.MlDsa.inPlaceContract; rfl⟩ },
+ { Spec.MlDsa.mulApi with
+ name := Spec.MlDsa.mulApi.name ++ "_avx2"
+ target := X86_64.target
+ doc := Spec.MlDsa.mulApi.doc
+ (notes := ["The function computes on eight coefficients at a time in AVX2 registers. It sets MXCSR to \
+ `0x1FBF` around its multiplications (Intel's mitigation of MXCSR-configuration-dependent timing), \
+ through the last 8 bytes of `h`, which it stores last, and loads the caller's MXCSR back before \
+ returning."])
+ code := Impl.MlDsa.X86_64.Arith.mulAvx2
+ contract := Spec.MlDsa.mulContract X86_64.abi
+ verified := Proof.MlDsa.X86_64.Arith.mulY_verified
+ spSafe := Code.all_of_allInstrs (by lit_decide)
+ features := ["avx", "avx2"] },
+ { Spec.MlDsa.mulAddApi with
+ name := Spec.MlDsa.mulAddApi.name ++ "_avx2"
+ target := X86_64.target
+ doc := Spec.MlDsa.mulAddApi.doc
+ (notes := ["The function computes on eight coefficients at a time in AVX2 registers. It sets MXCSR to \
+ `0x1FBF` around its multiplications (Intel's mitigation of MXCSR-configuration-dependent timing), \
+ through the last 8 bytes of `h`, which it stores last, and loads the caller's MXCSR back before \
+ returning."])
+ code := Impl.MlDsa.X86_64.Arith.mulAddAvx2
+ contract := Spec.MlDsa.mulAddContract X86_64.abi
+ verified := Proof.MlDsa.X86_64.Arith.mulAddY_verified
+ spSafe := Code.all_of_allInstrs (by lit_decide)
+ features := ["avx", "avx2"] },
+ { Spec.MlDsa.addApi with
+ name := Spec.MlDsa.addApi.name ++ "_avx2"
+ target := X86_64.target
+ doc := Spec.MlDsa.addApi.doc
+ (notes := ["The function computes on eight coefficients at a time in AVX2 registers."])
+ code := Impl.MlDsa.X86_64.Arith.addAvx2
+ contract := Spec.MlDsa.addContract X86_64.abi
+ verified := Proof.MlDsa.X86_64.Arith.addY_verified
+ spSafe := Code.all_of_allInstrs (by lit_decide)
+ features := ["avx", "avx2"] },
+ { Spec.MlDsa.subApi with
+ name := Spec.MlDsa.subApi.name ++ "_avx2"
+ target := X86_64.target
+ doc := Spec.MlDsa.subApi.doc
+ (notes := ["The function computes on eight coefficients at a time in AVX2 registers."])
+ code := Impl.MlDsa.X86_64.Arith.subAvx2
+ contract := Spec.MlDsa.subContract X86_64.abi
+ verified := Proof.MlDsa.X86_64.Arith.subY_verified
+ spSafe := Code.all_of_allInstrs (by lit_decide)
+ features := ["avx", "avx2"] }]
end VG.Artifacts.MlDsaArith.X86_64
diff --git a/lean/VerifiedGarbage/Impl/MlDsa/X86_64/Arith/Avx2.lean b/lean/VerifiedGarbage/Impl/MlDsa/X86_64/Arith/Avx2.lean
new file mode 100644
index 000000000..4c4172ca7
--- /dev/null
+++ b/lean/VerifiedGarbage/Impl/MlDsa/X86_64/Arith/Avx2.lean
@@ -0,0 +1,203 @@
+import VerifiedGarbage.Impl.MlDsa.X86_64.Arith.Backend
+import VerifiedGarbage.Impl.MlKem.X86_64.Avx
+
+/-!
+# ML-DSA on x86-64: the polynomial arithmetic with AVX2
+
+`vg_mldsa_ntt_avx2`, `vg_mldsa_inv_ntt_avx2`, `vg_mldsa_multiply_ntt_avx2`,
+`vg_mldsa_multiply_add_ntt_avx2`, `vg_mldsa_add_avx2` and
+`vg_mldsa_sub_avx2` are their SSE2 versions (`Ntt.lean`, `Mul.lean`,
+`AddSub.lean`) on eight coefficients at a time, four in each 128-bit lane of
+AVX2 registers: in each lane, the VEX.256 form of the SSE2 code (`toY`,
+`Impl/MlKem/X86_64/Avx.lean`) does what the SSE2 code does to an `xmm`
+register, with `q`, `-q⁻¹ mod 2³²` (and `2⁶⁴ mod q`) in both lanes of
+`ymm15`, `ymm14` (and `ymm11`) (`yconsts`).
+
+The layers of the NTT and its inverse, each a pass over `f` with `rdx` at
+the coefficients it loads and `r8` at the zetas of the table:
+
+* `len ≥ 8` (`ylay`): each block with its zeta in both lanes of `ymm13`
+ (`yzeta1`), and `len / 8` times the butterflies of the eight
+ coefficients `w[j]` and the eight `w[j + len]`;
+* `len = 4` (`ylay4`): two blocks at a time, their lower halves gathered
+ into `ymm0` and their upper halves into `ymm1` by `vperm2i128`, with the
+ zeta of each in a lane of `ymm13` (`yzetaS`: `vpshufd` and `vpblendd`);
+* `len = 2` and `len = 1` (`ylay2`, `ylay1`): in each lane `l`, what
+ `vlay2` and `vlay1` do to `xmm0` and `xmm1` (or `xmm2`), with lane `l` of
+ the two loads of 32 bytes holding the coefficients at `16l` and
+ `32 + 16l`, and the zetas of the blocks there in lane `l` of `ymm13`
+ (`yzetaS`, or `vpermq` of eight zetas).
+
+`NTT⁻¹` then scales every coefficient (`yscale`). The multiplications run
+inside `withMxcsr` as in the SSE2 code: for `vg_mldsa_multiply*_ntt_avx2`,
+through the last 8 bytes of `h`, whose last eight coefficients are loaded
+to `ymm6` first; the loop stores the first 248, and the last eight are
+stored after MXCSR is loaded back. Every function clears the upper halves of
+the vector registers before returning (`vzeroupper`). Every address and
+branch depends only on the pointers.
+-/
+
+namespace VG.Impl.MlDsa.X86_64.Arith
+
+open VG.X86_64
+open VG.Impl.MlKem.X86_64 (xb xmov withMxcsr rcxLoop toY yconst)
+
+/-- `q` in the doublewords of `ymm15` and `-q⁻¹ mod 2³²` in those of `ymm14`. -/
+def yconsts : List Instr := yconst .xmm15 8380417 ++ yconst .xmm14 4236238847
+
+/-- `vzeroupper`. -/
+def yepi : List Instr := [.vop .vzeroupper]
+
+/-! ## The NTT and its inverse -/
+
+/-- The zeta at `[r8]` in every doubleword of both lanes of `ymm13`, and in
+those of `ymm12`: `vzeta 0` in each lane. -/
+def yzeta1 : List Instr :=
+ .vbroadcasti128 .xmm13 (at_ .r8 0) :: toY [.xop (.pshufd .xmm13 .xmm13 0), .xop (.pshufd .xmm12 .xmm13 0xF5)]
+
+/-- The four zetas at `[r8]` in both lanes, arranged by `vpshufd` with `o₀`
+into lane 0 of `ymm13` and with `o₁` into lane 1 (through `ymm2`), and its
+odd doublewords in the even ones of `ymm12`. -/
+def yzetaS (o₀ o₁ : BitVec 8) : List Instr :=
+ .vbroadcasti128 .xmm13 (at_ .r8 0) ::
+ toY [.xop (.pshufd .xmm2 .xmm13 o₁), .xop (.pshufd .xmm13 .xmm13 o₀)] ++
+ [.vop (.vpblendd .l256 .xmm13 .xmm13 .xmm2 0xF0)] ++ toY [.xop (.pshufd .xmm12 .xmm13 0xF5)]
+
+/-- A layer with `len ≥ 8` and butterflies `bf`: its `128 / len` blocks, the
+first with the zeta `k`, the zeta pointer moving by `dz` bytes. -/
+def ylay (bf : List Instr) (len k : Nat) (dz : BitVec 32) : Prog isa :=
+ .seq (.block ([.mov .rdx (.reg .rdi)] ++ leaR .r8 .rsi (4 * k) ++
+ [.mov32 .rax (.imm (BitVec.ofNat 32 (128 / len)))])) <|
+ .loop (.seq (.block (yzeta1 ++ [.alu .add .r8 (.imm dz)]))
+ (.seq (rcxLoop (len / 8) ([.vmovdquLoad .l256 .xmm0 (at_ .rdx 0),
+ .vmovdquLoad .l256 .xmm1 (at_ .rdx (4 * len))] ++ toY bf ++
+ [.vmovdquStore .l256 (at_ .rdx 0) .xmm0, .vmovdquStore .l256 (at_ .rdx (4 * len)) .xmm3,
+ .alu .add .rdx (.imm 32)]))
+ (.block [.alu .add .rdx (.imm (BitVec.ofNat 32 (4 * len))), .alu .sub .rax (.imm 1)]))) .ne
+
+/-- The layer with `len = 4`, two blocks at a time: the first with the zeta
+`k`, the zetas of a pair at `[r8]` arranged by `yzetaS o₀ o₁`, the zeta
+pointer moving by `dz` bytes. -/
+def ylay4 (bf : List Instr) (k : Nat) (o₀ o₁ : BitVec 8) (dz : BitVec 32) : Prog isa :=
+ .seq (.block ([.mov .rdx (.reg .rdi)] ++ leaR .r8 .rsi (4 * k))) <|
+ rcxLoop 16 ([.vmovdquLoad .l256 .xmm4 (at_ .rdx 0), .vmovdquLoad .l256 .xmm5 (at_ .rdx 32)] ++
+ yzetaS o₀ o₁ ++
+ [.alu .add .r8 (.imm dz), .vop (.vperm2i128 .xmm0 .xmm4 .xmm5 0x20),
+ .vop (.vperm2i128 .xmm1 .xmm4 .xmm5 0x31)] ++ toY bf ++
+ [.vop (.vperm2i128 .xmm4 .xmm0 .xmm3 0x20), .vop (.vperm2i128 .xmm5 .xmm0 .xmm3 0x31),
+ .vmovdquStore .l256 (at_ .rdx 0) .xmm4, .vmovdquStore .l256 (at_ .rdx 32) .xmm5,
+ .alu .add .rdx (.imm 64)])
+
+/-- `vlay2`'s gathering of the halves of two blocks (`Ntt.lean`). -/
+def gath2 : List Instr := [xmov .xmm2 .xmm0, xb .punpcklqdq .xmm0 .xmm1, xb .punpckhqdq .xmm2 .xmm1, xmov .xmm1 .xmm2]
+
+/-- `vlay2`'s interleaving back. -/
+def scat2 : List Instr := [xmov .xmm1 .xmm0, xb .punpcklqdq .xmm0 .xmm3, xb .punpckhqdq .xmm1 .xmm3]
+
+/-- The layer with `len = 2`, four blocks at a time: in each lane, `vlay2`'s
+two (`gath2`, `bf`, `scat2`), with their zetas from `[r8]` arranged by
+`yzetaS o₀ o₁`, the zeta pointer moving by `dz` bytes. -/
+def ylay2 (bf : List Instr) (k : Nat) (o₀ o₁ : BitVec 8) (dz : BitVec 32) : Prog isa :=
+ .seq (.block ([.mov .rdx (.reg .rdi)] ++ leaR .r8 .rsi (4 * k))) <|
+ rcxLoop 16 ([.vmovdquLoad .l256 .xmm0 (at_ .rdx 0), .vmovdquLoad .l256 .xmm1 (at_ .rdx 32)] ++
+ yzetaS o₀ o₁ ++ [.alu .add .r8 (.imm dz)] ++ toY (gath2 ++ bf ++ scat2) ++
+ [.vmovdquStore .l256 (at_ .rdx 0) .xmm0, .vmovdquStore .l256 (at_ .rdx 32) .xmm1, .alu .add .rdx (.imm 64)])
+
+/-- `vlay1`'s gathering of the pairs of four blocks (`Ntt.lean`). -/
+def gath1 : List Instr :=
+ [.xop (.pshufd .xmm0 .xmm0 0xD8), .xop (.pshufd .xmm2 .xmm2 0xD8), xmov .xmm1 .xmm0,
+ xb .punpcklqdq .xmm0 .xmm2, xb .punpckhqdq .xmm1 .xmm2]
+
+/-- `vlay1`'s interleaving back. -/
+def scat1 : List Instr := [xmov .xmm1 .xmm0, xb .punpckldq .xmm0 .xmm3, xb .punpckhdq .xmm1 .xmm3]
+
+/-- The eight zetas at `[r8]` in the order the lanes of `ylay1` take them
+for `NTT`: the first two and the fifth and sixth in lane 0, the others in
+lane 1 (`vpermq`). -/
+def yzeta8 : List Instr :=
+ [.vmovdquLoad .l256 .xmm13 (at_ .r8 0), .vop (.vpermq .xmm13 .xmm13 0xD8)] ++
+ toY [.xop (.pshufd .xmm12 .xmm13 0xF5)]
+
+/-- The same for `NTT⁻¹`, whose blocks take the zetas in decreasing order:
+the eighth, seventh, fourth and third in lane 0, the others in lane 1. -/
+def yzeta8R : List Instr :=
+ [.vmovdquLoad .l256 .xmm13 (at_ .r8 0), .vop (.vpermq .xmm13 .xmm13 0x27)] ++
+ toY [.xop (.pshufd .xmm13 .xmm13 0xB1), .xop (.pshufd .xmm12 .xmm13 0xF5)]
+
+/-- The layer with `len = 1`, eight blocks at a time: in each lane,
+`vlay1`'s four, with their zetas from `[r8]` (`zl`), the zeta pointer moving
+by `dz` bytes. -/
+def ylay1 (bf : List Instr) (k : Nat) (zl : List Instr) (dz : BitVec 32) : Prog isa :=
+ .seq (.block ([.mov .rdx (.reg .rdi)] ++ leaR .r8 .rsi (4 * k))) <|
+ rcxLoop 16 ([.vmovdquLoad .l256 .xmm0 (at_ .rdx 0), .vmovdquLoad .l256 .xmm2 (at_ .rdx 32)] ++ zl ++
+ [.alu .add .r8 (.imm dz)] ++ toY (gath1 ++ bf ++ scat1) ++
+ [.vmovdquStore .l256 (at_ .rdx 0) .xmm0, .vmovdquStore .l256 (at_ .rdx 32) .xmm1, .alu .add .rdx (.imm 64)])
+
+/-- Every coefficient times `256⁻¹ mod q`: `vscale` in each lane. -/
+def yscale : Prog isa :=
+ .seq (.block ([.mov .rdx (.reg .rdi)] ++ yconst .xmm13 16382 ++ [.vop (.vmovdqa .l256 .xmm12 .xmm13)]))
+ (rcxLoop 32 ([.vmovdquLoad .l256 .xmm3 (at_ .rdx 0)] ++ toY (vmont .xmm3 .xmm13 .xmm12 .xmm2 .xmm4 ++
+ vcsub .xmm3 .xmm2) ++ [.vmovdquStore .l256 (at_ .rdx 0) .xmm3, .alu .add .rdx (.imm 32)]))
+
+/-- The table and the constants. -/
+def ypro : List Instr := dwordTab zmTab 256 .rsi ++ yconsts
+
+def nttAvx2 : Prog isa := withMxcsr .rsi 768 <|
+ .seq (.block ypro) (.seq (ylay vbfly 128 1 4) (.seq (ylay vbfly 64 2 4) (.seq (ylay vbfly 32 4 4)
+ (.seq (ylay vbfly 16 8 4) (.seq (ylay vbfly 8 16 4) (.seq (ylay4 vbfly 32 0x00 0x55 8)
+ (.seq (ylay2 vbfly 64 0xA0 0xF5 16) (.seq (ylay1 vbfly 128 yzeta8 32) (.block yepi)))))))))
+
+def nttInvAvx2 : Prog isa := withMxcsr .rsi 768 <|
+ .seq (.block ypro) (.seq (ylay1 vibfly 248 yzeta8R (-32)) (.seq (ylay2 vibfly 124 0x5F 0x0A (-16))
+ (.seq (ylay4 vibfly 62 0x55 0x00 (-8)) (.seq (ylay vibfly 8 31 (-4)) (.seq (ylay vibfly 16 15 (-4))
+ (.seq (ylay vibfly 32 7 (-4)) (.seq (ylay vibfly 64 3 (-4)) (.seq (ylay vibfly 128 1 (-4))
+ (.seq yscale (.block yepi))))))))))
+
+/-! ## Products -/
+
+/-- The constants and `2⁶⁴ mod q` in the doublewords of `ymm11`. -/
+def ymulPro : List Instr := yconsts ++ yconst .xmm11 2365951
+
+/-- The coefficients of `f`, `g` and `h` to `ymm3`, `ymm13` and `ymm5`. -/
+def ymulLoads : List Instr :=
+ [.vmovdquLoad .l256 .xmm3 (at_ .rsi 0), .vmovdquLoad .l256 .xmm13 (at_ .rdx 0),
+ .vmovdquLoad .l256 .xmm5 (at_ .rdi 0)]
+
+/-- Store `ymm3` to `h` and advance the three pointers. -/
+def ymulTail : List Instr :=
+ [.vmovdquStore .l256 (at_ .rdi 0) .xmm3, .alu .add .rdi (.imm 32), .alu .add .rsi (.imm 32),
+ .alu .add .rdx (.imm 32)]
+
+/-- The last eight coefficients, with those of `h` in `ymm6`, to `ymm3`. -/
+def ymulLast (core : List Instr) : List Instr :=
+ [.vmovdquLoad .l256 .xmm3 (at_ .rsi 0), .vmovdquLoad .l256 .xmm13 (at_ .rdx 0),
+ .vop (.vmovdqa .l256 .xmm5 .xmm6)] ++ toY core
+
+/-- `mulFn` on eight coefficients at a time. -/
+def ymulFn (core : List Instr) : Prog isa :=
+ .seq (.block [.mov .r8 (.reg .rdi), .vmovdquLoad .l256 .xmm6 (at_ .rdi 992)])
+ (.seq (withMxcsr .r8 1016
+ (.seq (.block ymulPro) (.seq (rcxLoop 31 (ymulLoads ++ toY core ++ ymulTail)) (.block (ymulLast core)))))
+ (.block ([.vmovdquStore .l256 (at_ .rdi 0) .xmm3] ++ yepi)))
+
+def mulAvx2 : Prog isa := ymulFn mulCore
+
+def mulAddAvx2 : Prog isa := ymulFn mulAddCore
+
+/-! ## Sums and differences -/
+
+/-- The body of `add` and `sub` on eight coefficients at a time. -/
+def yaccBody (op : XBinOp) (fix : List Instr) : List Instr :=
+ [.vmovdquLoad .l256 .xmm0 (at_ .rdi 0), .vmovdquLoad .l256 .xmm1 (at_ .rsi 0)] ++ toY (xb op .xmm0 .xmm1 :: fix) ++
+ [.vmovdquStore .l256 (at_ .rdi 0) .xmm0, .alu .add .rdi (.imm 32), .alu .add .rsi (.imm 32)]
+
+def addAvx2 : Prog isa :=
+ .seq (.block (yconst .xmm15 8380417)) (.seq (rcxLoop 32 (yaccBody .paddd (vcsub .xmm0 .xmm2))) (.block yepi))
+
+def subAvx2 : Prog isa :=
+ .seq (.block (yconst .xmm15 8380417)) (.seq (rcxLoop 32 (yaccBody .psubd (vcadd .xmm0 .xmm2))) (.block yepi))
+
+/-- The AVX2 code. -/
+def Backend.avx2 : Backend := ⟨nttAvx2, nttInvAvx2, mulAvx2, mulAddAvx2, addAvx2, subAvx2, "_avx2"⟩
+
+end VG.Impl.MlDsa.X86_64.Arith
diff --git a/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/BackendAvx2.lean b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/BackendAvx2.lean
new file mode 100644
index 000000000..157073d12
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/BackendAvx2.lean
@@ -0,0 +1,36 @@
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.Backend
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.YNtt
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.YMul
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.YAddSub
+
+/-!
+# ML-DSA on x86-64: the polynomial arithmetic with AVX2, as an `ArithImpl`
+
+Untrusted: everything here is checked by Lean. The AVX2 code
+(`Impl/MlDsa/X86_64/Arith/Avx2.lean`) meets what the callers of the
+polynomial arithmetic need of it (`FnOk`), and requires AVX and AVX2.
+-/
+
+namespace VG.Proof.MlDsa.X86_64
+
+open VG VG.X86_64 VG.Impl.MlDsa.X86_64.Arith
+
+/-- The AVX2 code. -/
+def ArithImpl.avx2 : ArithImpl where
+ code := .avx2
+ ok :=
+ { ntt := FnOk.of Arith.nttY_verified (by decide +kernel) (by decide +kernel) (by decide +kernel)
+ (by decide +kernel)
+ invNtt := FnOk.of Arith.nttInvY_verified (by decide +kernel) (by decide +kernel) (by decide +kernel)
+ (by decide +kernel)
+ mul := FnOk.of Arith.mulY_verified (by decide +kernel) (by decide +kernel) (by decide +kernel)
+ (by decide +kernel)
+ mulAdd := FnOk.of Arith.mulAddY_verified (by decide +kernel) (by decide +kernel) (by decide +kernel)
+ (by decide +kernel)
+ add := FnOk.of Arith.addY_verified (by decide +kernel) (by decide +kernel) (by decide +kernel)
+ (by decide +kernel)
+ sub := FnOk.of Arith.subY_verified (by decide +kernel) (by decide +kernel) (by decide +kernel)
+ (by decide +kernel) }
+ features := ["avx", "avx2"]
+
+end VG.Proof.MlDsa.X86_64
diff --git a/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/Mul.lean b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/Mul.lean
index 7cdf5d3b0..dcff58350 100644
--- a/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/Mul.lean
+++ b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/Mul.lean
@@ -286,7 +286,7 @@ theorem fn_ok {t : Poly → Poly → Poly → Poly} {hPre : Mem → Addr → Pro
s3.gpr .rdi = coeffAddr h 252 ∧ Frame [pR h] σ.mem s3.mem ∧
(∀ k < 252, (coeffAt s3.mem h k).toNat = (R[k]!).val) ∧
∀ e < 4, (dword (s3.xmm .xmm3) e).toNat = (R[252 + e]!).val)
- fun s2 k2 f2 x2 => ?_) fun s4 ⟨s3, ⟨kk, hdi, fr, dn, ln⟩, f4, k4, x4⟩ => ?_)
+ fun s2 k2 f2 x2 _ => ?_) fun s4 ⟨s3, ⟨kk, hdi, fr, dn, ln⟩, f4, k4, x4, _⟩ => ?_)
· have fσ2 : Frame [mxH h] σ.mem s2.mem := by rw [← m1]; exact f2
refine WP.mono (WP.keep [.rax, .rdi, .rsi, .rdx, .rcx] (WP.seq (WP.mono (mulPro_ok s2)
fun w ⟨cw, xw, x6, kw, mw⟩ => ?_) (Q := fun (s3 : State) => s3.gpr .rdi = coeffAddr h 252 ∧
diff --git a/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/Mxcsr.lean b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/Mxcsr.lean
index d87f9e044..ef50cbe5b 100644
--- a/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/Mxcsr.lean
+++ b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/Mxcsr.lean
@@ -29,34 +29,37 @@ those bytes, and nothing more than they and MXCSR change after it. -/
theorem withMxcsrH_ok {c : Prog isa} {r : Reg} (hr : r ≠ .r11 ∧ r ≠ .rax) (rs : List Reg)
(hrs : r ∉ rs ∧ Reg.r11 ∉ rs) {p : Addr} {s : State} {Q : State → Prop}
(hsi : s.gpr r = p) (hw : pR p ∈ s.wr) (hk : writesOnly rs c = true)
- (hc : ∀ s1, Keep [.rax, .r11] s s1 → Frame [mxH p] s.mem s1.mem → s1.xmm = s.xmm → WP isa c s1 Q) :
+ (hc : ∀ s1, Keep [.rax, .r11] s s1 → Frame [mxH p] s.mem s1.mem → s1.xmm = s.xmm → s1.ymmHi = s.ymmHi →
+ WP isa c s1 Q) :
WP isa (withMxcsr r 1016 c) s fun s' =>
- ∃ s2, Q s2 ∧ Frame [mxH p] s2.mem s'.mem ∧ Keep [] s2 s' ∧ s'.xmm = s2.xmm := by
+ ∃ s2, Q s2 ∧ Frame [mxH p] s2.mem s'.mem ∧ Keep [] s2 s' ∧ s'.xmm = s2.xmm ∧ s'.ymmHi = s2.ymmHi := by
have h0 := mxH_in hw 1016 (by decide)
have h0' := mxH_in (List.mem_append_right s.rd hw) 1016 (by decide)
have h4 := mxH_in hw 1020 (by decide)
simp only [withMxcsr]
refine WP.seq (WP.mono (Q := fun (s1 : State) => s1.gpr .r11 = (s.mxcsr &&& 0xFFFF).setWidth 64 ∧ Keep [.r11] s s1 ∧
- Frame [mxH p] s.mem s1.mem ∧ s1.xmm = s.xmm) (by
+ Frame [mxH p] s.mem s1.mem ∧ s1.xmm = s.xmm ∧ s1.ymmHi = s.ymmHi) (by
vrunm [hsi, h0, h0', Mem.readW_writeW_self32, hr.1]
refine ⟨by rw [BitVec.setWidth_setWidth_of_le _ (by decide), BitVec.setWidth_eq],
⟨fun r hr => ?_, rfl, rfl⟩, (Frame.refl _ _).writeW (List.mem_singleton_self _) _
- (Offset.contains p (by decide) (by decide) (by decide))⟩
+ (Offset.contains p (by decide) (by decide) (by decide)),
+ by simp only [RegUpd.ymmHi_setReg, RegUpd.ymmHi_setFlags]⟩
simp only [List.mem_singleton] at hr
- simp only [RegUpd.gpr_setReg, RegUpd.gpr_setFlags, hr, ite_false]) fun s1 ⟨h11, k1, f1, x1⟩ => ?_)
+ simp only [RegUpd.gpr_setReg, RegUpd.gpr_setFlags, hr, ite_false]) fun s1 ⟨h11, k1, f1, x1, y1⟩ => ?_)
have hsi1 : s1.gpr r = p := by rw [k1.gpr (by simpa using hr.1), hsi]
have h4' : InRegions s1.wr (p + BitVec.ofNat 64 (1016 + 4)) 4 := by rw [k1.2.2]; exact h4
have h4'' : InRegions (s1.rd ++ s1.wr) (p + BitVec.ofNat 64 (1016 + 4)) 4 :=
let ⟨r, hr, hc⟩ := h4'; ⟨r, List.mem_append_right _ hr, hc⟩
refine WP.seq (WP.seq (WP.mono (Q := fun (s2 : State) => Keep [.rax] s1 s2 ∧ Frame [mxH p] s1.mem s2.mem ∧
- s2.xmm = s1.xmm)
+ s2.xmm = s1.xmm ∧ s2.ymmHi = s1.ymmHi)
(by
vrunm [hsi1, h4', h4'', Mem.readW_writeW_self32, hr.2]
refine ⟨⟨fun r hr => ?_, rfl, rfl⟩, (Frame.refl _ _).writeW (List.mem_singleton_self _) _
- (Offset.contains p (by decide) (by decide) (by decide))⟩
+ (Offset.contains p (by decide) (by decide) (by decide)), by simp only [RegUpd.ymmHi_setReg]⟩
simp only [List.mem_singleton] at hr
- simp only [RegUpd.gpr_setReg, hr, ite_false]) fun s2 ⟨k2, f2, x2⟩ => ?_))
- refine WP.seq (WP.mono (WP.keep _ (hc s2 ((k1.trans k2).mono (by simp)) (f1.trans f2) (x2.trans x1)) hk)
+ simp only [RegUpd.gpr_setReg, hr, ite_false]) fun s2 ⟨k2, f2, x2, y2⟩ => ?_))
+ refine WP.seq (WP.mono (WP.keep _ (hc s2 ((k1.trans k2).mono (by simp)) (f1.trans f2) (x2.trans x1)
+ (y2.trans y1)) hk)
fun s3 ⟨hq, k3⟩ => ?_)
have k23 := k2.trans k3
have hsi3 : s3.gpr r = p := by rw [k23.gpr (by simp [hr.2, hrs.1]), hsi1]
@@ -68,6 +71,6 @@ theorem withMxcsrH_ok {c : Prog isa} {r : Reg} (hr : r ≠ .r11 ∧ r ≠ .rax)
subst h4
vrunm [hsi3, h113, h03, h03', Mem.readW_writeW_self32, ldmxcsr_ok]
exact ⟨_, hq, (Frame.refl _ _).writeW (List.mem_singleton_self _) _
- (Offset.contains p (by decide) (by decide) (by decide)), ⟨fun _ _ => rfl, rfl, rfl⟩, rfl⟩
+ (Offset.contains p (by decide) (by decide) (by decide)), ⟨fun _ _ => rfl, rfl, rfl⟩, rfl, rfl⟩
end VG.Proof.MlDsa.X86_64.Arith
diff --git a/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YAddSub.lean b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YAddSub.lean
new file mode 100644
index 000000000..701332da3
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YAddSub.lean
@@ -0,0 +1,220 @@
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.YBase
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.AddSub
+
+/-!
+# ML-DSA on x86-64: `vg_mldsa_add_avx2` and `vg_mldsa_sub_avx2`
+
+Untrusted: everything here is checked by Lean. Each iteration of the loop
+loads eight coefficients of `f` and of `g` and, in each lane, does what an
+iteration of `vg_mldsa_add` (`vg_mldsa_sub`) does (`AddSub.lean`), whose
+proof holds of each lane (`ylanes`), and stores the eight results to `f`
+(`YAddSub.step`); the loop leaves `f` with all 256 (`YAddSub.fn_ok`).
+-/
+
+namespace VG.Proof.MlDsa.X86_64.Arith
+
+open VG VG.X86_64 VG.Impl.MlDsa.X86_64.Arith
+open VG.Proof.MlDsa.Arith
+open VG.Proof.MlKem.X86_64 (Keep XOnly YOnly ylanes yld_ok yconst_ok WP.keep writesOnly gprPreserved_of ifp ifn
+ ptr_step GOnly wp_rcxLoopY add_ofNat_zero lane_setReg lane_setFlags sx32 State.setMem_ymm)
+open VG.Impl.MlKem.X86_64 (xb xmov toY yconst)
+open VG.Spec.MlDsa (q n Poly Zq coeffAt polyAt Reduced PolyIs)
+
+theorem addFixX_ok (s : State) (hq : s.xmm .xmm15 = qV) :
+ WP isa (.block (xb .paddd .xmm0 .xmm1 :: vcsub .xmm0 .xmm2)) s fun s' =>
+ s'.xmm .xmm0 = addV (s.xmm .xmm0) (s.xmm .xmm1) ∧ XOnly [.xmm0, .xmm2] s s' := by
+ simp only [vcsub, vcadd, xmov, xb]
+ vrun [eval_movdqa]
+ rw [hq]
+ exact ⟨rfl, by xonly⟩
+
+theorem subFixX_ok (s : State) (hq : s.xmm .xmm15 = qV) :
+ WP isa (.block (xb .psubd .xmm0 .xmm1 :: vcadd .xmm0 .xmm2)) s fun s' =>
+ s'.xmm .xmm0 = subV (s.xmm .xmm0) (s.xmm .xmm1) ∧ XOnly [.xmm0, .xmm2] s s' := by
+ simp only [vcadd, xmov, xb]
+ vrun [eval_movdqa]
+ rw [hq]
+ exact ⟨rfl, by xonly⟩
+
+theorem lane_addFix : laneSseBlock (toY (xb .paddd .xmm0 .xmm1 :: vcsub .xmm0 .xmm2)) =
+ some (xb .paddd .xmm0 .xmm1 :: vcsub .xmm0 .xmm2) := by decide +kernel
+
+theorem lane_subFix : laneSseBlock (toY (xb .psubd .xmm0 .xmm1 :: vcadd .xmm0 .xmm2)) =
+ some (xb .psubd .xmm0 .xmm1 :: vcadd .xmm0 .xmm2) := by decide +kernel
+
+namespace YAddSub
+
+/-- After `i` vectors of eight, each coefficient before `8i` is `v k`. -/
+structure Inv (s₀ : State) (v : Nat → BitVec 32) (i : Nat) (s : State) : Prop where
+ rdi : s.gpr .rdi = s₀.gpr .rdi + BitVec.ofNat 64 (32 * i)
+ rsi : s.gpr .rsi = s₀.gpr .rsi + BitVec.ofNat 64 (32 * i)
+ rd : s.rd = s₀.rd
+ wr : s.wr = s₀.wr
+ q : ∀ l < 2, s.lane .xmm15 l = qV
+ frame : Frame [pR (s₀.gpr .rdi)] s₀.mem s.mem
+ coeff : ∀ k < 256, coeffAt s.mem (s₀.gpr .rdi) k = if k < 8 * i then v k else coeffAt s₀.mem (s₀.gpr .rdi) k
+
+section
+variable {t : Poly → Poly → Poly} {s₀ : State} (hp : (accK t).pre s₀)
+ {op : XBinOp} {fix : List Instr} {F : BitVec 128 → BitVec 128 → BitVec 128}
+ {L : BitVec 32 → BitVec 32 → BitVec 32}
+ (hF : ∀ (s : State), s.xmm .xmm15 = qV →
+ WP isa (.block (xb op .xmm0 .xmm1 :: fix)) s fun s' =>
+ s'.xmm .xmm0 = F (s.xmm .xmm0) (s.xmm .xmm1) ∧ XOnly [.xmm0, .xmm2] s s')
+ (hY : laneSseBlock (toY (xb op .xmm0 .xmm1 :: fix)) = some (xb op .xmm0 .xmm1 :: fix))
+ (hL : ∀ x y : BitVec 128, ∀ e < 4, dword (F x y) e = L (dword x e) (dword y e))
+include hp hF hY hL
+
+/-- An iteration, which stores `F` of the vectors of `f` and `g` in each lane. -/
+theorem step {i : Nat} (hi : i < 32) {s : State}
+ (hI : Inv s₀ (fun k => L (coeffAt s₀.mem (s₀.gpr .rdi) k) (coeffAt s₀.mem (s₀.gpr .rsi) k)) i s) :
+ WP isa (.block (yaccBody op fix ++ ([.alu .sub .rcx (.imm 1)] : List Instr))) s fun s' =>
+ Inv s₀ (fun k => L (coeffAt s₀.mem (s₀.gpr .rdi) k) (coeffAt s₀.mem (s₀.gpr .rsi) k)) (i + 1) s' ∧
+ s'.gpr .rcx = s.gpr .rcx - 1 ∧ s'.zf = some (s.gpr .rcx - 1 == 0) := by
+ have j0 : 8 * i + 8 ≤ 256 := by omega
+ have hw : pR (s₀.gpr .rdi) ∈ s.wr := by rw [hI.wr, hp.2.1]; simp
+ have hr : pR (s₀.gpr .rsi) ∈ s.rd ++ s.wr := by rw [hI.rd, hI.wr, hp.1]; simp
+ have e1 : s.gpr .rdi + BitVec.ofNat 64 0 = coeffAddr (s₀.gpr .rdi) (8 * i) := by
+ rw [add_ofNat_zero, hI.rdi]; congr 2; omega
+ have e2 : s.gpr .rsi + BitVec.ofNat 64 0 = coeffAddr (s₀.gpr .rsi) (8 * i) := by
+ rw [add_ofNat_zero, hI.rsi]; congr 2; omega
+ rw [yaccBody, List.append_assoc, List.append_assoc, WP.block_append_iff,
+ show ∀ a b : Instr, [a, b] = [a] ++ [b] from fun _ _ => rfl, WP.block_append_iff]
+ refine WP.mono (yld_ok (by rw [e1]; exact f_in32 (List.mem_append_right _ hw) j0)) fun s1 ⟨L1, o1⟩ => ?_
+ refine WP.mono (yld_ok (by rw [o1.rd, o1.wr, o1.gpr, e2]; exact ⟨_, hr, pR_contains32 _ j0⟩))
+ fun s2 ⟨L2, o2⟩ => ?_
+ rw [WP.block_append_iff]
+ have o12 := o1.trans o2
+ refine WP.mono (ylanes hY (P := fun l t => t.xmm .xmm0 = F ((s2.proj l).xmm .xmm0) ((s2.proj l).xmm .xmm1))
+ fun l hl => hF _ (by rw [State.proj_xmm, o12.lane _ (by decide) l hl]; exact hI.q l hl))
+ fun s3 ⟨B3, o3⟩ => ?_
+ have o13 := o12.trans o3
+ have g3 : s3.gpr .rdi = coeffAddr (s₀.gpr .rdi) (8 * i) := by rw [o13.gpr, ← e1, add_ofNat_zero]
+ have g3' : s3.gpr .rsi = coeffAddr (s₀.gpr .rsi) (8 * i) := by rw [o13.gpr, ← e2, add_ofNat_zero]
+ have w0 : InRegions s3.wr (s3.gpr .rdi) 32 := by rw [o13.wr, g3]; exact f_in32 hw j0
+ vrund [State.store256_eq, State.setMem_gpr, State.setMem_wr, State.setMem_mem, State.setMem_rd,
+ State.setMem_ymm, w0, sx32]
+ refine ⟨⟨?_, ?_, ?_, ?_, fun l hl => ?_, ?_, fun k hk => ?_⟩, ?_⟩
+ · simp only [RegUpd.gpr_setReg, RegUpd.gpr_setFlags, ite_true, ite_false, reduceCtorEq, State.setMem_gpr]
+ rw [o13.gpr, hI.rdi]; exact ptr_step _ i 32
+ · simp only [RegUpd.gpr_setReg, RegUpd.gpr_setFlags, ite_true, ite_false, reduceCtorEq, State.setMem_gpr]
+ rw [o13.gpr, hI.rsi]; exact ptr_step _ i 32
+ · simp only [RegUpd.rd_setReg, RegUpd.rd_setFlags, State.setMem_rd]; rw [o13.rd, hI.rd]
+ · simp only [RegUpd.wr_setReg, RegUpd.wr_setFlags, State.setMem_wr]; rw [o13.wr, hI.wr]
+ · simp only [lane_setReg, lane_setFlags, State.setMem_lane]; rw [o13.lane _ (by decide) l hl]; exact hI.q l hl
+ · simp only [RegUpd.mem_setReg, RegUpd.mem_setFlags, State.setMem_mem]
+ rw [g3, o13.mem]; exact hI.frame.writeW (List.mem_singleton_self _) _ (pR_contains32 _ j0)
+ · simp only [RegUpd.mem_setReg, RegUpd.mem_setFlags, State.setMem_mem]
+ rw [g3, o13.mem, coeffAt_write256 _ _ j0 _ hk]
+ split
+ · rename_i h
+ rw [ifp (show k < 8 * (i + 1) by omega), State.ymm, extract_ymm _ _ (by omega)]
+ have hc : ∀ l < 2, ∀ e < 4, dword (s3.lane .xmm0 l) e =
+ L (coeffAt s₀.mem (s₀.gpr .rdi) (8 * i + 4 * l + e)) (coeffAt s₀.mem (s₀.gpr .rsi) (8 * i + 4 * l + e)) :=
+ fun l hl e he => by
+ rw [← State.proj_xmm, B3 l hl, hL _ _ _ he, State.proj_xmm, State.proj_xmm,
+ o2.lane _ (by decide) l hl, L1 l hl, L2 l hl, o1.gpr, o1.mem, e1, e2, dword_readW _ _ he,
+ dword_readW _ _ he, lane_load, lane_load, coeffAddr_add, coeffAddr_add, ← coeffAt_eq, ← coeffAt_eq,
+ hI.coeff _ (by omega), ifn (by omega),
+ coeffAt_frame hI.frame (by simpa using hp.2.2.1.symm) (by rw [n_eq]; omega)]
+ split
+ · rename_i h4
+ have := hc 0 (by decide) (k - 8 * i) h4
+ rw [show 8 * i + 4 * 0 + (k - 8 * i) = k by omega] at this
+ exact this
+ · rename_i h4
+ have := hc 1 (by decide) (k - 8 * i - 4) (by omega)
+ rw [show 8 * i + 4 * 1 + (k - 8 * i - 4) = k by omega] at this
+ exact this
+ · rename_i h
+ rw [hI.coeff k hk]
+ by_cases h' : k < 8 * i
+ · rw [ifp h', ifp (by omega)]
+ · rw [ifn h', ifn (by omega)]
+ · exact ⟨by rw [o13.gpr], by rw [o13.gpr]⟩
+
+/-- The whole function, from its precondition. -/
+theorem fn_ok (hv : ∀ k < 256, (L (coeffAt s₀.mem (s₀.gpr .rdi) k) (coeffAt s₀.mem (s₀.gpr .rsi) k)).toNat =
+ ((t (polyAt s₀.mem (s₀.gpr .rdi)) (polyAt s₀.mem (s₀.gpr .rsi)))[k]!).val)
+ (hc : writesOnly [.rax, .rdi, .rsi, .rcx] (.seq (.block (yconst .xmm15 8380417))
+ (.seq (VG.Impl.MlKem.X86_64.rcxLoop 32 (yaccBody op fix)) (.block yepi))) = true)
+ (hm : Code.allInstrs (fun i => !loadsMxcsr i) (.seq (.block (yconst .xmm15 8380417))
+ (.seq (VG.Impl.MlKem.X86_64.rcxLoop 32 (yaccBody op fix)) (.block yepi)) : Prog isa) = true) :
+ ∃ tr s', Exec isa (.seq (.block (yconst .xmm15 8380417))
+ (.seq (VG.Impl.MlKem.X86_64.rcxLoop 32 (yaccBody op fix)) (.block yepi))) s₀ tr s' ∧
+ abiPreserved s₀ s' ∧ (accK t).post s₀ s' := by
+ have hW : WP isa (.seq (.block (yconst .xmm15 8380417))
+ (.seq (VG.Impl.MlKem.X86_64.rcxLoop 32 (yaccBody op fix)) (.block yepi))) s₀ fun s' =>
+ Frame [pR (s₀.gpr .rdi)] s₀.mem s'.mem ∧ ∀ k < 256, coeffAt s'.mem (s₀.gpr .rdi) k =
+ L (coeffAt s₀.mem (s₀.gpr .rdi) k) (coeffAt s₀.mem (s₀.gpr .rsi) k) := by
+ refine WP.seq (WP.mono (yconst_ok .xmm15 _ s₀) fun w ⟨lq, k1, m1, _, _⟩ => ?_)
+ refine WP.seq (WP.mono (wp_rcxLoopY (N := 32) (by decide) (by decide) _ (fun u o hy _ =>
+ ⟨by rw [o.keep.gpr (by decide), k1.gpr (by decide), Nat.mul_zero, add_ofNat_zero],
+ by rw [o.keep.gpr (by decide), k1.gpr (by decide), Nat.mul_zero, add_ofNat_zero],
+ by rw [o.keep.2.1, k1.2.1], by rw [o.keep.2.2, k1.2.2],
+ fun l hl => by
+ rw [show u.lane .xmm15 l = w.lane .xmm15 l by simp only [State.lane]; rw [o.xmm, hy], lq l hl]; decide,
+ by rw [o.mem, m1]; exact Frame.refl _ _, fun k _ => by rw [o.mem, m1, ifn (by omega)]⟩)
+ fun i hi u hI => step hp hF hY hL hi hI) fun u hI => ?_)
+ refine WP.mono (Q := fun (u' : State) => u'.mem = u.mem) (by simp only [yepi]; vrund; rfl) fun u' hm' => ?_
+ rw [hm']
+ exact ⟨hI.frame, fun k hk => by rw [hI.coeff k hk, ifp (by omega)]⟩
+ obtain ⟨tr, s', he, ⟨hf, hco⟩, hk⟩ := WP.keep _ hW hc
+ refine ⟨tr, s', he, abiPreserved_of_exec hm he (gprPreserved_of hk (by decide) hf ?_),
+ polyIs_of_toNat fun k hk => ?_⟩
+ · simpa using hp.2.2.2.1
+ · rw [n_eq] at hk
+ rw [hco k hk]
+ exact hv k hk
+
+end
+
+end YAddSub
+
+end VG.Proof.MlDsa.X86_64.Arith
+
+namespace VG.Proof.MlDsa.X86_64.Arith
+
+open VG VG.X86_64 VG.Impl.MlDsa.X86_64.Arith
+open VG.Proof.MlDsa.Arith
+open VG.Spec.MlDsa (n)
+
+theorem addY_correct (s : State) (hs : (accK Spec.MlDsa.add).pre s) :
+ ∃ t s', Exec isa addAvx2 s t s' ∧ abiPreserved s s' ∧ (accK Spec.MlDsa.add).post s s' :=
+ YAddSub.fn_ok hs (op := .paddd) (fix := vcsub .xmm0 .xmm2) (L := fun a b => csubL (a + b)) addFixX_ok
+ lane_addFix (fun x y e he => dword_addV x y he)
+ (fun k hk => by
+ have hk' : k < n := by rw [n_eq]; exact hk
+ rw [add_get _ _ hk', addD_toNat (by rw [← polyAt_val hs.2.2.2.2.2.1 hk']; exact val_lt _)
+ (by rw [← polyAt_val hs.2.2.2.2.2.2 hk']; exact val_lt _),
+ ← polyAt_val hs.2.2.2.2.2.1 hk', ← polyAt_val hs.2.2.2.2.2.2 hk', val_add])
+ (by decide +kernel) (by decide +kernel)
+
+theorem subY_correct (s : State) (hs : (accK Spec.MlDsa.sub).pre s) :
+ ∃ t s', Exec isa subAvx2 s t s' ∧ abiPreserved s s' ∧ (accK Spec.MlDsa.sub).post s s' :=
+ YAddSub.fn_ok hs (op := .psubd) (fix := vcadd .xmm0 .xmm2) (L := fun a b => caddL (a - b)) subFixX_ok
+ lane_subFix (fun x y e he => dword_subV x y he)
+ (fun k hk => by
+ have hk' : k < n := by rw [n_eq]; exact hk
+ rw [sub_get _ _ hk', subD_toNat (by rw [← polyAt_val hs.2.2.2.2.2.1 hk']; exact val_lt _)
+ (by rw [← polyAt_val hs.2.2.2.2.2.2 hk']; exact val_lt _),
+ ← polyAt_val hs.2.2.2.2.2.1 hk', ← polyAt_val hs.2.2.2.2.2.2 hk', val_sub])
+ (by decide +kernel) (by decide +kernel)
+
+theorem addY_ct : ConstantTime isa (accK Spec.MlDsa.add).pre (accK Spec.MlDsa.add).pub addAvx2 :=
+ VG.Taint.constantTime (A := taint) accτ acc_agree (by taint_decide)
+
+theorem subY_ct : ConstantTime isa (accK Spec.MlDsa.sub).pre (accK Spec.MlDsa.sub).pub subAvx2 :=
+ VG.Taint.constantTime (A := taint) accτ acc_agree (by taint_decide)
+
+theorem addY_verified : Verified X86_64.target addAvx2 (Spec.MlDsa.addContract X86_64.abi) :=
+ Verified.of_correct addY_correct addY_ct (by
+ mldsa_implies [Spec.MlDsa.addContract, Spec.MlDsa.accSig, accK, X86_64.abi, X86_64.argRegs]
+ [accSat] using accSat)
+
+theorem subY_verified : Verified X86_64.target subAvx2 (Spec.MlDsa.subContract X86_64.abi) :=
+ Verified.of_correct subY_correct subY_ct (by
+ mldsa_implies [Spec.MlDsa.subContract, Spec.MlDsa.accSig, accK, X86_64.abi, X86_64.argRegs]
+ [accSat] using accSat)
+
+end VG.Proof.MlDsa.X86_64.Arith
diff --git a/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YBase.lean b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YBase.lean
new file mode 100644
index 000000000..b5f4c278b
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YBase.lean
@@ -0,0 +1,130 @@
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.VLay
+import VerifiedGarbage.Proof.MlKem.X86_64.YLanes
+import VerifiedGarbage.Impl.MlDsa.X86_64.Arith.Avx2
+
+/-!
+# ML-DSA on x86-64: coefficients in the lanes of AVX2 registers
+
+Untrusted: everything here is checked by Lean. The AVX2 code does to each
+128-bit lane what the SSE2 code does to a register (`toY`), so the proofs
+of the SSE2 code hold of each lane (`ylanes`, ML-KEM's): `YConsts` is
+`VConsts` in both lanes (`yconsts_ok`); a 256-bit load of coefficient `j`
+puts coefficients `j + 4l` to `j + 4l + 3` in lane `l` (`ylanes_load`),
+and a 256-bit store of a register whose lanes hold `a` and `a (· + 4)`
+puts `a` at coefficients `j` to `j + 7` (`polyIs_write2Y`, `ylanes_ymm`).
+-/
+
+namespace VG.Proof.MlDsa.X86_64.Arith
+
+open VG VG.X86_64 VG.Impl.MlDsa.X86_64.Arith
+open VG.Proof.MlDsa.Arith
+open VG.Proof.MlKem.X86_64 (Keep XOnly XKeep YOnly ylanes yld_ok yconst_ok ifp ifn)
+open VG.Spec.MlDsa (q n Poly Zq coeffAt polyAt PolyIs)
+
+/-- `VConsts` in both lanes. -/
+def YConsts (s : State) : Prop := ∀ l < 2, VConsts (s.proj l)
+
+theorem yonly_yconsts {rs : List XReg} {s s' : State} (h : YOnly rs s s') (hc : YConsts s)
+ (h14 : XReg.xmm14 ∉ rs) (h15 : XReg.xmm15 ∉ rs) : YConsts s' := fun l hl =>
+ ⟨by rw [State.proj_xmm, h.lane _ h15 l hl]; exact (hc l hl).q,
+ by rw [State.proj_xmm, h.lane _ h14 l hl]; exact (hc l hl).qinv⟩
+
+/-- The constants in both lanes. -/
+theorem yconsts_ok (s : State) :
+ WP isa (.block yconsts) s fun s' => YConsts s' ∧ Keep [.rax] s s' ∧ s'.mem = s.mem ∧
+ s'.mxcsr = s.mxcsr ∧ ∀ r, r ≠ .xmm15 → r ≠ .xmm14 → ∀ l < 2, s'.lane r l = s.lane r l := by
+ rw [yconsts, WP.block_append_iff]
+ refine WP.mono (yconst_ok .xmm15 _ s) fun s1 ⟨l1, k1, m1, x1, o1⟩ =>
+ WP.mono (yconst_ok .xmm14 _ s1) fun s2 ⟨l2, k2, m2, x2, o2⟩ =>
+ ⟨fun l hl => ⟨?_, ?_⟩, (k1.trans k2).mono (by simp), m2.trans m1, x2.trans x1,
+ fun r h15 h14 l hl => by rw [o2 r h14 l hl, o1 r h15 l hl]⟩
+ · rw [State.proj_xmm, o2 _ (by decide) l hl, l1 l hl]; decide
+ · rw [State.proj_xmm, l2 l hl]; decide
+
+/-- The eight doublewords of a 256-bit value, as those of its lanes. -/
+theorem extract_ymm (hi lo : BitVec 128) {e : Nat} (he : e < 8) :
+ (hi ++ lo).extractLsb' (32 * e) 32 = if e < 4 then dword lo e else dword hi (e - 4) := by
+ by_cases h4 : e < 4
+ · rw [ifp h4]
+ apply BitVec.eq_of_getLsbD_eq; intro i hi'
+ simp only [dword, BitVec.getLsbD_extractLsb', hi', decide_true, Bool.true_and, BitVec.getLsbD_append,
+ ifp (show 32 * e + i < 128 by omega)]
+ · rw [ifn h4]
+ apply BitVec.eq_of_getLsbD_eq; intro i hi'
+ simp only [dword, BitVec.getLsbD_extractLsb', hi', decide_true, Bool.true_and, BitVec.getLsbD_append,
+ ifn (show ¬32 * e + i < 128 by omega)]
+ exact congrArg _ (by omega)
+
+/-- The doublewords of a 256-bit value are the coefficients `a`. -/
+def YLanes (x : BitVec 256) (a : Nat → Zq) : Prop := ∀ e < 8, (x.extractLsb' (32 * e) 32).toNat = (a e).val
+
+/-- A register whose lanes hold `a` and `a (· + 4)`. -/
+theorem ylanes_ymm {s : State} {r : XReg} {a : Nat → Zq} (h0 : DLanes (s.lane r 0) a)
+ (h1 : DLanes (s.lane r 1) (fun e => a (e + 4))) : YLanes (s.ymm r) a := fun e he => by
+ have h0' : DLanes (s.xmm r) a := h0
+ have h1' : DLanes (s.ymmHi r) (fun e => a (e + 4)) := h1
+ rw [State.ymm, extract_ymm _ _ he]
+ split
+ · exact h0' e (by omega)
+ · rw [h1' (e - 4) (by omega)]; dsimp only; rw [show e - 4 + 4 = e by omega]
+
+/-- Coefficient `i` after storing `x` at coefficient `j`. -/
+theorem coeffAt_write256 (m : Mem) (p : Addr) {j : Nat} (hj : j + 8 ≤ 256) (x : BitVec 256) {i : Nat}
+ (hi : i < 256) :
+ coeffAt (m.writeW (coeffAddr p j) x) p i =
+ if j ≤ i ∧ i < j + 8 then x.extractLsb' (32 * (i - j)) 32 else coeffAt m p i := by
+ split
+ · rename_i h
+ rw [coeffAt_eq, show coeffAddr p i = coeffAddr p j + BitVec.ofNat 64 (4 * (i - j)) by
+ rw [coeffAddr_add, show j + (i - j) = i by omega]]
+ rw [show 32 * (i - j) = 8 * (4 * (i - j)) by omega]
+ exact readW_writeW_inside (k := 4 * (i - j)) (n := 4) _ _ _ (by omega) (by decide)
+ · exact Mem.readW_writeW_sep (Offset.sep p (by omega) (by omega) (by omega)) (by decide)
+
+/-- Two vectors of eight coefficients stored into a polynomial. -/
+theorem polyIs_write2Y {m : Mem} {p : Addr} {P R : Poly} (hP : PolyIs m p P) {j j' : Nat}
+ (hj : j + 8 ≤ 256) (hj' : j' + 8 ≤ 256) (hsep : j + 8 ≤ j' ∨ j' + 8 ≤ j) {x y : BitVec 256}
+ {a b : Nat → Zq} (hx : YLanes x a) (hy : YLanes y b)
+ (hR : ∀ i < 256, R[i]! = if j ≤ i ∧ i < j + 8 then a (i - j)
+ else if j' ≤ i ∧ i < j' + 8 then b (i - j') else P[i]!) :
+ PolyIs ((m.writeW (coeffAddr p j) x).writeW (coeffAddr p j') y) p R := polyIs_of_toNat fun i hi => by
+ rw [n_eq] at hi
+ rw [coeffAt_write256 _ _ hj' _ hi, coeffAt_write256 _ _ hj _ hi, hR i hi]
+ by_cases h1 : j' ≤ i ∧ i < j' + 8
+ · rw [ite_eq_left_of_eq_true _ _ (eq_true h1), ite_eq_right_of_eq_false _ _ (eq_false (by omega)),
+ ite_eq_left_of_eq_true _ _ (eq_true h1)]
+ exact hy _ (by omega)
+ · rw [ite_eq_right_of_eq_false _ _ (eq_false h1)]
+ by_cases h2 : j ≤ i ∧ i < j + 8
+ · rw [ite_eq_left_of_eq_true _ _ (eq_true h2), ite_eq_left_of_eq_true _ _ (eq_true h2)]
+ exact hx _ (by omega)
+ · rw [ite_eq_right_of_eq_false _ _ (eq_false h2), ite_eq_right_of_eq_false _ _ (eq_false h2),
+ ite_eq_right_of_eq_false _ _ (eq_false h1)]
+ exact polyIs_toNat hP (by rw [n_eq]; exact hi)
+
+theorem pR_contains32 (p : Addr) {j : Nat} (hj : j + 8 ≤ 256) : (pR p).Contains (coeffAddr p j) 32 :=
+ Offset.contains_base p (by omega) (by omega)
+
+theorem f_in32 {rs : List Region} {fP : Addr} (hw : pR fP ∈ rs) {j : Nat} (hj : j + 8 ≤ 256) :
+ InRegions rs (coeffAddr fP j) 32 :=
+ ⟨_, hw, pR_contains32 fP hj⟩
+
+theorem frame_write2Y {m m' : Mem} {p : Addr} (hf : Frame [pR p] m m') {j j' : Nat} (hj : j + 8 ≤ 256)
+ (hj' : j' + 8 ≤ 256) (x y : BitVec 256) :
+ Frame [pR p] m ((m'.writeW (coeffAddr p j) x).writeW (coeffAddr p j') y) :=
+ (hf.writeW (List.mem_singleton_self _) x (pR_contains32 p hj)).writeW (List.mem_singleton_self _) y
+ (pR_contains32 p hj')
+
+/-- Lane `l` of a 256-bit load of coefficient `j`. -/
+theorem lane_load {p : Addr} {j l : Nat} :
+ coeffAddr p j + BitVec.ofNat 64 (16 * l) = coeffAddr p (j + 4 * l) := by
+ rw [show 16 * l = 4 * (4 * l) by omega, coeffAddr_add]
+
+/-- The lanes of a 256-bit load of coefficient `j` of `F`. -/
+theorem dlanes_loadY {m : Mem} {p : Addr} {F : Poly} (h : PolyIs m p F) {j : Nat} (hj : j + 8 ≤ 256)
+ {l : Nat} (hl : l < 2) :
+ DLanes (m.readW (coeffAddr p j + BitVec.ofNat 64 (16 * l)) 128) (fun e => F[j + 4 * l + e]!) := by
+ rw [lane_load]
+ exact dlanes_load h (by omega)
+
+end VG.Proof.MlDsa.X86_64.Arith
diff --git a/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YLay.lean b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YLay.lean
new file mode 100644
index 000000000..3468aa875
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YLay.lean
@@ -0,0 +1,632 @@
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.YBase
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.VLay21
+import VerifiedGarbage.Proof.MlKem.X86_64.YNtt
+import VerifiedGarbage.Proof.MlKem.X86_64.YNttLay
+
+/-!
+# ML-DSA on x86-64: the layers of the NTT and its inverse with `len ≥ 4` on AVX2 registers
+
+Untrusted: everything here is checked by Lean. For any butterfly code `bf`
+that does what `op` does to the doublewords of two SSE registers
+(`VBflyOk`) and whose AVX2 form does it in each lane
+(`laneSseBlock (toY bf) = some bf`), and any block of the specification
+whose butterflies do `op` (`BlkOk`): eight butterflies of a block
+(`ystep`), the `len / 8` of them of a block (`yblock_ok`), and the
+`128 / len` blocks of a layer with `len ≥ 8` (`ylay_ok`); and the layer
+with `len = 4`, two blocks at a time, the lower halves of their
+coefficients gathered into `ymm0` and the upper ones into `ymm1` by
+`vperm2i128` (`ylay4_ok`). The zetas: `yzeta1_ok` and `yzetaS_ok`, and the
+layers' result coefficient by coefficient (`layF_get`).
+-/
+
+namespace VG.Proof.MlDsa.X86_64.Arith
+
+open VG VG.X86_64 VG.Impl.MlDsa.X86_64.Arith
+open VG.Proof.MlDsa.Arith
+open VG.Proof.MlKem.X86_64 (Keep XOnly XKeep YOnly ylanes yld_ok ifp ifn sel sel_lt sel_zero sel_55
+ add_ofNat_zero GOnly addR_ok wp_rcxLoopY wp_countdown ybcast_ok yblend_ok yperm_ok perm20 perm31
+ wp_cons_iff lane_setReg lane_setFlags State.setMem_ymm State.setMem_setMem sx32)
+open VG.Impl.MlKem.X86_64 (xb xmov toY rcxLoop)
+open VG.Spec.MlDsa (q n Poly Zq coeffAt polyAt PolyIs zetas)
+
+/-! ## A layer, coefficient by coefficient -/
+
+section
+variable {op : Zq → Zq → Zq → Zq × Zq} {blk : Poly → Nat → Nat → Nat → Nat → Poly} (hblk : BlkOk blk op)
+include hblk
+
+/-- Each coefficient after the first `b` blocks of the layer with `len`. -/
+theorem layF_get (F : Poly) {len : Nat} (hl : 0 < len) (zi : Nat → Nat) {b : Nat} (hb : 2 * len * b ≤ 256)
+ {j : Nat} (hj : j < 256) :
+ (layF blk F len zi b)[j]! = if j < 2 * len * b then
+ (if j % (2 * len) < len then (op F[j]! F[j + len]! (zetas (zi (j / (2 * len))))).1
+ else (op F[j - len]! F[j]! (zetas (zi (j / (2 * len))))).2) else F[j]! := by
+ induction b generalizing j with
+ | zero => rw [ite_eq_right (by omega)]; rfl
+ | succ b ih =>
+ have hb' : 2 * len * b + 2 * len ≤ 256 := by rw [Nat.mul_succ] at hb; exact hb
+ rw [layF, foldl_range_succ, ← layF,
+ hblk.get _ len _ _ len hl (Nat.le_refl _) (by rw [n_eq]; omega) j (by rw [n_eq]; exact hj)]
+ have hd : ∀ i, 2 * len * b ≤ i → i < 2 * len * b + 2 * len → i / (2 * len) = b ∧
+ i % (2 * len) = i - 2 * len * b := fun i h1 h2 => by
+ have e1 : i / (2 * len) = b := by
+ apply Nat.div_eq_of_lt_le
+ · rw [Nat.mul_comm]; exact h1
+ · rw [Nat.succ_mul, Nat.mul_comm b]; exact h2
+ refine ⟨e1, ?_⟩
+ have := Nat.div_add_mod i (2 * len)
+ rw [e1] at this; omega
+ by_cases h1 : 2 * len * b ≤ j ∧ j < 2 * len * b + len
+ · obtain ⟨d1, d2⟩ := hd j h1.1 (by omega)
+ rw [ite_eq_left_of_eq_true _ _ (eq_true h1), ih (by omega) hj, ih (by omega) (by omega), d1,
+ ite_eq_left_of_eq_true _ _ (eq_true (show j < 2 * len * (b + 1) by rw [Nat.mul_succ]; omega)),
+ ite_eq_left_of_eq_true _ _ (eq_true (show j % (2 * len) < len by omega)),
+ ite_eq_right_of_eq_false _ _ (eq_false (show ¬ j < 2 * len * b by omega)),
+ ite_eq_right_of_eq_false _ _ (eq_false (show ¬ j + len < 2 * len * b by omega))]
+ · rw [ite_eq_right_of_eq_false _ _ (eq_false h1)]
+ by_cases h2 : 2 * len * b + len ≤ j ∧ j < 2 * len * b + len + len
+ · obtain ⟨d1, d2⟩ := hd j (by omega) (by omega)
+ rw [ite_eq_left_of_eq_true _ _ (eq_true h2), ih (by omega) (by omega), ih (by omega) hj, d1,
+ ite_eq_left_of_eq_true _ _ (eq_true (show j < 2 * len * (b + 1) by rw [Nat.mul_succ]; omega)),
+ ite_eq_right_of_eq_false _ _ (eq_false (show ¬ j % (2 * len) < len by omega)),
+ ite_eq_right_of_eq_false _ _ (eq_false (show ¬ j - len < 2 * len * b by omega)),
+ ite_eq_right_of_eq_false _ _ (eq_false (show ¬ j < 2 * len * b by omega))]
+ · rw [ite_eq_right_of_eq_false _ _ (eq_false h2), ih (by omega) hj]
+ by_cases h3 : j < 2 * len * b
+ · rw [ite_eq_left_of_eq_true _ _ (eq_true h3),
+ ite_eq_left_of_eq_true _ _ (eq_true (show j < 2 * len * (b + 1) by rw [Nat.mul_succ]; omega))]
+ · rw [ite_eq_right_of_eq_false _ _ (eq_false h3),
+ ite_eq_right_of_eq_false _ _ (eq_false (show ¬ j < 2 * len * (b + 1) by rw [Nat.mul_succ]; omega))]
+
+end
+
+/-! ## Coefficients in both lanes -/
+
+/-- The facts a piece of a layer keeps. -/
+structure BInvY (fP : Addr) (s₀ s : State) : Prop where
+ keep : Keep [.r8, .rcx, .rdx, .rax] s₀ s
+ frame : Frame [pR fP] s₀.mem s.mem
+ consts : YConsts s
+ mxcsr : s.mxcsr = s₀.mxcsr
+
+theorem BInvY.trans {fP : Addr} {s₁ s₂ s₃ : State} (h₁ : BInvY fP s₁ s₂) (h₂ : BInvY fP s₂ s₃) :
+ BInvY fP s₁ s₃ :=
+ ⟨(h₁.keep.trans h₂.keep).mono (by simp), h₁.frame.trans h₂.frame, h₂.consts, h₂.mxcsr.trans h₁.mxcsr⟩
+
+/-- `YConsts` after code that changed the vector registers `rs` only, then
+nothing in them. -/
+theorem ylanes_gpr {s s' : State} (h : ∀ r l, s'.lane r l = s.lane r l) {rs : List XReg} {s₀ : State}
+ (o : YOnly rs s₀ s) (hc : YConsts s₀) (h14 : XReg.xmm14 ∉ rs) (h15 : XReg.xmm15 ∉ rs) : YConsts s' :=
+ fun l hl => ⟨by rw [State.proj_xmm, h]; exact (yonly_yconsts o hc h14 h15 l hl).q,
+ by rw [State.proj_xmm, h]; exact (yonly_yconsts o hc h14 h15 l hl).qinv⟩
+
+/-- Two registers stored into a polynomial at coefficients `j` and `j'`,
+lane `l` of each holding the four coefficients of `R` from `j + 4l` and
+`j' + 4l`. -/
+theorem polyIs_write2L {m : Mem} {p : Addr} {P R : Poly} (hP : PolyIs m p P) {j j' : Nat}
+ (hj : j + 8 ≤ 256) (hj' : j' + 8 ≤ 256) (hsep : j + 8 ≤ j' ∨ j' + 8 ≤ j) {s : State} {x y : XReg}
+ (hx : ∀ l < 2, DLanes (s.lane x l) (fun e => R[j + 4 * l + e]!))
+ (hy : ∀ l < 2, DLanes (s.lane y l) (fun e => R[j' + 4 * l + e]!))
+ (hR : ∀ i < 256, (i < j ∨ j + 8 ≤ i) → (i < j' ∨ j' + 8 ≤ i) → R[i]! = P[i]!) :
+ PolyIs ((m.writeW (coeffAddr p j) (s.ymm x)).writeW (coeffAddr p j') (s.ymm y)) p R :=
+ polyIs_write2Y hP hj hj' hsep (a := fun e => R[j + e]!) (b := fun e => R[j' + e]!)
+ (ylanes_ymm (fun e he => (hx 0 (by decide) e he).trans (by simp only [Nat.mul_zero, Nat.add_zero]))
+ (fun e he => (hx 1 (by decide) e he).trans (by dsimp only; rw [show j + 4 * 1 + e = j + (e + 4) by omega])))
+ (ylanes_ymm (fun e he => (hy 0 (by decide) e he).trans (by simp only [Nat.mul_zero, Nat.add_zero]))
+ (fun e he => (hy 1 (by decide) e he).trans (by dsimp only; rw [show j' + 4 * 1 + e = j' + (e + 4) by omega])))
+ fun i hi => by
+ by_cases h1 : j ≤ i ∧ i < j + 8
+ · rw [ite_eq_left_of_eq_true _ _ (eq_true h1), show j + (i - j) = i by omega]
+ · rw [ite_eq_right_of_eq_false _ _ (eq_false h1)]
+ by_cases h2 : j' ≤ i ∧ i < j' + 8
+ · rw [ite_eq_left_of_eq_true _ _ (eq_true h2), show j' + (i - j') = i by omega]
+ · rw [ite_eq_right_of_eq_false _ _ (eq_false h2)]; exact hR i hi (by omega) (by omega)
+
+theorem DLanes.congr {x : BitVec 128} {f g : Nat → Zq} (h : DLanes x f) (e : ∀ i < 4, f i = g i) : DLanes x g :=
+ fun i hi => by rw [h i hi, e i hi]
+
+theorem ZLanes.congr {x : BitVec 128} {f g : Nat → Zq} (h : ZLanes x f) (e : ∀ i < 4, f i = g i) : ZLanes x g :=
+ fun i hi => by rw [h i hi, e i hi]
+
+theorem getP_congr (P : Poly) {a b : Nat} (h : a = b) : P[a]! = P[b]! := h ▸ rfl
+
+/-- A butterfly of the coefficients at `a` and `b` of `P` with the zeta of
+index `zi c`, at other indices that are the same. -/
+theorem op_idx (op : Zq → Zq → Zq → Zq × Zq) (P : Poly) (zi : Nat → Nat) {a b c a' b' c' : Nat} (ha : a = a')
+ (hb : b = b') (hc : c = c') : op P[a]! P[b]! (zetas (zi c)) = op P[a']! P[b']! (zetas (zi c')) := by
+ subst ha hb hc; rfl
+
+/-- The prologue of the layers with `len` = 4, 2 and 1. -/
+theorem ypre21 {fP sP : Addr} (k : Nat) (hk : k + 4 ≤ 256) {s : State} (hdi : s.gpr .rdi = fP)
+ (hsi : s.gpr .rsi = sP) :
+ WP isa (.block (([.mov .rdx (.reg .rdi)] : List Instr) ++ leaR .r8 .rsi (4 * k))) s fun w =>
+ w.gpr .rdx = fP ∧ w.gpr .r8 = coeffAddr sP k ∧ GOnly [.rdx, .r8] s w ∧ w.ymmHi = s.ymmHi := by
+ simp only [leaR]
+ vrund [sx_ofNat (show 4 * k < 2 ^ 31 by omega), hsi, hdi]
+ exact ⟨by gonlyd, rfl⟩
+
+/-! ## The zetas -/
+
+theorem zodd_F5 (x : BitVec 128) : ZOdd x (shufDwords x 0xF5) := fun j hj => by
+ rw [dword_shufDwords _ _ (by omega)]
+ rcases (by omega : j = 0 ∨ j = 1) with rfl | rfl <;> rfl
+
+/-- The zetas `pshufd` with `o` leaves of the four at index `k` of the table. -/
+theorem zlanes_tab (o : BitVec 8) {zP : Addr} {k : Nat} (hk : ∀ j < 4, k + sel o j < 256) {m : Mem}
+ (ht : Tab zmTab m zP 256) :
+ ZLanes (shufDwords (m.readW (coeffAddr zP k) 128) o) (fun i => zetas (k + sel o i)) := fun i hi => by
+ have hs := sel_lt o i
+ rw [dword_shufDwords_sel _ _ hi, dword_readW _ _ hs, coeffAddr_add]
+ exact tab_zeta ht (hk i hi)
+
+theorem zsse1_ok (t : State) :
+ WP isa (.block [.xop (.pshufd .xmm13 .xmm13 0), .xop (.pshufd .xmm12 .xmm13 0xF5)]) t fun t' =>
+ (t'.xmm .xmm13 = shufDwords (t.xmm .xmm13) 0 ∧
+ t'.xmm .xmm12 = shufDwords (shufDwords (t.xmm .xmm13) 0) 0xF5) ∧ XOnly [.xmm13, .xmm12] t t' := by
+ vrun
+ exact ⟨by first | trivial | simp, by xonly⟩
+
+theorem yzeta1_ok {zP : Addr} {k : Nat} (hk : k + 4 ≤ 256) {s : State} (h8 : s.gpr .r8 = coeffAddr zP k)
+ (hin : InRegions (s.rd ++ s.wr) (coeffAddr zP k) 16) (ht : Tab zmTab s.mem zP 256) :
+ WP isa (.block yzeta1) s fun s' => (∀ l < 2, ZLanes (s'.lane .xmm13 l) (fun _ => zetas k) ∧
+ ZOdd (s'.lane .xmm13 l) (s'.lane .xmm12 l)) ∧ YOnly [.xmm13, .xmm12] s s' := by
+ rw [yzeta1, wp_cons_iff]
+ refine WP.mono (ybcast_ok (by rw [h8, add_ofNat_zero]; exact hin)) fun s1 ⟨b1, o1⟩ => ?_
+ refine WP.mono (ylanes (by decide) (P := fun l t => t.xmm .xmm13 = shufDwords (s1.lane .xmm13 l) 0 ∧
+ t.xmm .xmm12 = shufDwords (shufDwords (s1.lane .xmm13 l) 0) 0xF5)
+ fun l _ => zsse1_ok (s1.proj l)) fun s2 ⟨l2, o2⟩ => ⟨fun l hl => ?_, (o1.trans o2).mono (by simp)⟩
+ have e13 : s2.lane .xmm13 l = _ := (l2 l hl).1
+ have e12 : s2.lane .xmm12 l = _ := (l2 l hl).2
+ rw [e12, e13, b1 l hl, h8, add_ofNat_zero]
+ refine ⟨fun i hi => ?_, zodd_F5 _⟩
+ rw [zlanes_tab 0 (fun j _ => by rw [sel_zero]; omega) ht i hi]
+ dsimp only; rw [sel_zero, Nat.add_zero]
+
+theorem zsseS_ok (o₀ o₁ : BitVec 8) (t : State) :
+ WP isa (.block [.xop (.pshufd .xmm2 .xmm13 o₁), .xop (.pshufd .xmm13 .xmm13 o₀)]) t fun t' =>
+ (t'.xmm .xmm13 = shufDwords (t.xmm .xmm13) o₀ ∧ t'.xmm .xmm2 = shufDwords (t.xmm .xmm13) o₁) ∧
+ XOnly [.xmm2, .xmm13] t t' := by
+ vrun
+ exact ⟨by first | trivial | simp, by xonly⟩
+
+theorem zsseF5_ok (t : State) :
+ WP isa (.block [.xop (.pshufd .xmm12 .xmm13 0xF5)]) t fun t' =>
+ t'.xmm .xmm12 = shufDwords (t.xmm .xmm13) 0xF5 ∧ XOnly [.xmm12] t t' := by
+ vrun
+ exact ⟨by first | trivial | simp, by xonly⟩
+
+/-- The odd zetas of each lane of `ymm13` in the even doublewords of `ymm12`. -/
+theorem yF5_ok (s : State) :
+ WP isa (.block (toY [.xop (.pshufd .xmm12 .xmm13 0xF5)])) s fun s' =>
+ (∀ l < 2, s'.lane .xmm12 l = shufDwords (s.lane .xmm13 l) 0xF5) ∧ YOnly [.xmm12] s s' :=
+ ylanes (by decide) (P := fun l t => t.xmm .xmm12 = shufDwords (s.lane .xmm13 l) 0xF5)
+ fun l _ => zsseF5_ok (s.proj l)
+
+theorem yzetaS_ok (o₀ o₁ : BitVec 8) {zP : Addr} {k : Nat} (hk0 : ∀ j < 4, k + sel o₀ j < 256)
+ (hk1 : ∀ j < 4, k + sel o₁ j < 256) {s : State} (h8 : s.gpr .r8 = coeffAddr zP k)
+ (hin : InRegions (s.rd ++ s.wr) (coeffAddr zP k) 16) (ht : Tab zmTab s.mem zP 256) :
+ WP isa (.block (yzetaS o₀ o₁)) s fun s' => ZLanes (s'.lane .xmm13 0) (fun i => zetas (k + sel o₀ i)) ∧
+ ZLanes (s'.lane .xmm13 1) (fun i => zetas (k + sel o₁ i)) ∧
+ (∀ l < 2, ZOdd (s'.lane .xmm13 l) (s'.lane .xmm12 l)) ∧ YOnly [.xmm13, .xmm2, .xmm12] s s' := by
+ rw [yzetaS, WP.block_append_iff, WP.block_append_iff, wp_cons_iff]
+ refine WP.mono (ybcast_ok (by rw [h8, add_ofNat_zero]; exact hin)) fun s1 ⟨b1, o1⟩ => ?_
+ refine WP.mono (ylanes (by rfl) (P := fun l t =>
+ t.xmm .xmm13 = shufDwords (s1.lane .xmm13 l) o₀ ∧ t.xmm .xmm2 = shufDwords (s1.lane .xmm13 l) o₁)
+ fun l _ => zsseS_ok o₀ o₁ (s1.proj l)) fun s2 ⟨l2, o2⟩ => ?_
+ refine WP.mono (yblend_ok s2) fun s3 ⟨e0, e1, o3⟩ => ?_
+ refine WP.mono (yF5_ok s3) fun s4 ⟨f4, o4⟩ => ?_
+ have x0 : s4.lane .xmm13 0 = shufDwords (s.mem.readW (coeffAddr zP k) 128) o₀ := by
+ have e : s2.lane .xmm13 0 = _ := (l2 0 (by decide)).1
+ rw [o4.lane _ (by decide) 0 (by decide), e0, e, b1 0 (by decide), h8, add_ofNat_zero]
+ have x1 : s4.lane .xmm13 1 = shufDwords (s.mem.readW (coeffAddr zP k) 128) o₁ := by
+ have e : s2.lane .xmm2 1 = _ := (l2 1 (by decide)).2
+ rw [o4.lane _ (by decide) 1 (by decide), e1, e, b1 1 (by decide), h8, add_ofNat_zero]
+ refine ⟨by rw [x0]; exact zlanes_tab o₀ hk0 ht, by rw [x1]; exact zlanes_tab o₁ hk1 ht,
+ fun l hl => ?_, (((o1.trans o2).trans o3).trans o4).mono (by simp)⟩
+ rw [f4 l hl, o4.lane _ (by decide) l hl]
+ exact zodd_F5 _
+
+/-! ## A layer with `len ≥ 8` -/
+
+section
+variable {bf : List Instr} {op : Zq → Zq → Zq → Zq × Zq} (hbf : VBflyOk bf op)
+ (hY : laneSseBlock (toY bf) = some bf)
+ {blk : Poly → Nat → Nat → Nat → Nat → Poly} (hblk : BlkOk blk op)
+include hbf hY
+
+/-- The butterflies of `bf` in each lane, from the coefficients `x` and `y`
+of the lanes of `ymm0` and `ymm1` and the zetas `ζ` of those of `ymm13`. -/
+theorem ybf_ok {s : State} (hc : YConsts s) {x y ζ : Nat → Nat → Zq}
+ (hx : ∀ l < 2, DLanes (s.lane .xmm0 l) (x l)) (hy : ∀ l < 2, DLanes (s.lane .xmm1 l) (y l))
+ (hz : ∀ l < 2, ZLanes (s.lane .xmm13 l) (ζ l)) (ho : ∀ l < 2, ZOdd (s.lane .xmm13 l) (s.lane .xmm12 l)) :
+ WP isa (.block (toY bf)) s fun s' =>
+ (∀ l < 2, DLanes (s'.lane .xmm0 l) (fun i => (op (x l i) (y l i) (ζ l i)).1) ∧
+ DLanes (s'.lane .xmm3 l) (fun i => (op (x l i) (y l i) (ζ l i)).2)) ∧
+ YOnly [.xmm1, .xmm2, .xmm4, .xmm0, .xmm3] s s' :=
+ ylanes hY (P := fun l t => DLanes (t.xmm .xmm0) (fun i => (op (x l i) (y l i) (ζ l i)).1) ∧
+ DLanes (t.xmm .xmm3) (fun i => (op (x l i) (y l i) (ζ l i)).2))
+ fun l hl => WP.mono (hbf _ (hc l hl) _ _ _ (hx l hl) (hy l hl) (hz l hl) (ho l hl))
+ fun _ ⟨a, b, c⟩ => ⟨⟨a, b⟩, c⟩
+
+include hblk
+
+/-- The body of the loop over the vectors of a block. -/
+abbrev ybody (bf : List Instr) (len : Nat) : List Instr :=
+ [.vmovdquLoad .l256 .xmm0 (at_ .rdx 0), .vmovdquLoad .l256 .xmm1 (at_ .rdx (4 * len))] ++ toY bf ++
+ [.vmovdquStore .l256 (at_ .rdx 0) .xmm0, .vmovdquStore .l256 (at_ .rdx (4 * len)) .xmm3,
+ .alu .add .rdx (.imm 32)] ++ [.alu .sub .rcx (.imm 1)]
+
+theorem ystep {fP : Addr} {len st u k : Nat} (hl : 8 ≤ len) (hs : st + 2 * len ≤ 256) (hu : 8 * u + 8 ≤ len)
+ {G : Poly} {s : State} (hc : YConsts s) (hz : ∀ l < 2, ZLanes (s.lane .xmm13 l) (fun _ => zetas k))
+ (ho : ∀ l < 2, ZOdd (s.lane .xmm13 l) (s.lane .xmm12 l))
+ (hdx : s.gpr .rdx = coeffAddr fP (st + 8 * u)) (hS : PolyIs s.mem fP (blk G len k st (8 * u)))
+ (hw : pR fP ∈ s.wr) :
+ WP isa (.block (ybody bf len)) s fun s' =>
+ PolyIs s'.mem fP (blk G len k st (8 * (u + 1))) ∧ s'.gpr .rdx = coeffAddr fP (st + 8 * (u + 1)) ∧
+ Frame [pR fP] s.mem s'.mem ∧ YConsts s' ∧ (∀ l < 2, s'.lane .xmm13 l = s.lane .xmm13 l) ∧
+ (∀ l < 2, s'.lane .xmm12 l = s.lane .xmm12 l) ∧ Keep [.rdx, .rcx] s s' ∧
+ s'.gpr .rcx = s.gpr .rcx - 1 ∧ s'.zf = some (s.gpr .rcx - 1 == 0) ∧ s'.mxcsr = s.mxcsr := by
+ have j0 : st + 8 * u + 8 ≤ 256 := by omega
+ have j1 : st + 8 * u + len + 8 ≤ 256 := by omega
+ have a1 : coeffAddr fP (st + 8 * u) + BitVec.ofNat 64 (4 * len) = coeffAddr fP (st + 8 * u + len) :=
+ coeffAddr_add _ _ _
+ have r0 : InRegions (s.rd ++ s.wr) (coeffAddr fP (st + 8 * u) + BitVec.ofNat 64 0) 32 := by
+ rw [add_ofNat_zero]; exact f_in32 (List.mem_append_right _ hw) j0
+ have r1 : InRegions (s.rd ++ s.wr) (coeffAddr fP (st + 8 * u) + BitVec.ofNat 64 (4 * len)) 32 := by
+ rw [a1]; exact f_in32 (List.mem_append_right _ hw) j1
+ rw [ybody, List.append_assoc, List.append_assoc, WP.block_append_iff,
+ show ∀ a b : Instr, [a, b] = [a] ++ [b] from fun _ _ => rfl, WP.block_append_iff]
+ refine WP.mono (yld_ok (by rw [hdx]; exact r0)) fun s1 ⟨L1, o1⟩ => ?_
+ refine WP.mono (yld_ok (by rw [o1.rd, o1.wr, o1.gpr, hdx]; exact r1)) fun s2 ⟨L2, o2⟩ => ?_
+ rw [WP.block_append_iff]
+ have o12 := o1.trans o2
+ generalize hP : blk G len k st (8 * u) = P at hS
+ refine WP.mono (ybf_ok hbf hY (yonly_yconsts o12 hc (by decide) (by decide))
+ (x := fun l e => P[st + 8 * u + 4 * l + e]!) (y := fun l e => P[st + 8 * u + len + 4 * l + e]!)
+ (ζ := fun _ _ => zetas k)
+ (fun l hl => by
+ rw [o2.lane _ (by decide) l hl, L1 l hl, hdx, add_ofNat_zero]; exact dlanes_loadY hS j0 hl)
+ (fun l hl => by
+ rw [L2 l hl, o1.gpr, o1.mem, hdx, a1]; exact dlanes_loadY hS j1 hl)
+ (fun l hl => by rw [o12.lane _ (by decide) l hl]; exact hz l hl)
+ (fun l hl => by rw [o12.lane _ (by decide) l hl, o12.lane _ (by decide) l hl]; exact ho l hl))
+ fun s3 ⟨B3, o3⟩ => ?_
+ have o13 := o12.trans o3
+ have w0 : InRegions s3.wr (s3.gpr .rdx) 32 := by
+ rw [o13.wr, o13.gpr, hdx]; exact f_in32 hw j0
+ have w1 : InRegions s3.wr (s3.gpr .rdx + BitVec.ofNat 64 (4 * len)) 32 := by
+ rw [o13.wr, o13.gpr, hdx, a1]; exact f_in32 hw j1
+ vrund [State.store256_eq, State.setMem_gpr, State.setMem_wr, State.setMem_mem, State.setMem_rd, State.setMem_ymm,
+ State.setMem_setMem, w0, w1, sx32]
+ have g3 : s3.gpr .rdx = coeffAddr fP (st + 8 * u) := by rw [o13.gpr, hdx]
+ rw [g3, a1, o13.mem]
+ refine ⟨?_, ?_, ?_, ?_, ?_, ?_, ⟨fun r hr => ?_, ?_, ?_⟩, ?_, ?_, ?_⟩
+ · have hR : ∀ i < 256, (blk G len k st (8 * (u + 1)))[i]! = if st + 8 * u ≤ i ∧ i < st + 8 * u + 8 then
+ (op P[i]! P[i + len]! (zetas k)).1 else if st + 8 * u + len ≤ i ∧ i < st + 8 * u + len + 8 then
+ (op P[i - len]! P[i]! (zetas k)).2 else P[i]! := fun i hi => by
+ rw [← hP, show 8 * (u + 1) = 8 * u + 8 by omega, hblk.add, hblk.get _ _ _ _ _ (by omega) (by omega)
+ (by rw [n_eq]; omega) _ (by rw [n_eq]; exact hi)]
+ refine polyIs_write2L (s := s3) hS j0 j1 (by omega) (fun l hl e he => ?_) (fun l hl e he => ?_)
+ (fun i hi h1 h2 => by rw [hR i hi, ite_eq_right (by omega), ite_eq_right (by omega)])
+ · rw [(B3 l hl).1 e he]; dsimp only; rw [hR _ (by omega), ite_eq_left (by omega),
+ show st + 8 * u + len + 4 * l + e = st + 8 * u + 4 * l + e + len by omega]
+ · rw [(B3 l hl).2 e he]; dsimp only; rw [hR _ (by omega), ite_eq_right (by omega), ite_eq_left (by omega),
+ show st + 8 * u + len + 4 * l + e - len = st + 8 * u + 4 * l + e by omega]
+ · rw [show (32 : BitVec 64) = BitVec.ofNat 64 (4 * 8) from rfl, coeffAddr_add,
+ show st + 8 * u + 8 = st + 8 * (u + 1) by omega]
+ · exact frame_write2Y (Frame.refl _ _) j0 j1 _ _
+ · exact ylanes_gpr (s := s3) (fun r l => by simp only [lane_setReg, lane_setFlags, State.setMem_lane]) o13 hc
+ (by decide) (by decide)
+ · intro l hl; simp only [lane_setReg, lane_setFlags, State.setMem_lane]; exact o13.lane _ (by decide) l hl
+ · intro l hl; simp only [lane_setReg, lane_setFlags, State.setMem_lane]; exact o13.lane _ (by decide) l hl
+ · simp only [List.mem_cons, List.not_mem_nil, or_false, not_or] at hr
+ simp only [RegUpd.gpr_setReg, RegUpd.gpr_setFlags, hr.1, hr.2, ite_false, State.setMem_gpr]
+ rw [o13.gpr]
+ · simp only [RegUpd.rd_setReg, RegUpd.rd_setFlags, State.setMem_rd]; rw [o13.rd]
+ · simp only [RegUpd.wr_setReg, RegUpd.wr_setFlags, State.setMem_wr]; rw [o13.wr]
+ · rw [o13.gpr]
+ · rw [o13.gpr]
+ · exact o13.mxcsr
+
+/-- The code of a block of a layer with `len ≥ 8`. -/
+abbrev yblk (bf : List Instr) (len : Nat) (dz : BitVec 32) : Prog isa :=
+ .seq (.block (yzeta1 ++ [.alu .add .r8 (.imm dz)]))
+ (.seq (rcxLoop (len / 8) ([.vmovdquLoad .l256 .xmm0 (at_ .rdx 0),
+ .vmovdquLoad .l256 .xmm1 (at_ .rdx (4 * len))] ++ toY bf ++
+ [.vmovdquStore .l256 (at_ .rdx 0) .xmm0, .vmovdquStore .l256 (at_ .rdx (4 * len)) .xmm3,
+ .alu .add .rdx (.imm 32)]))
+ (.block [.alu .add .rdx (.imm (BitVec.ofNat 32 (4 * len))), .alu .sub .rax (.imm 1)]))
+
+theorem yblock_ok {fP sP : Addr} {len st kz : Nat} (h8 : 8 ≤ len) (hl8 : len % 8 = 0) (hl : len ≤ 128)
+ (hs : st + 2 * len ≤ 256) (hkz : kz + 4 ≤ 256) (dz : BitVec 32) {G : Poly} {s : State} (hc : YConsts s)
+ (hdx : s.gpr .rdx = coeffAddr fP st) (h8r : s.gpr .r8 = coeffAddr sP kz) (hS : PolyIs s.mem fP G)
+ (hT : Tab zmTab s.mem sP 256) (hwf : pR fP ∈ s.wr) (hw : pR sP ∈ s.wr) :
+ WP isa (yblk bf len dz) s fun s' => PolyIs s'.mem fP (blk G len kz st len) ∧
+ s'.gpr .rdx = coeffAddr fP (st + 2 * len) ∧ s'.gpr .r8 = s.gpr .r8 + BitVec.signExtend 64 dz ∧
+ s'.gpr .rax = s.gpr .rax - 1 ∧ s'.zf = some (s.gpr .rax - 1 == 0) ∧ BInvY fP s s' := by
+ -- the zeta
+ refine WP.seq ?_
+ rw [WP.block_append_iff]
+ refine WP.mono (yzeta1_ok hkz h8r (tab_in (List.mem_append_right _ hw) hkz) hT) fun s1 ⟨z1, o1⟩ => ?_
+ have g1 : s1.gpr = s.gpr := o1.gpr
+ refine WP.mono (addR_ok .r8 dz s1) fun s2 ⟨h82, o2, y2⟩ => ?_
+ have l2 := o2.lane y2
+ have c2 : YConsts s2 := ylanes_gpr (s := s1) l2 o1 hc (by decide) (by decide)
+ have dx2 : s2.gpr .rdx = coeffAddr fP st := by rw [o2.keep.gpr (by decide), g1, hdx]
+ have hw2 : pR fP ∈ s2.wr := by rw [o2.keep.2.2, o1.wr]; exact hwf
+ have m2 : s2.mem = s.mem := by rw [o2.mem, o1.mem]
+ refine WP.seq (WP.mono (wp_rcxLoopY (N := len / 8) (by omega) (by omega)
+ (fun u w => PolyIs w.mem fP (blk G len kz st (8 * u)) ∧ w.gpr .rdx = coeffAddr fP (st + 8 * u) ∧
+ YConsts w ∧ (∀ l < 2, w.lane .xmm13 l = s2.lane .xmm13 l) ∧ (∀ l < 2, w.lane .xmm12 l = s2.lane .xmm12 l) ∧
+ Keep [.rcx, .rdx] s2 w ∧ Frame [pR fP] s2.mem w.mem ∧ w.mxcsr = s2.mxcsr)
+ (fun w o hy _ => ⟨by rw [hblk.zero, o.mem, m2]; exact hS, by rw [o.keep.gpr (by decide), dx2]; rfl,
+ ylanes_gpr (s := s2) (o.lane hy) (YOnly.refl [] s2) c2 (by decide) (by decide),
+ fun l _ => o.lane hy _ l, fun l _ => o.lane hy _ l, o.keep.mono (by simp),
+ by rw [o.mem]; exact Frame.refl _ _, o.mxcsr⟩)
+ (fun u hu w ⟨hS', hdx', hc', hz', hzo', hk', hf', hx'⟩ => WP.mono (ystep hbf hY hblk h8 hs (by
+ have := Nat.div_mul_cancel (Nat.dvd_of_mod_eq_zero hl8); omega) hc'
+ (fun l hl => by rw [hz' l hl, l2]; exact (z1 l hl).1)
+ (fun l hl => by rw [hz' l hl, hzo' l hl, l2, l2]; exact (z1 l hl).2) hdx' hS'
+ (by rw [hk'.2.2]; exact hw2))
+ fun w' ⟨hS'', hdx'', hf'', hc'', hz'', hzo'', hk'', hcx, hzf, hx''⟩ =>
+ ⟨⟨hS'', hdx'', hc'', fun l hl => by rw [hz'' l hl, hz' l hl], fun l hl => by rw [hzo'' l hl, hzo' l hl],
+ (hk'.trans hk'').mono (by simp), hf'.trans hf'', by rw [hx'', hx']⟩, hcx, hzf⟩))
+ fun w ⟨hS3, hdx3, hc3, _, _, hk3, hf3, hx3⟩ => ?_)
+ rw [show 8 * (len / 8) = len from Nat.mul_div_cancel' (Nat.dvd_of_mod_eq_zero hl8)] at hS3 hdx3
+ have hax : w.gpr .rax = s.gpr .rax := by rw [hk3.gpr (by decide), o2.keep.gpr (by decide), g1]
+ have h8w : w.gpr .r8 = s.gpr .r8 + BitVec.signExtend 64 dz := by rw [hk3.gpr (by decide), h82, g1]
+ vrund [hdx3, sx_ofNat (show 4 * len < 2 ^ 31 by omega), hax, h8w]
+ refine ⟨hS3, by rw [coeffAddr_add, show st + len + len = st + 2 * len by omega], ?_⟩
+ have k1 : Keep [.r8, .rcx, .rdx, .rax] s w :=
+ (Keep.trans (⟨fun r _ => by rw [g1], o1.rd, o1.wr⟩ : Keep [] s s1) (o2.keep.trans hk3)).mono (by simp)
+ refine ⟨⟨fun r hr => ?_, k1.2.1, k1.2.2⟩, by rw [← m2]; exact hf3,
+ ylanes_gpr (s := w) (fun r l => by simp only [lane_setReg, lane_setFlags]) (YOnly.refl [] w) hc3
+ (by decide) (by decide),
+ by simp only [RegUpd.mxcsr_setReg, RegUpd.mxcsr_setFlags]; rw [hx3, o2.mxcsr, o1.mxcsr]⟩
+ simp only [List.mem_cons, List.not_mem_nil, or_false, not_or] at hr
+ simp only [RegUpd.gpr_setReg, RegUpd.gpr_setFlags, hr, ite_false]
+ exact k1.gpr (by simp [hr])
+
+theorem ylay_ok {fP sP : Addr} {len k : Nat} (hlen : len ∈ [8, 16, 32, 64, 128]) (dz : BitVec 32)
+ (zi : Nat → Nat) (hz0 : zi 0 = k) (hzi : ∀ c < 128 / len, zi c + 4 ≤ 256)
+ (hstep : ∀ c < 128 / len, coeffAddr sP (zi c) + BitVec.signExtend 64 dz = coeffAddr sP (zi (c + 1)))
+ {F : Poly} {s : State} (hc : YConsts s) (hdi : s.gpr .rdi = fP) (hsi : s.gpr .rsi = sP)
+ (hS : PolyIs s.mem fP F) (hT : Tab zmTab s.mem sP 256) (hwf : pR fP ∈ s.wr) (hw : pR sP ∈ s.wr)
+ (hd : (pR sP).Disjoint (pR fP)) :
+ WP isa (ylay bf len k dz) s fun s' => PolyIs s'.mem fP (layF blk F len zi (128 / len)) ∧
+ BInvY fP s s' := by
+ have hl : 8 ≤ len ∧ len % 8 = 0 ∧ len ≤ 128 ∧ 2 * len * (128 / len) = 256 ∧ 0 < 128 / len ∧
+ 128 / len ≤ 16 := by
+ simp only [List.mem_cons, List.not_mem_nil, or_false] at hlen
+ rcases hlen with rfl | rfl | rfl | rfl | rfl <;> decide
+ obtain ⟨h8, hl8, hl128, hcov, hpos, h16⟩ := hl
+ have hk : k + 4 ≤ 256 := hz0 ▸ hzi 0 hpos
+ refine WP.seq (WP.mono (Q := fun (w : State) => w.gpr .rdx = fP ∧ w.gpr .r8 = coeffAddr sP k ∧
+ w.gpr .rax = BitVec.ofNat 64 (128 / len) ∧ GOnly [.rdx, .r8, .rax] s w ∧ w.ymmHi = s.ymmHi)
+ (by
+ simp only [leaR]
+ vrund [sx_ofNat (show 4 * k < 2 ^ 31 by omega), hsi, hdi, RegUpd.ymmHi_setReg]
+ refine ⟨?_, by gonlyd, rfl⟩
+ apply BitVec.eq_of_toNat_eq
+ rw [BitVec.toNat_setWidth, BitVec.toNat_ofNat, BitVec.toNat_ofNat]
+ omega) fun w ⟨hdx, h8r, hax, o, hy⟩ => ?_)
+ have hwf' : pR fP ∈ w.wr := by rw [o.keep.2.2]; exact hwf
+ have hw' : pR sP ∈ w.wr := by rw [o.keep.2.2]; exact hw
+ have cw : YConsts w := ylanes_gpr (s := s) (o.lane hy) (YOnly.refl [] s) hc (by decide) (by decide)
+ refine WP.mono (wp_countdown (cnt := .rax) (N := 128 / len) (by omega) hpos
+ (fun c u => PolyIs u.mem fP (layF blk F len zi c) ∧ u.gpr .rdx = coeffAddr fP (2 * len * c) ∧
+ u.gpr .r8 = coeffAddr sP (zi c) ∧ BInvY fP w u ∧ Tab zmTab u.mem sP 256)
+ (fun c hc u ⟨hS', hdx', h8', hb', hT'⟩ _ => ?_) (fun u h => h)
+ ⟨by rw [o.mem]; exact hS, by rw [hdx, Nat.mul_zero, coeffAddr, Nat.mul_zero, add_ofNat_zero],
+ by rw [h8r, hz0], ⟨Keep.refl _ _, Frame.refl _ _, cw, rfl⟩, by rw [o.mem]; exact hT⟩ hax)
+ fun u ⟨hS', _, _, hb', _⟩ => ⟨hS', ⟨(o.keep.trans hb'.keep).mono (by simp),
+ by rw [← o.mem]; exact hb'.frame, hb'.consts, by rw [hb'.mxcsr, o.mxcsr]⟩⟩
+ have hs : 2 * len * c + 2 * len ≤ 256 := by
+ have : 2 * len * (c + 1) ≤ 2 * len * (128 / len) := Nat.mul_le_mul_left _ (by omega)
+ rw [Nat.mul_succ] at this; omega
+ refine WP.mono (yblock_ok hbf hY hblk h8 hl8 hl128 hs (hzi c hc) dz hb'.consts hdx' h8' hS' hT'
+ (by rw [hb'.keep.2.2]; exact hwf') (by rw [hb'.keep.2.2]; exact hw'))
+ fun u' ⟨hS'', hdx'', h8'', hax'', hzf'', hb''⟩ =>
+ ⟨⟨by rw [layF, foldl_range_succ]; exact hS'', by rw [hdx'', Nat.mul_succ],
+ by rw [h8'', h8', hstep c hc], hb'.trans hb'',
+ hT'.frame hb''.frame (fun r hr => by rw [List.mem_singleton.mp hr]; exact hd) (by decide)⟩, hax'', hzf''⟩
+
+/-! ## The layer with `len = 4` -/
+
+/-- The body of the layer with `len = 4`. -/
+abbrev ybody4 (bf : List Instr) (o₀ o₁ : BitVec 8) (dz : BitVec 32) : List Instr :=
+ [.vmovdquLoad .l256 .xmm4 (at_ .rdx 0)] ++ ([.vmovdquLoad .l256 .xmm5 (at_ .rdx 32)] ++ (yzetaS o₀ o₁ ++
+ ([.alu .add .r8 (.imm dz)] ++ ([.vop (.vperm2i128 .xmm0 .xmm4 .xmm5 0x20)] ++
+ ([.vop (.vperm2i128 .xmm1 .xmm4 .xmm5 0x31)] ++ (toY bf ++ ([.vop (.vperm2i128 .xmm4 .xmm0 .xmm3 0x20)] ++
+ ([.vop (.vperm2i128 .xmm5 .xmm0 .xmm3 0x31)] ++
+ [.vmovdquStore .l256 (at_ .rdx 0) .xmm4, .vmovdquStore .l256 (at_ .rdx 32) .xmm5, .alu .add .rdx (.imm 64),
+ .alu .sub .rcx (.imm 1)]))))))))
+
+theorem ystep4 {fP sP : Addr} {m kb : Nat} (hm : m < 16) (o₀ o₁ : BitVec 8) (dz : BitVec 32) (zi : Nat → Nat)
+ (hk : kb + 4 ≤ 256) (hsel : ∀ e < 4, kb + sel o₀ e = zi (2 * m) ∧ kb + sel o₁ e = zi (2 * m + 1))
+ {F : Poly} {s : State} (hc : YConsts s) (hdx : s.gpr .rdx = coeffAddr fP (16 * m))
+ (h8 : s.gpr .r8 = coeffAddr sP kb) (hS : PolyIs s.mem fP (layF blk F 4 zi (2 * m)))
+ (hT : Tab zmTab s.mem sP 256) (hwf : pR fP ∈ s.wr) (hw : pR sP ∈ s.wr) :
+ WP isa (.block (ybody4 bf o₀ o₁ dz)) s fun s' =>
+ PolyIs s'.mem fP (layF blk F 4 zi (2 * (m + 1))) ∧ s'.gpr .rdx = coeffAddr fP (16 * (m + 1)) ∧
+ s'.gpr .r8 = s.gpr .r8 + BitVec.signExtend 64 dz ∧ s'.gpr .rcx = s.gpr .rcx - 1 ∧
+ s'.zf = some (s.gpr .rcx - 1 == 0) ∧ BInvY fP s s' := by
+ have j0 : 16 * m + 8 ≤ 256 := by omega
+ have j1 : 16 * m + 8 + 8 ≤ 256 := by omega
+ have a1 : coeffAddr fP (16 * m) + BitVec.ofNat 64 32 = coeffAddr fP (16 * m + 8) := coeffAddr_add _ _ 8
+ have r0 : InRegions (s.rd ++ s.wr) (s.gpr .rdx + BitVec.ofNat 64 0) 32 := by
+ rw [hdx, add_ofNat_zero]; exact f_in32 (List.mem_append_right s.rd hwf) j0
+ have r1 : InRegions (s.rd ++ s.wr) (s.gpr .rdx + BitVec.ofNat 64 32) 32 := by
+ rw [hdx, a1]; exact f_in32 (List.mem_append_right s.rd hwf) j1
+ generalize hP : layF blk F 4 zi (2 * m) = P at hS
+ -- the loads
+ rw [ybody4, WP.block_append_iff]
+ refine WP.mono (yld_ok r0) fun s1 ⟨L4, o1⟩ => ?_
+ rw [WP.block_append_iff]
+ refine WP.mono (yld_ok (by rw [o1.rd, o1.wr, o1.gpr]; exact r1)) fun s2 ⟨L5, o2⟩ => ?_
+ have o12 := o1.trans o2
+ -- the zetas
+ rw [WP.block_append_iff]
+ have hk0 : ∀ j < 4, kb + sel o₀ j < 256 := fun j _ => by have := sel_lt o₀ j; omega
+ have hk1 : ∀ j < 4, kb + sel o₁ j < 256 := fun j _ => by have := sel_lt o₁ j; omega
+ refine WP.mono (yzetaS_ok o₀ o₁ (zP := sP) (k := kb) hk0 hk1 (by rw [o12.gpr, h8])
+ (by rw [o12.rd, o12.wr]; exact tab_in (List.mem_append_right _ hw) hk) (by rw [o12.mem]; exact hT))
+ fun s3 ⟨Z0, Z1, ZO, o3⟩ => ?_
+ rw [WP.block_append_iff]
+ refine WP.mono (addR_ok .r8 dz s3) fun s4 ⟨h84, g4, y4⟩ => ?_
+ have l4 := g4.lane y4
+ -- the lower and upper halves
+ rw [WP.block_append_iff]
+ refine WP.mono (yperm_ok s4) fun s5 ⟨P5, o5⟩ => ?_
+ rw [WP.block_append_iff]
+ refine WP.mono (yperm_ok s5) fun s6 ⟨P6, o6⟩ => ?_
+ have c6 : YConsts s6 := yonly_yconsts (o5.trans o6)
+ (ylanes_gpr (s := s3) l4 (o12.trans o3) hc (by decide) (by decide)) (by decide) (by decide)
+ have m3 : s3.mem = s.mem := (o12.trans o3).mem
+ have q4 : ∀ l < 2, s4.lane .xmm4 l = s.mem.readW (coeffAddr fP (16 * m) + BitVec.ofNat 64 (16 * l)) 128 :=
+ fun l hl => by rw [l4, o3.lane _ (by decide) l hl, o2.lane _ (by decide) l hl, L4 l hl, hdx, add_ofNat_zero]
+ have q5 : ∀ l < 2, s4.lane .xmm5 l =
+ s.mem.readW (coeffAddr fP (16 * m + 8) + BitVec.ofNat 64 (16 * l)) 128 :=
+ fun l hl => by rw [l4, o3.lane _ (by decide) l hl, L5 l hl, o1.gpr, o1.mem, hdx, a1]
+ rw [WP.block_append_iff]
+ refine WP.mono (ybf_ok hbf hY c6 (x := fun l e => P[16 * m + 8 * l + e]!)
+ (y := fun l e => P[16 * m + 8 * l + 4 + e]!) (ζ := fun l _ => zetas (zi (2 * m + l)))
+ (fun l hl => by
+ rw [o6.lane _ (by decide) l hl, P5 l hl, perm20 _ _ hl]
+ rcases lane01 hl with rfl | rfl
+ · rw [ifp rfl, q4 0 (by decide)]
+ exact (dlanes_loadY hS j0 (by decide)).congr fun e _ => getP_congr P (by omega)
+ · rw [ifn (by decide), q5 0 (by decide)]
+ exact (dlanes_loadY hS j1 (by decide)).congr fun e _ => getP_congr P (by omega))
+ (fun l hl => by
+ rw [P6 l hl, perm31 _ _ hl, o5.lane .xmm4 (by decide) 1 (by decide), o5.lane .xmm5 (by decide) 1 (by decide)]
+ rcases lane01 hl with rfl | rfl
+ · rw [ifp rfl, q4 1 (by decide)]
+ exact (dlanes_loadY hS j0 (by decide)).congr fun e _ => getP_congr P (by omega)
+ · rw [ifn (by decide), q5 1 (by decide)]
+ exact (dlanes_loadY hS j1 (by decide)).congr fun e _ => getP_congr P (by omega))
+ (fun l hl => by
+ rw [(o5.trans o6).lane _ (by decide) l hl, l4]
+ rcases lane01 hl with rfl | rfl
+ · exact Z0.congr fun i hi => congrArg zetas (hsel i hi).1
+ · exact Z1.congr fun i hi => congrArg zetas (hsel i hi).2)
+ (fun l hl => by
+ rw [(o5.trans o6).lane _ (by decide) l hl, (o5.trans o6).lane _ (by decide) l hl, l4, l4]
+ exact ZO l hl))
+ fun s7 ⟨B7, o7⟩ => ?_
+ -- the blocks back
+ rw [WP.block_append_iff]
+ refine WP.mono (yperm_ok s7) fun s8 ⟨P8, o8⟩ => ?_
+ rw [WP.block_append_iff]
+ refine WP.mono (yperm_ok s8) fun s9 ⟨P9, o9⟩ => ?_
+ have o59 := (o5.trans o6).trans (o7.trans (o8.trans o9))
+ have w0 : InRegions s9.wr (s9.gpr .rdx) 32 := by
+ rw [o59.wr, o59.gpr, g4.keep.2.2, g4.keep.gpr (by decide), o3.wr, o3.gpr, o12.wr, o12.gpr, hdx]
+ exact f_in32 hwf j0
+ have w1 : InRegions s9.wr (s9.gpr .rdx + BitVec.ofNat 64 32) 32 := by
+ rw [o59.wr, o59.gpr, g4.keep.2.2, g4.keep.gpr (by decide), o3.wr, o3.gpr, o12.wr, o12.gpr, hdx, a1]
+ exact f_in32 hwf j1
+ vrund [State.store256_eq, State.setMem_gpr, State.setMem_wr, State.setMem_mem, State.setMem_rd, State.setMem_ymm,
+ State.setMem_setMem, w0, w1, sx_ofNat (show 64 < 2 ^ 31 by decide)]
+ have g9 : s9.gpr = s4.gpr := o59.gpr
+ have m9 : s9.mem = s.mem := by rw [o59.mem, g4.mem, m3]
+ have dx9 : s9.gpr .rdx = coeffAddr fP (16 * m) := by
+ rw [g9, g4.keep.gpr (by decide), o3.gpr, o12.gpr, hdx]
+ rw [dx9, a1, m9]
+ have hR : ∀ i < 256, (layF blk F 4 zi (2 * (m + 1)))[i]! = if 16 * m ≤ i ∧ i < 16 * m + 16 then
+ (if i % (2 * 4) < 4 then (op P[i]! P[i + 4]! (zetas (zi (i / (2 * 4))))).1
+ else (op P[i - 4]! P[i]! (zetas (zi (i / (2 * 4))))).2) else P[i]! := fun i hi => by
+ have hF : ∀ j, 16 * m ≤ j → j < 256 → P[j]! = F[j]! := fun j h1 h2 => by
+ rw [← hP, layF_get hblk F (by decide) zi (by omega) h2, ite_eq_right (by omega)]
+ rw [layF_get hblk F (by decide) zi (by omega) hi]
+ by_cases h1 : 16 * m ≤ i ∧ i < 16 * m + 16
+ · rw [ite_eq_left (by omega), ite_eq_left h1]
+ by_cases h2 : i % (2 * 4) < 4
+ · rw [ite_eq_left h2, ite_eq_left h2, hF _ h1.1 hi, hF _ (by omega) (by omega)]
+ · rw [ite_eq_right h2, ite_eq_right h2, hF _ (by omega) (by omega), hF _ h1.1 hi]
+ · rw [ite_eq_right h1, ← hP, layF_get hblk F (by decide) zi (by omega) hi]
+ by_cases h3 : i < 16 * m
+ · rw [ite_eq_left (show i < 2 * 4 * (2 * (m + 1)) by omega),
+ ite_eq_left (show i < 2 * 4 * (2 * m) by omega)]
+ · rw [ite_eq_right (show ¬ i < 2 * 4 * (2 * (m + 1)) by omega),
+ ite_eq_right (show ¬ i < 2 * 4 * (2 * m) by omega)]
+ refine ⟨?_, ?_, ?_, ?_, ?_, ⟨⟨fun r hr => ?_, ?_, ?_⟩, ?_, ?_, ?_⟩⟩
+ · refine polyIs_write2L (s := s9) hS j0 j1 (by omega) (fun l hl => ?_) (fun l hl => ?_)
+ (fun i hi h1 h2 => by rw [hR i hi, ite_eq_right (by omega)])
+ · rw [o9.lane .xmm4 (by decide) l hl, P8 l hl, perm20 _ _ hl]
+ rcases lane01 hl with rfl | rfl
+ · rw [ifp rfl]
+ exact (B7 0 (by decide)).1.congr fun e he => by
+ rw [hR _ (by omega), ite_eq_left (by omega), ite_eq_left (by omega)]
+ exact congrArg Prod.fst (op_idx op P zi (by omega) (by omega) (by omega))
+ · rw [ifn (by decide)]
+ exact (B7 0 (by decide)).2.congr fun e he => by
+ rw [hR _ (by omega), ite_eq_left (by omega), ite_eq_right (by omega)]
+ exact congrArg Prod.snd (op_idx op P zi (by omega) (by omega) (by omega))
+ · rw [P9 l hl, perm31 _ _ hl, o8.lane .xmm0 (by decide) 1 (by decide),
+ o8.lane .xmm3 (by decide) 1 (by decide)]
+ rcases lane01 hl with rfl | rfl
+ · rw [ifp rfl]
+ exact (B7 1 (by decide)).1.congr fun e he => by
+ rw [hR _ (by omega), ite_eq_left (by omega), ite_eq_left (by omega)]
+ exact congrArg Prod.fst (op_idx op P zi (by omega) (by omega) (by omega))
+ · rw [ifn (by decide)]
+ exact (B7 1 (by decide)).2.congr fun e he => by
+ rw [hR _ (by omega), ite_eq_left (by omega), ite_eq_right (by omega)]
+ exact congrArg Prod.snd (op_idx op P zi (by omega) (by omega) (by omega))
+ · rw [show BitVec.signExtend 64 (64 : BitVec 32) = BitVec.ofNat 64 (4 * 16) by decide, coeffAddr_add,
+ Nat.mul_succ]
+ · rw [g9, h84, o3.gpr, o12.gpr]
+ · rw [g9, g4.keep.gpr (by decide), o3.gpr, o12.gpr]
+ · rw [g9, g4.keep.gpr (by decide), o3.gpr, o12.gpr]
+ · simp only [List.mem_cons, List.not_mem_nil, or_false, not_or] at hr
+ simp only [RegUpd.gpr_setReg, RegUpd.gpr_setFlags, hr, ite_false, State.setMem_gpr]
+ rw [g9, g4.keep.gpr (by simp [hr]), o3.gpr, o12.gpr]
+ · simp only [RegUpd.rd_setReg, RegUpd.rd_setFlags, State.setMem_rd]
+ rw [o59.rd, g4.keep.2.1, o3.rd, o12.rd]
+ · simp only [RegUpd.wr_setReg, RegUpd.wr_setFlags, State.setMem_wr]
+ rw [o59.wr, g4.keep.2.2, o3.wr, o12.wr]
+ · exact frame_write2Y (Frame.refl _ _) j0 j1 _ _
+ · exact ylanes_gpr (s := s9) (fun r l => by simp only [lane_setReg, lane_setFlags, State.setMem_lane])
+ o59 (ylanes_gpr (s := s3) l4 (o12.trans o3) hc (by decide) (by decide)) (by decide) (by decide)
+ · exact o59.mxcsr.trans (g4.mxcsr.trans (o12.trans o3).mxcsr)
+
+theorem ylay4_ok {fP sP : Addr} (k : Nat) (o₀ o₁ : BitVec 8) (dz : BitVec 32) (zi kb : Nat → Nat)
+ (hkb0 : kb 0 = k) (hk : ∀ m < 16, kb m + 4 ≤ 256)
+ (hsel : ∀ m < 16, ∀ e < 4, kb m + sel o₀ e = zi (2 * m) ∧ kb m + sel o₁ e = zi (2 * m + 1))
+ (hstep : ∀ m < 16, coeffAddr sP (kb m) + BitVec.signExtend 64 dz = coeffAddr sP (kb (m + 1)))
+ {F : Poly} {s : State} (hc : YConsts s) (hdi : s.gpr .rdi = fP) (hsi : s.gpr .rsi = sP)
+ (hS : PolyIs s.mem fP F) (hT : Tab zmTab s.mem sP 256) (hwf : pR fP ∈ s.wr) (hw : pR sP ∈ s.wr)
+ (hd : (pR sP).Disjoint (pR fP)) :
+ WP isa (ylay4 bf k o₀ o₁ dz) s fun s' => PolyIs s'.mem fP (layF blk F 4 zi 32) ∧ BInvY fP s s' := by
+ have hk0 : k + 4 ≤ 256 := by have := hk 0 (by decide); omega
+ refine WP.seq (WP.mono (ypre21 k hk0 hdi hsi) fun w ⟨hdx, h8, og, hy⟩ => ?_)
+ have cw : YConsts w := ylanes_gpr (s := s) (og.lane hy) (YOnly.refl [] s) hc (by decide) (by decide)
+ refine WP.mono (wp_rcxLoopY (N := 16) (by decide) (by decide)
+ (fun i u => PolyIs u.mem fP (layF blk F 4 zi (2 * i)) ∧ u.gpr .rdx = coeffAddr fP (16 * i) ∧
+ u.gpr .r8 = coeffAddr sP (kb i) ∧ BInvY fP w u)
+ (fun u ou hu _ => ⟨by rw [ou.mem, og.mem]; exact hS,
+ by rw [ou.keep.gpr (by decide), hdx, Nat.mul_zero, coeffAddr, Nat.mul_zero, add_ofNat_zero],
+ by rw [ou.keep.gpr (by decide), h8, hkb0], ⟨ou.keep.mono (by simp), by rw [ou.mem]; exact Frame.refl _ _,
+ ylanes_gpr (s := w) (ou.lane hu) (YOnly.refl [] w) cw (by decide) (by decide), ou.mxcsr⟩⟩)
+ (fun i hi u ⟨hS', hdx', h8', hb'⟩ => ?_)) fun u ⟨hS', _, _, hb'⟩ =>
+ ⟨hS', ⟨(og.keep.trans hb'.keep).mono (by simp), by rw [← og.mem]; exact hb'.frame, hb'.consts,
+ by rw [hb'.mxcsr, og.mxcsr]⟩⟩
+ have hT' : Tab zmTab u.mem sP 256 := (by rw [og.mem]; exact hT : Tab zmTab w.mem sP 256).frame hb'.frame
+ (fun r hr => by rw [List.mem_singleton.mp hr]; exact hd) (by decide)
+ have hwf' : pR fP ∈ u.wr := by rw [hb'.keep.2.2, og.keep.2.2]; exact hwf
+ have hw' : pR sP ∈ u.wr := by rw [hb'.keep.2.2, og.keep.2.2]; exact hw
+ rw [show [Instr.vmovdquLoad .l256 .xmm4 (at_ .rdx 0), .vmovdquLoad .l256 .xmm5 (at_ .rdx 32)] ++ yzetaS o₀ o₁ ++
+ [.alu .add .r8 (.imm dz), .vop (.vperm2i128 .xmm0 .xmm4 .xmm5 0x20),
+ .vop (.vperm2i128 .xmm1 .xmm4 .xmm5 0x31)] ++ toY bf ++
+ [.vop (.vperm2i128 .xmm4 .xmm0 .xmm3 0x20), .vop (.vperm2i128 .xmm5 .xmm0 .xmm3 0x31),
+ .vmovdquStore .l256 (at_ .rdx 0) .xmm4, .vmovdquStore .l256 (at_ .rdx 32) .xmm5,
+ .alu .add .rdx (.imm 64)] ++ [.alu .sub .rcx (.imm 1)] = ybody4 bf o₀ o₁ dz by
+ simp [List.append_assoc]]
+ exact WP.mono (ystep4 hbf hY hblk hi o₀ o₁ dz zi (hk i hi) (hsel i hi) hb'.consts hdx' h8' hS' hT' hwf' hw')
+ fun u' ⟨hS'', hdx'', h8'', hcx, hzf, hb''⟩ => ⟨⟨hS'', hdx'', by rw [h8'', h8', hstep i hi],
+ hb'.trans hb''⟩, hcx, hzf⟩
+
+end
+
+end VG.Proof.MlDsa.X86_64.Arith
diff --git a/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YLay21.lean b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YLay21.lean
new file mode 100644
index 000000000..f8bf6a6bd
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YLay21.lean
@@ -0,0 +1,526 @@
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.YLay
+
+/-!
+# ML-DSA on x86-64: the layers of the NTT and its inverse with `len` = 2 and 1 on AVX2 registers
+
+Untrusted: everything here is checked by Lean. Each iteration of these
+layers loads sixteen coefficients, from `j`, into `ymm0` and `ymm1` (or
+`ymm2`), and in each lane `l` runs `vlay2`'s or `vlay1`'s gathering,
+butterflies and interleaving back (`Ntt.lean`) on the four coefficients
+from `j + 4l` and the four from `j + 8 + 4l` (`core2_ok`, `core1_ok`), with
+the zetas of their blocks in lane `l` of `ymm13` (`yzetaS_ok`, `yzeta8_ok`,
+`yzeta8R_ok`); `ystep21` is an iteration for any such code, and `ylay2_ok`
+and `ylay1_ok` the layers.
+-/
+
+namespace VG.Proof.MlDsa.X86_64.Arith
+
+open VG VG.X86_64 VG.Impl.MlDsa.X86_64.Arith
+open VG.Proof.MlDsa.Arith
+open VG.Proof.MlKem.X86_64 (Keep XOnly XKeep YOnly ylanes yld_ok ifp ifn sel sel_lt add_ofNat_zero GOnly
+ addR_ok wp_rcxLoopY wp_cons_iff lane_setReg lane_setFlags State.setMem_ymm State.setMem_setMem q256lo q256hi
+ lo4 hi4)
+open VG.Impl.MlKem.X86_64 (xb xmov toY rcxLoop)
+open VG.Spec.MlDsa (q n Poly Zq coeffAt polyAt PolyIs zetas)
+
+/-! ## An iteration -/
+
+/-- The body of the loop of the layers with `len` = 2 and 1. -/
+abbrev ybody21 (r2 : XReg) (zl core : List Instr) (dz : BitVec 32) : List Instr :=
+ [.vmovdquLoad .l256 .xmm0 (at_ .rdx 0)] ++ ([.vmovdquLoad .l256 r2 (at_ .rdx 32)] ++ (zl ++
+ ([.alu .add .r8 (.imm dz)] ++ (toY core ++
+ [.vmovdquStore .l256 (at_ .rdx 0) .xmm0, .vmovdquStore .l256 (at_ .rdx 32) .xmm1, .alu .add .rdx (.imm 64),
+ .alu .sub .rcx (.imm 1)]))))
+
+/-- An iteration of a layer with `len` = 2 or 1: the sixteen coefficients of
+`G` from `j`, in lane `l` the four from `j + 4l` and the four from
+`j + 8 + 4l`, become those of `R`, with the zetas `ζ l` that `zl` leaves in
+the lanes of `ymm13`. -/
+theorem ystep21 {core zl : List Instr} {r2 : XReg} {zs : List XReg} {dz : BitVec 32}
+ (hY : laneSseBlock (toY core) = some core) (h0 : XReg.xmm0 ∉ zs) (h2 : r2 ∉ zs)
+ (h14 : XReg.xmm14 ∉ [XReg.xmm0] ++ [r2] ++ zs) (h15 : XReg.xmm15 ∉ [XReg.xmm0] ++ [r2] ++ zs)
+ (h20 : XReg.xmm0 ∉ [r2]) {fP : Addr} {j : Nat} (hj : j + 16 ≤ 256) {G R : Poly}
+ {ζ : Nat → Nat → Zq} {s : State} (hc : YConsts s) (hdx : s.gpr .rdx = coeffAddr fP j)
+ (hS : PolyIs s.mem fP G) (hw : pR fP ∈ s.wr)
+ (hz : ∀ s', XKeep s s' →
+ WP isa (.block zl) s' fun s'' => (∀ l < 2, ZLanes (s''.lane .xmm13 l) (ζ l) ∧
+ ZOdd (s''.lane .xmm13 l) (s''.lane .xmm12 l)) ∧ YOnly zs s' s'')
+ (hcore : ∀ l < 2, ∀ t : State, VConsts t → DLanes (t.xmm .xmm0) (fun e => G[j + 4 * l + e]!) →
+ DLanes (t.xmm r2) (fun e => G[j + 8 + 4 * l + e]!) → ZLanes (t.xmm .xmm13) (ζ l) →
+ ZOdd (t.xmm .xmm13) (t.xmm .xmm12) →
+ WP isa (.block core) t fun t' => (DLanes (t'.xmm .xmm0) (fun e => R[j + 4 * l + e]!) ∧
+ DLanes (t'.xmm .xmm1) (fun e => R[j + 8 + 4 * l + e]!)) ∧
+ XOnly [.xmm0, .xmm1, .xmm2, .xmm3, .xmm4] t t')
+ (hR : ∀ i < 256, i < j ∨ j + 16 ≤ i → R[i]! = G[i]!) :
+ WP isa (.block (ybody21 r2 zl core dz)) s fun s' =>
+ PolyIs s'.mem fP R ∧ s'.gpr .rdx = coeffAddr fP (j + 16) ∧
+ s'.gpr .r8 = s.gpr .r8 + BitVec.signExtend 64 dz ∧ s'.gpr .rcx = s.gpr .rcx - 1 ∧
+ s'.zf = some (s.gpr .rcx - 1 == 0) ∧ BInvY fP s s' := by
+ have j0 : j + 8 ≤ 256 := by omega
+ have j1 : j + 8 + 8 ≤ 256 := by omega
+ have a1 : coeffAddr fP j + BitVec.ofNat 64 32 = coeffAddr fP (j + 8) := coeffAddr_add _ _ 8
+ have r0 : InRegions (s.rd ++ s.wr) (s.gpr .rdx + BitVec.ofNat 64 0) 32 := by
+ rw [hdx, add_ofNat_zero]; exact f_in32 (List.mem_append_right s.rd hw) j0
+ have r1 : InRegions (s.rd ++ s.wr) (s.gpr .rdx + BitVec.ofNat 64 32) 32 := by
+ rw [hdx, a1]; exact f_in32 (List.mem_append_right s.rd hw) j1
+ rw [ybody21, WP.block_append_iff]
+ refine WP.mono (yld_ok r0) fun s1 ⟨L0, o1⟩ => ?_
+ rw [WP.block_append_iff]
+ refine WP.mono (yld_ok (d := r2) (by rw [o1.rd, o1.wr, o1.gpr]; exact r1)) fun s2 ⟨L2, o2⟩ => ?_
+ have o12 := o1.trans o2
+ rw [WP.block_append_iff]
+ refine WP.mono (hz s2 o12.toXKeep) fun s3 ⟨Z3, o3⟩ => ?_
+ rw [WP.block_append_iff]
+ refine WP.mono (addR_ok .r8 dz s3) fun s4 ⟨h84, g4, y4⟩ => ?_
+ have l4 := g4.lane y4
+ have c4 : YConsts s4 := ylanes_gpr (s := s3) l4 (o12.trans o3) hc h14 h15
+ rw [WP.block_append_iff]
+ refine WP.mono (ylanes hY (P := fun l t => DLanes (t.xmm .xmm0) (fun e => R[j + 4 * l + e]!) ∧
+ DLanes (t.xmm .xmm1) (fun e => R[j + 8 + 4 * l + e]!))
+ fun l hl => hcore l hl _ (c4 l hl)
+ (by rw [State.proj_xmm, l4, o3.lane _ h0 l hl, o2.lane _ h20 l hl, L0 l hl, hdx, add_ofNat_zero]
+ exact dlanes_loadY hS j0 hl)
+ (by rw [State.proj_xmm, l4, o3.lane _ h2 l hl, L2 l hl, o1.gpr, o1.mem, hdx, a1]
+ exact dlanes_loadY hS j1 hl)
+ (by rw [State.proj_xmm, l4]; exact (Z3 l hl).1)
+ (by rw [State.proj_xmm, State.proj_xmm, l4, l4]; exact (Z3 l hl).2)) fun s5 ⟨C5, o5⟩ => ?_
+ have m5 : s5.mem = s.mem := by rw [o5.mem, g4.mem, o3.mem, o12.mem]
+ have g5 : s5.gpr = s4.gpr := o5.gpr
+ have dx5 : s5.gpr .rdx = coeffAddr fP j := by rw [g5, g4.keep.gpr (by decide), o3.gpr, o12.gpr, hdx]
+ have k5 : s5.rd = s.rd ∧ s5.wr = s.wr := ⟨by rw [o5.rd, g4.keep.2.1, o3.rd, o12.rd],
+ by rw [o5.wr, g4.keep.2.2, o3.wr, o12.wr]⟩
+ have w0 : InRegions s5.wr (s5.gpr .rdx) 32 := by rw [k5.2, dx5]; exact f_in32 hw j0
+ have w1 : InRegions s5.wr (s5.gpr .rdx + BitVec.ofNat 64 32) 32 := by rw [k5.2, dx5, a1]; exact f_in32 hw j1
+ vrund [State.store256_eq, State.setMem_gpr, State.setMem_wr, State.setMem_mem, State.setMem_rd,
+ State.setMem_ymm, State.setMem_setMem, w0, w1, sx_ofNat (show 64 < 2 ^ 31 by decide)]
+ rw [dx5, a1, m5]
+ refine ⟨?_, ?_, ?_, ?_, ?_, ⟨⟨fun r hr => ?_, ?_, ?_⟩, ?_, ?_, ?_⟩⟩
+ · exact polyIs_write2L (s := s5) hS j0 j1 (by omega) (fun l hl => (C5 l hl).1)
+ (fun l hl => (C5 l hl).2) fun i hi _ _ => hR i hi (by omega)
+ · rw [show BitVec.signExtend 64 (64 : BitVec 32) = BitVec.ofNat 64 (4 * 16) by decide, coeffAddr_add]
+ · rw [g5, h84, o3.gpr, o12.gpr]
+ · rw [g5, g4.keep.gpr (by decide), o3.gpr, o12.gpr]
+ · rw [g5, g4.keep.gpr (by decide), o3.gpr, o12.gpr]
+ · simp only [List.mem_cons, List.not_mem_nil, or_false, not_or] at hr
+ simp only [RegUpd.gpr_setReg, RegUpd.gpr_setFlags, hr, ite_false, State.setMem_gpr]
+ rw [g5, g4.keep.gpr (by simp [hr]), o3.gpr, o12.gpr]
+ · simp only [RegUpd.rd_setReg, RegUpd.rd_setFlags, State.setMem_rd]; exact k5.1
+ · simp only [RegUpd.wr_setReg, RegUpd.wr_setFlags, State.setMem_wr]; exact k5.2
+ · exact frame_write2Y (Frame.refl _ _) j0 j1 _ _
+ · exact ylanes_gpr (s := s5) (fun r l => by simp only [lane_setReg, lane_setFlags, State.setMem_lane]) o5 c4
+ (by decide) (by decide)
+ · exact o5.mxcsr.trans (g4.mxcsr.trans (o12.trans o3).mxcsr)
+
+/-! ## The gatherings, the butterflies and the interleavings back of a lane -/
+
+theorem gath2_ok (t : State) :
+ WP isa (.block gath2) t fun t' => (t'.xmm .xmm0 = XBinOp.eval .punpcklqdq (t.xmm .xmm0) (t.xmm .xmm1) ∧
+ t'.xmm .xmm1 = XBinOp.eval .punpckhqdq (t.xmm .xmm0) (t.xmm .xmm1)) ∧ XOnly [.xmm2, .xmm0, .xmm1] t t' := by
+ simp only [gath2, xmov, xb]
+ vrun [eval_movdqa]
+ exact ⟨by first | trivial | simp, by xonly⟩
+
+theorem scat2_ok (t : State) :
+ WP isa (.block scat2) t fun t' => (t'.xmm .xmm0 = XBinOp.eval .punpcklqdq (t.xmm .xmm0) (t.xmm .xmm3) ∧
+ t'.xmm .xmm1 = XBinOp.eval .punpckhqdq (t.xmm .xmm0) (t.xmm .xmm3)) ∧ XOnly [.xmm1, .xmm0] t t' := by
+ simp only [scat2, xmov, xb]
+ vrun [eval_movdqa]
+ exact ⟨by first | trivial | simp, by xonly⟩
+
+theorem gath1_ok (t : State) :
+ WP isa (.block gath1) t fun t' =>
+ (t'.xmm .xmm0 = XBinOp.eval .punpcklqdq (shufDwords (t.xmm .xmm0) 0xD8) (shufDwords (t.xmm .xmm2) 0xD8) ∧
+ t'.xmm .xmm1 = XBinOp.eval .punpckhqdq (shufDwords (t.xmm .xmm0) 0xD8) (shufDwords (t.xmm .xmm2) 0xD8)) ∧
+ XOnly [.xmm0, .xmm2, .xmm1] t t' := by
+ simp only [gath1, xmov, xb]
+ vrun [eval_movdqa]
+ exact ⟨by first | trivial | simp, by xonly⟩
+
+theorem scat1_ok (t : State) :
+ WP isa (.block scat1) t fun t' => (t'.xmm .xmm0 = XBinOp.eval .punpckldq (t.xmm .xmm0) (t.xmm .xmm3) ∧
+ t'.xmm .xmm1 = XBinOp.eval .punpckhdq (t.xmm .xmm0) (t.xmm .xmm3)) ∧ XOnly [.xmm1, .xmm0] t t' := by
+ simp only [scat1, xmov, xb]
+ vrun [eval_movdqa]
+ exact ⟨by first | trivial | simp, by xonly⟩
+
+section
+variable {bf : List Instr} {op : Zq → Zq → Zq → Zq × Zq} (hbf : VBflyOk bf op)
+include hbf
+
+/-- `vlay2`'s work on the coefficients `A` of `xmm0` and `B` of `xmm1`: the
+blocks `A` and `B` of `len = 2`, with the zetas `ζ` (the first two for `A`,
+the last two for `B`). -/
+theorem core2_ok {t : State} (hc : VConsts t) {A B ζ : Nat → Zq} (hA : DLanes (t.xmm .xmm0) A)
+ (hB : DLanes (t.xmm .xmm1) B) (hz : ZLanes (t.xmm .xmm13) ζ) (ho : ZOdd (t.xmm .xmm13) (t.xmm .xmm12)) :
+ WP isa (.block (gath2 ++ bf ++ scat2)) t fun t' =>
+ (DLanes (t'.xmm .xmm0) (fun e => if e < 2 then (op (A e) (A (2 + e)) (ζ e)).1
+ else (op (A (e - 2)) (A e) (ζ (e - 2))).2) ∧
+ DLanes (t'.xmm .xmm1) (fun e => if e < 2 then (op (B e) (B (2 + e)) (ζ (2 + e))).1
+ else (op (B (e - 2)) (B e) (ζ e)).2)) ∧ XOnly [.xmm0, .xmm1, .xmm2, .xmm3, .xmm4] t t' := by
+ rw [List.append_assoc, WP.block_append_iff]
+ refine WP.mono (gath2_ok t) fun t1 ⟨⟨e0, e1⟩, o1⟩ => ?_
+ rw [WP.block_append_iff]
+ refine WP.mono (hbf _ (xonly_vconsts o1 hc (by decide) (by decide))
+ (fun e => if e < 2 then A e else B (e - 2)) (fun e => if e < 2 then A (2 + e) else B e) ζ
+ (fun e he => by
+ dsimp only; rw [e0, dword_punpcklqdq _ _ he]
+ by_cases h : e < 2 <;> simp only [h, ite_true, ite_false]
+ · exact hA e he
+ · exact hB (e - 2) (by omega))
+ (fun e he => by
+ dsimp only; rw [e1, dword_punpckhqdq _ _ he]
+ by_cases h : e < 2 <;> simp only [h, ite_true, ite_false]
+ · exact hA (2 + e) (by omega)
+ · exact hB e he)
+ (by rw [o1.xmm _ (by decide)]; exact hz) (by rw [o1.xmm _ (by decide), o1.xmm _ (by decide)]; exact ho))
+ fun t2 ⟨X, Y, o2⟩ => ?_
+ refine WP.mono (scat2_ok t2) fun t3 ⟨⟨f0, f1⟩, o3⟩ => ⟨⟨fun e he => ?_, fun e he => ?_⟩, ?_⟩
+ · rw [f0, dword_punpcklqdq _ _ he]
+ split
+ · rw [X e he]; dsimp only
+ rw [ite_eq_left_of_eq_true _ _ (eq_true ‹e < 2›), ite_eq_left_of_eq_true _ _ (eq_true ‹e < 2›),
+ ite_eq_left_of_eq_true _ _ (eq_true ‹e < 2›)]
+ · rw [Y (e - 2) (by omega)]; dsimp only
+ rw [ite_eq_left_of_eq_true _ _ (eq_true (show e - 2 < 2 by omega)),
+ ite_eq_left_of_eq_true _ _ (eq_true (show e - 2 < 2 by omega)),
+ ite_eq_right_of_eq_false _ _ (eq_false ‹¬ e < 2›), show 2 + (e - 2) = e by omega]
+ · rw [f1, dword_punpckhqdq _ _ he]
+ split
+ · rw [X (2 + e) (by omega)]; dsimp only
+ rw [ite_eq_right_of_eq_false _ _ (eq_false (show ¬ 2 + e < 2 by omega)),
+ ite_eq_right_of_eq_false _ _ (eq_false (show ¬ 2 + e < 2 by omega)),
+ ite_eq_left_of_eq_true _ _ (eq_true ‹e < 2›), show 2 + e - 2 = e by omega]
+ · rw [Y e he]; dsimp only
+ rw [ite_eq_right_of_eq_false _ _ (eq_false ‹¬ e < 2›), ite_eq_right_of_eq_false _ _ (eq_false ‹¬ e < 2›),
+ ite_eq_right_of_eq_false _ _ (eq_false ‹¬ e < 2›)]
+ · exact ((o1.trans o2).trans o3).mono (by simp)
+
+/-- `vlay1`'s work on the coefficients `A` of `xmm0` and `B` of `xmm2`: the
+blocks `A₀₁`, `A₂₃`, `B₀₁` and `B₂₃` of `len = 1`, with the zetas `ζ`. -/
+theorem core1_ok {t : State} (hc : VConsts t) {A B ζ : Nat → Zq} (hA : DLanes (t.xmm .xmm0) A)
+ (hB : DLanes (t.xmm .xmm2) B) (hz : ZLanes (t.xmm .xmm13) ζ) (ho : ZOdd (t.xmm .xmm13) (t.xmm .xmm12)) :
+ WP isa (.block (gath1 ++ bf ++ scat1)) t fun t' =>
+ (DLanes (t'.xmm .xmm0) (fun e => if e % 2 = 0 then (op (A e) (A (e + 1)) (ζ (e / 2))).1
+ else (op (A (e - 1)) (A e) (ζ (e / 2))).2) ∧
+ DLanes (t'.xmm .xmm1) (fun e => if e % 2 = 0 then (op (B e) (B (e + 1)) (ζ (2 + e / 2))).1
+ else (op (B (e - 1)) (B e) (ζ (2 + e / 2))).2)) ∧ XOnly [.xmm0, .xmm1, .xmm2, .xmm3, .xmm4] t t' := by
+ rw [List.append_assoc, WP.block_append_iff]
+ refine WP.mono (gath1_ok t) fun t1 ⟨⟨e0, e1⟩, o1⟩ => ?_
+ rw [WP.block_append_iff]
+ refine WP.mono (hbf _ (xonly_vconsts o1 hc (by decide) (by decide))
+ (fun e => if e < 2 then A (2 * e) else B (2 * (e - 2))) (fun e => if e < 2 then A (2 * e + 1) else B (2 * (e - 2) + 1))
+ ζ
+ (fun e he => by
+ dsimp only; rw [e0, dword_punpcklqdq _ _ he]
+ by_cases h : e < 2 <;> simp only [h, ite_true, ite_false]
+ · rw [dword_d8 _ he, ite_eq_left h]; exact hA _ (by omega)
+ · rw [dword_d8 _ (by omega), ite_eq_left (by omega)]; exact hB _ (by omega))
+ (fun e he => by
+ dsimp only; rw [e1, dword_punpckhqdq _ _ he]
+ by_cases h : e < 2 <;> simp only [h, ite_true, ite_false]
+ · rw [dword_d8 _ (by omega), ite_eq_right (by omega), show 2 * (2 + e - 2) + 1 = 2 * e + 1 by omega]
+ exact hA _ (by omega)
+ · rw [dword_d8 _ he, ite_eq_right h]; exact hB _ (by omega))
+ (by rw [o1.xmm _ (by decide)]; exact hz) (by rw [o1.xmm _ (by decide), o1.xmm _ (by decide)]; exact ho))
+ fun t2 ⟨X, Y, o2⟩ => ?_
+ refine WP.mono (scat1_ok t2) fun t3 ⟨⟨f0, f1⟩, o3⟩ => ⟨⟨fun e he => ?_, fun e he => ?_⟩, ?_⟩
+ · rw [f0, dword_punpckldq' _ _ he]
+ split
+ · rw [X (e / 2) (by omega)]; dsimp only
+ rw [ite_eq_left (by omega), ite_eq_left (by omega), ite_eq_left ‹e % 2 = 0›,
+ show 2 * (e / 2) = e by omega]
+ · rw [Y (e / 2) (by omega)]; dsimp only
+ rw [ite_eq_left (by omega), ite_eq_left (by omega), ite_eq_right ‹¬ e % 2 = 0›,
+ show 2 * (e / 2) = e - 1 by omega, show e - 1 + 1 = e by omega]
+ · rw [f1, dword_punpckhdq' _ _ he]
+ split
+ · rw [X (2 + e / 2) (by omega)]; dsimp only
+ rw [ite_eq_right (by omega), ite_eq_right (by omega), ite_eq_left ‹e % 2 = 0›,
+ show 2 * (2 + e / 2 - 2) = e by omega]
+ · rw [Y (2 + e / 2) (by omega)]; dsimp only
+ rw [ite_eq_right (by omega), ite_eq_right (by omega), ite_eq_right ‹¬ e % 2 = 0›,
+ show 2 * (2 + e / 2 - 2) = e - 1 by omega, show e - 1 + 1 = e by omega]
+ · exact ((o1.trans o2).trans o3).mono (by simp)
+
+end
+
+/-! ## The zetas of the layer with `len = 1` -/
+
+/-- A doubleword of four of the zetas, at index `i` of the table. -/
+theorem dword_tab {m : Mem} {zP : Addr} (ht : Tab zmTab m zP 256) {j e i : Nat} (he : e < 4) (hi : j + e = i)
+ (hi' : i < 256) : (dword (m.readW (coeffAddr zP j) 128) e).toNat = (zetas i).val * 2 ^ 32 % q := by
+ subst hi; rw [dword_readW _ _ he, coeffAddr_add]; exact tab_zeta ht hi'
+
+/-- `vpermq` with `0x27`: lane 0 is `punpckhqdq` of the upper and the lower lane, lane 1 their `punpcklqdq`. -/
+theorem perm27 (a b : BitVec 128) :
+ permQwords (b ++ a) 0x27 = qword256 (b ++ a) 0 ++ qword256 (b ++ a) (2 + 0) ++
+ qword256 (b ++ a) 1 ++ qword256 (b ++ a) (2 + 1) := rfl
+
+theorem perm27_lo (a b : BitVec 128) :
+ (permQwords (b ++ a) 0x27).extractLsb' 0 128 = XBinOp.eval .punpckhqdq b a := by
+ rw [perm27, q256hi, q256hi, q256lo _ _ (by decide), q256lo _ _ (by decide), lo4]; rfl
+
+theorem perm27_hi (a b : BitVec 128) :
+ (permQwords (b ++ a) 0x27).extractLsb' 128 128 = XBinOp.eval .punpcklqdq b a := by
+ rw [perm27, q256hi, q256hi, q256lo _ _ (by decide), q256lo _ _ (by decide), hi4]; rfl
+
+/-- `vpermq d, r, 0x27`. -/
+theorem ypermq27_ok {d r : XReg} (s : State) :
+ WP isa (.block [.vop (.vpermq d r 0x27)]) s fun s' =>
+ s'.lane d 0 = XBinOp.eval .punpckhqdq (s.lane r 1) (s.lane r 0) ∧
+ s'.lane d 1 = XBinOp.eval .punpcklqdq (s.lane r 1) (s.lane r 0) ∧ YOnly [d] s s' := by
+ apply WP.of_runBlock
+ simp only [runBlock_cons, runStep_some, runBlock_nil, exec, VOp.exec, Option.some.injEq, exists_eq_left']
+ refine ⟨?_, ?_, ⟨⟨rfl, rfl, rfl, rfl, rfl⟩, fun r' hr l hl => ?_⟩⟩
+ · rw [State.lane_setV256, ifp rfl, ifp rfl, State.ymm_eq, perm27_lo]
+ · rw [State.lane_setV256, ifp rfl, ifn (by decide), State.ymm_eq, perm27_hi]
+ · rw [State.lane_setV256, ifn (by simpa using hr)]
+
+/-- The eight zetas at index `k` of the table, in the order of the blocks of
+`ylay1` for `NTT`: in lane `l`, zetas `k + 2l`, `k + 2l + 1`, `k + 2l + 4`
+and `k + 2l + 5`. -/
+theorem yzeta8_ok {zP : Addr} {k : Nat} (hk : k + 8 ≤ 256) {s : State} (h8 : s.gpr .r8 = coeffAddr zP k)
+ (hin : InRegions (s.rd ++ s.wr) (coeffAddr zP k) 32) (ht : Tab zmTab s.mem zP 256) :
+ WP isa (.block yzeta8) s fun s' =>
+ (∀ l < 2, ZLanes (s'.lane .xmm13 l) (fun e => zetas (k + (2 * l + e + 2 * (e / 2)))) ∧
+ ZOdd (s'.lane .xmm13 l) (s'.lane .xmm12 l)) ∧ YOnly [.xmm13, .xmm12] s s' := by
+ rw [yzeta8, WP.block_append_iff, wp_cons_iff]
+ refine WP.mono (yld_ok (by rw [h8, add_ofNat_zero]; exact hin)) fun s1 ⟨L1, o1⟩ => ?_
+ refine WP.mono (VG.Proof.MlKem.X86_64.ypermq_ok s1) fun s2 ⟨e0, e1, o2⟩ => ?_
+ refine WP.mono (yF5_ok s2) fun s3 ⟨f3, o3⟩ => ⟨fun l hl => ?_, ((o1.trans o2).trans o3).mono (by simp)⟩
+ rw [f3 l hl, o3.lane _ (by decide) l hl]
+ refine ⟨fun e he => ?_, zodd_F5 _⟩
+ have a : ∀ l < 2, s1.lane .xmm13 l = s.mem.readW (coeffAddr zP (k + 4 * l)) 128 := fun l hl => by
+ rw [L1 l hl, h8, add_ofNat_zero, lane_load]
+ rcases lane01 hl with rfl | rfl
+ · rw [e0, dword_punpcklqdq _ _ he, a 0 (by decide), a 1 (by decide)]
+ split
+ · exact dword_tab ht he (by omega) (by omega)
+ · exact dword_tab ht (by omega) (by omega) (by omega)
+ · rw [e1, dword_punpckhqdq _ _ he, a 0 (by decide), a 1 (by decide)]
+ split
+ · exact dword_tab ht (by omega) (by omega) (by omega)
+ · exact dword_tab ht he (by omega) (by omega)
+
+theorem dword_b1 (x : BitVec 128) {e : Nat} (he : e < 4) :
+ dword (shufDwords x 0xB1) e = dword x (if e % 2 = 0 then e + 1 else e - 1) := by
+ rw [dword_shufDwords _ _ he]
+ rcases cases4 he with rfl | rfl | rfl | rfl <;> rfl
+
+theorem zsseR_ok (t : State) :
+ WP isa (.block [.xop (.pshufd .xmm13 .xmm13 0xB1), .xop (.pshufd .xmm12 .xmm13 0xF5)]) t fun t' =>
+ (t'.xmm .xmm13 = shufDwords (t.xmm .xmm13) 0xB1 ∧
+ t'.xmm .xmm12 = shufDwords (shufDwords (t.xmm .xmm13) 0xB1) 0xF5) ∧ XOnly [.xmm13, .xmm12] t t' := by
+ vrun
+ exact ⟨by first | trivial | simp, by xonly⟩
+
+/-- The eight zetas at index `k` of the table, in the order of the blocks of
+`ylay1` for `NTT⁻¹`, which take them in decreasing order: in lane `l`, zetas
+`k + 7 - 2l`, `k + 6 - 2l`, `k + 3 - 2l` and `k + 2 - 2l`. -/
+theorem yzeta8R_ok {zP : Addr} {k : Nat} (hk : k + 8 ≤ 256) {s : State} (h8 : s.gpr .r8 = coeffAddr zP k)
+ (hin : InRegions (s.rd ++ s.wr) (coeffAddr zP k) 32) (ht : Tab zmTab s.mem zP 256) :
+ WP isa (.block yzeta8R) s fun s' =>
+ (∀ l < 2, ZLanes (s'.lane .xmm13 l) (fun e => zetas (k + 7 - (2 * l + e + 2 * (e / 2)))) ∧
+ ZOdd (s'.lane .xmm13 l) (s'.lane .xmm12 l)) ∧ YOnly [.xmm13, .xmm12] s s' := by
+ rw [yzeta8R, WP.block_append_iff, wp_cons_iff]
+ refine WP.mono (yld_ok (by rw [h8, add_ofNat_zero]; exact hin)) fun s1 ⟨L1, o1⟩ => ?_
+ refine WP.mono (ypermq27_ok s1) fun s2 ⟨e0, e1, o2⟩ => ?_
+ refine WP.mono (ylanes (by decide) (P := fun l t => t.xmm .xmm13 = shufDwords (s2.lane .xmm13 l) 0xB1 ∧
+ t.xmm .xmm12 = shufDwords (shufDwords (s2.lane .xmm13 l) 0xB1) 0xF5)
+ fun l _ => zsseR_ok (s2.proj l)) fun s3 ⟨l3, o3⟩ => ⟨fun l hl => ?_, ((o1.trans o2).trans o3).mono (by simp)⟩
+ have e13 : s3.lane .xmm13 l = _ := (l3 l hl).1
+ have e12 : s3.lane .xmm12 l = _ := (l3 l hl).2
+ rw [e12, e13]
+ refine ⟨fun e he => ?_, zodd_F5 _⟩
+ have a : ∀ l < 2, s1.lane .xmm13 l = s.mem.readW (coeffAddr zP (k + 4 * l)) 128 := fun l hl => by
+ rw [L1 l hl, h8, add_ofNat_zero, lane_load]
+ have he' : (if e % 2 = 0 then e + 1 else e - 1) < 4 := by split <;> omega
+ rw [dword_b1 _ he]
+ generalize hf : (if e % 2 = 0 then e + 1 else e - 1) = f at he'
+ have hf' : f = if e % 2 = 0 then e + 1 else e - 1 := hf.symm
+ rcases lane01 hl with rfl | rfl
+ · rw [e0, dword_punpckhqdq _ _ he', a 0 (by decide), a 1 (by decide)]
+ split
+ · exact dword_tab ht (by omega) (by split at hf' <;> omega) (by omega)
+ · exact dword_tab ht he' (by split at hf' <;> omega) (by omega)
+ · rw [e1, dword_punpcklqdq _ _ he', a 0 (by decide), a 1 (by decide)]
+ split
+ · exact dword_tab ht he' (by split at hf' <;> omega) (by omega)
+ · exact dword_tab ht (by omega) (by split at hf' <;> omega) (by omega)
+
+/-! ## The layers -/
+
+section
+variable {op : Zq → Zq → Zq → Zq × Zq} {blk : Poly → Nat → Nat → Nat → Nat → Poly} (hblk : BlkOk blk op)
+include hblk
+
+/-- The sixteen coefficients from `16i` after the next blocks of the layer
+with `len = 2`. -/
+theorem layF2_next (F : Poly) (zi : Nat → Nat) {i : Nat} (hi : i < 16) {x : Nat} (hx : x < 256) :
+ (layF blk F 2 zi (4 * (i + 1)))[x]! = if 16 * i ≤ x ∧ x < 16 * i + 16 then
+ (if x % (2 * 2) < 2 then
+ (op (layF blk F 2 zi (4 * i))[x]! (layF blk F 2 zi (4 * i))[x + 2]! (zetas (zi (x / (2 * 2))))).1
+ else (op (layF blk F 2 zi (4 * i))[x - 2]! (layF blk F 2 zi (4 * i))[x]! (zetas (zi (x / (2 * 2))))).2)
+ else (layF blk F 2 zi (4 * i))[x]! := by
+ have hF : ∀ y, 16 * i ≤ y → y < 256 → (layF blk F 2 zi (4 * i))[y]! = F[y]! := fun y h1 h2 => by
+ rw [layF_get hblk F (by decide) zi (by omega) h2, ite_eq_right (by omega)]
+ rw [layF_get hblk F (by decide) zi (by omega) hx]
+ by_cases h1 : 16 * i ≤ x ∧ x < 16 * i + 16
+ · rw [ite_eq_left (by omega), ite_eq_left h1]
+ by_cases h2 : x % (2 * 2) < 2
+ · rw [ite_eq_left h2, ite_eq_left h2, hF _ h1.1 hx, hF _ (by omega) (by omega)]
+ · rw [ite_eq_right h2, ite_eq_right h2, hF _ (by omega) (by omega), hF _ h1.1 hx]
+ · rw [ite_eq_right h1, layF_get hblk F (by decide) zi (by omega) hx]
+ by_cases h3 : x < 16 * i
+ · rw [ite_eq_left (show x < 2 * 2 * (4 * (i + 1)) by omega), ite_eq_left (show x < 2 * 2 * (4 * i) by omega)]
+ · rw [ite_eq_right (show ¬ x < 2 * 2 * (4 * (i + 1)) by omega),
+ ite_eq_right (show ¬ x < 2 * 2 * (4 * i) by omega)]
+
+/-- The sixteen coefficients from `16i` after the next blocks of the layer
+with `len = 1`. -/
+theorem layF1_next (F : Poly) (zi : Nat → Nat) {i : Nat} (hi : i < 16) {x : Nat} (hx : x < 256) :
+ (layF blk F 1 zi (8 * (i + 1)))[x]! = if 16 * i ≤ x ∧ x < 16 * i + 16 then
+ (if x % (2 * 1) < 1 then
+ (op (layF blk F 1 zi (8 * i))[x]! (layF blk F 1 zi (8 * i))[x + 1]! (zetas (zi (x / (2 * 1))))).1
+ else (op (layF blk F 1 zi (8 * i))[x - 1]! (layF blk F 1 zi (8 * i))[x]! (zetas (zi (x / (2 * 1))))).2)
+ else (layF blk F 1 zi (8 * i))[x]! := by
+ have hF : ∀ y, 16 * i ≤ y → y < 256 → (layF blk F 1 zi (8 * i))[y]! = F[y]! := fun y h1 h2 => by
+ rw [layF_get hblk F (by decide) zi (by omega) h2, ite_eq_right (by omega)]
+ rw [layF_get hblk F (by decide) zi (by omega) hx]
+ by_cases h1 : 16 * i ≤ x ∧ x < 16 * i + 16
+ · rw [ite_eq_left (by omega), ite_eq_left h1]
+ by_cases h2 : x % (2 * 1) < 1
+ · rw [ite_eq_left h2, ite_eq_left h2, hF _ h1.1 hx, hF _ (by omega) (by omega)]
+ · rw [ite_eq_right h2, ite_eq_right h2, hF _ (by omega) (by omega), hF _ h1.1 hx]
+ · rw [ite_eq_right h1, layF_get hblk F (by decide) zi (by omega) hx]
+ by_cases h3 : x < 16 * i
+ · rw [ite_eq_left (show x < 2 * 1 * (8 * (i + 1)) by omega), ite_eq_left (show x < 2 * 1 * (8 * i) by omega)]
+ · rw [ite_eq_right (show ¬ x < 2 * 1 * (8 * (i + 1)) by omega),
+ ite_eq_right (show ¬ x < 2 * 1 * (8 * i) by omega)]
+
+variable {bf : List Instr} (hbf : VBflyOk bf op)
+include hbf
+
+theorem ylay2_ok (hY : laneSseBlock (toY (gath2 ++ bf ++ scat2)) = some (gath2 ++ bf ++ scat2)) {fP sP : Addr}
+ (k : Nat) (o₀ o₁ : BitVec 8) (dz : BitVec 32) (zi kb : Nat → Nat) (hkb0 : kb 0 = k)
+ (hk : ∀ i < 16, kb i + 4 ≤ 256)
+ (hsel : ∀ i < 16, ∀ e < 4, kb i + sel o₀ e = zi (4 * i + 2 * (e / 2)) ∧
+ kb i + sel o₁ e = zi (4 * i + 1 + 2 * (e / 2)))
+ (hstep : ∀ i < 16, coeffAddr sP (kb i) + BitVec.signExtend 64 dz = coeffAddr sP (kb (i + 1)))
+ {F : Poly} {s : State} (hc : YConsts s) (hdi : s.gpr .rdi = fP) (hsi : s.gpr .rsi = sP)
+ (hS : PolyIs s.mem fP F) (hT : Tab zmTab s.mem sP 256) (hwf : pR fP ∈ s.wr) (hw : pR sP ∈ s.wr)
+ (hd : (pR sP).Disjoint (pR fP)) :
+ WP isa (ylay2 bf k o₀ o₁ dz) s fun s' => PolyIs s'.mem fP (layF blk F 2 zi 64) ∧ BInvY fP s s' := by
+ have hk0 : k + 4 ≤ 256 := by have := hk 0 (by decide); omega
+ refine WP.seq (WP.mono (ypre21 k hk0 hdi hsi) fun w ⟨hdx, h8, og, hy⟩ => ?_)
+ have cw : YConsts w := ylanes_gpr (s := s) (og.lane hy) (YOnly.refl [] s) hc (by decide) (by decide)
+ refine WP.mono (wp_rcxLoopY (N := 16) (by decide) (by decide)
+ (fun i u => PolyIs u.mem fP (layF blk F 2 zi (4 * i)) ∧ u.gpr .rdx = coeffAddr fP (16 * i) ∧
+ u.gpr .r8 = coeffAddr sP (kb i) ∧ BInvY fP w u)
+ (fun u ou hu _ => ⟨by rw [ou.mem, og.mem]; exact hS,
+ by rw [ou.keep.gpr (by decide), hdx, Nat.mul_zero, coeffAddr, Nat.mul_zero, add_ofNat_zero],
+ by rw [ou.keep.gpr (by decide), h8, hkb0], ⟨ou.keep.mono (by simp), by rw [ou.mem]; exact Frame.refl _ _,
+ ylanes_gpr (s := w) (ou.lane hu) (YOnly.refl [] w) cw (by decide) (by decide), ou.mxcsr⟩⟩)
+ (fun i hi u ⟨hS', hdx', h8', hb'⟩ => ?_)) fun u ⟨hS', _, _, hb'⟩ =>
+ ⟨hS', ⟨(og.keep.trans hb'.keep).mono (by simp), by rw [← og.mem]; exact hb'.frame, hb'.consts,
+ by rw [hb'.mxcsr, og.mxcsr]⟩⟩
+ have hT' : Tab zmTab u.mem sP 256 := (by rw [og.mem]; exact hT : Tab zmTab w.mem sP 256).frame hb'.frame
+ (fun r hr => by rw [List.mem_singleton.mp hr]; exact hd) (by decide)
+ have hwf' : pR fP ∈ u.wr := by rw [hb'.keep.2.2, og.keep.2.2]; exact hwf
+ have hw' : pR sP ∈ u.wr := by rw [hb'.keep.2.2, og.keep.2.2]; exact hw
+ have hk0' : ∀ j < 4, kb i + sel o₀ j < 256 := fun j _ => by have := sel_lt o₀ j; have := hk i hi; omega
+ have hk1' : ∀ j < 4, kb i + sel o₁ j < 256 := fun j _ => by have := sel_lt o₁ j; have := hk i hi; omega
+ rw [show [Instr.vmovdquLoad .l256 .xmm0 (at_ .rdx 0), .vmovdquLoad .l256 .xmm1 (at_ .rdx 32)] ++ yzetaS o₀ o₁ ++
+ [.alu .add .r8 (.imm dz)] ++ toY (gath2 ++ bf ++ scat2) ++
+ [.vmovdquStore .l256 (at_ .rdx 0) .xmm0, .vmovdquStore .l256 (at_ .rdx 32) .xmm1,
+ .alu .add .rdx (.imm 64)] ++ [.alu .sub .rcx (.imm 1)] =
+ ybody21 .xmm1 (yzetaS o₀ o₁) (gath2 ++ bf ++ scat2) dz by simp [List.append_assoc]]
+ have hR := fun x hx => layF2_next hblk F zi hi (x := x) hx
+ refine WP.mono (ystep21 hY (zs := [.xmm13, .xmm2, .xmm12]) (by decide) (by decide) (by decide) (by decide)
+ (by decide) (j := 16 * i) (by omega) (R := layF blk F 2 zi (4 * (i + 1)))
+ (ζ := fun l e => zetas (zi (4 * i + l + 2 * (e / 2)))) hb'.consts hdx' hS' hwf' (fun s' k' => ?_)
+ (fun l hl t ht hA hB hz ho => ?_) (fun x hx h => by rw [hR x hx, ite_eq_right (by omega)]))
+ fun u' ⟨hS'', hdx'', h8'', hcx, hzf, hb''⟩ => ⟨⟨hS'', by rw [hdx'', Nat.mul_succ],
+ by rw [h8'', h8', hstep i hi], hb'.trans hb''⟩, hcx, hzf⟩
+ · -- the zetas
+ refine WP.mono (yzetaS_ok o₀ o₁ (zP := sP) (k := kb i) hk0' hk1' (by rw [k'.gpr, h8'])
+ (by rw [k'.rd, k'.wr]; exact tab_in (List.mem_append_right _ hw') (hk i hi)) (by rw [k'.mem]; exact hT'))
+ fun s'' ⟨Z0, Z1, ZO, o⟩ => ⟨fun l hl => ⟨?_, ZO l hl⟩, o⟩
+ rcases lane01 hl with rfl | rfl
+ · exact Z0.congr fun e he => congrArg zetas ((hsel i hi e he).1.trans (congrArg zi (by omega)))
+ · exact Z1.congr fun e he => congrArg zetas ((hsel i hi e he).2.trans (congrArg zi (by omega)))
+ · -- the blocks of a lane
+ refine WP.mono (core2_ok hbf ht hA hB hz ho) fun t' ⟨⟨a, b⟩, o⟩ =>
+ ⟨⟨a.congr fun e he => ?_, b.congr fun e he => ?_⟩, o⟩
+ · by_cases h : e < 2
+ · rw [ite_eq_left h, hR _ (by omega), ite_eq_left (by omega), ite_eq_left (by omega)]
+ exact congrArg Prod.fst (op_idx op _ zi (by omega) (by omega) (by omega))
+ · rw [ite_eq_right h, hR _ (by omega), ite_eq_left (by omega), ite_eq_right (by omega)]
+ exact congrArg Prod.snd (op_idx op _ zi (by omega) (by omega) (by omega))
+ · by_cases h : e < 2
+ · rw [ite_eq_left h, hR _ (by omega), ite_eq_left (by omega), ite_eq_left (by omega)]
+ exact congrArg Prod.fst (op_idx op _ zi (by omega) (by omega) (by omega))
+ · rw [ite_eq_right h, hR _ (by omega), ite_eq_left (by omega), ite_eq_right (by omega)]
+ exact congrArg Prod.snd (op_idx op _ zi (by omega) (by omega) (by omega))
+
+theorem ylay1_ok (hY : laneSseBlock (toY (gath1 ++ bf ++ scat1)) = some (gath1 ++ bf ++ scat1)) {fP sP : Addr}
+ (k : Nat) (zl : List Instr) (dz : BitVec 32) (zi kb : Nat → Nat) (hkb0 : kb 0 = k)
+ (hk : ∀ i < 16, kb i + 8 ≤ 256)
+ (hzl : ∀ i < 16, ∀ s : State, s.gpr .r8 = coeffAddr sP (kb i) →
+ InRegions (s.rd ++ s.wr) (coeffAddr sP (kb i)) 32 → Tab zmTab s.mem sP 256 →
+ WP isa (.block zl) s fun s' => (∀ l < 2, ZLanes (s'.lane .xmm13 l)
+ (fun e => zetas (zi (8 * i + 2 * l + e + 2 * (e / 2)))) ∧ ZOdd (s'.lane .xmm13 l) (s'.lane .xmm12 l)) ∧
+ YOnly [.xmm13, .xmm12] s s')
+ (hstep : ∀ i < 16, coeffAddr sP (kb i) + BitVec.signExtend 64 dz = coeffAddr sP (kb (i + 1)))
+ {F : Poly} {s : State} (hc : YConsts s) (hdi : s.gpr .rdi = fP) (hsi : s.gpr .rsi = sP)
+ (hS : PolyIs s.mem fP F) (hT : Tab zmTab s.mem sP 256) (hwf : pR fP ∈ s.wr) (hw : pR sP ∈ s.wr)
+ (hd : (pR sP).Disjoint (pR fP)) :
+ WP isa (ylay1 bf k zl dz) s fun s' => PolyIs s'.mem fP (layF blk F 1 zi 128) ∧ BInvY fP s s' := by
+ have hk0 : k + 4 ≤ 256 := by have := hk 0 (by decide); omega
+ refine WP.seq (WP.mono (ypre21 k hk0 hdi hsi) fun w ⟨hdx, h8, og, hy⟩ => ?_)
+ have cw : YConsts w := ylanes_gpr (s := s) (og.lane hy) (YOnly.refl [] s) hc (by decide) (by decide)
+ refine WP.mono (wp_rcxLoopY (N := 16) (by decide) (by decide)
+ (fun i u => PolyIs u.mem fP (layF blk F 1 zi (8 * i)) ∧ u.gpr .rdx = coeffAddr fP (16 * i) ∧
+ u.gpr .r8 = coeffAddr sP (kb i) ∧ BInvY fP w u)
+ (fun u ou hu _ => ⟨by rw [ou.mem, og.mem]; exact hS,
+ by rw [ou.keep.gpr (by decide), hdx, Nat.mul_zero, coeffAddr, Nat.mul_zero, add_ofNat_zero],
+ by rw [ou.keep.gpr (by decide), h8, hkb0], ⟨ou.keep.mono (by simp), by rw [ou.mem]; exact Frame.refl _ _,
+ ylanes_gpr (s := w) (ou.lane hu) (YOnly.refl [] w) cw (by decide) (by decide), ou.mxcsr⟩⟩)
+ (fun i hi u ⟨hS', hdx', h8', hb'⟩ => ?_)) fun u ⟨hS', _, _, hb'⟩ =>
+ ⟨hS', ⟨(og.keep.trans hb'.keep).mono (by simp), by rw [← og.mem]; exact hb'.frame, hb'.consts,
+ by rw [hb'.mxcsr, og.mxcsr]⟩⟩
+ have hT' : Tab zmTab u.mem sP 256 := (by rw [og.mem]; exact hT : Tab zmTab w.mem sP 256).frame hb'.frame
+ (fun r hr => by rw [List.mem_singleton.mp hr]; exact hd) (by decide)
+ have hwf' : pR fP ∈ u.wr := by rw [hb'.keep.2.2, og.keep.2.2]; exact hwf
+ have hw' : pR sP ∈ u.wr := by rw [hb'.keep.2.2, og.keep.2.2]; exact hw
+ rw [show [Instr.vmovdquLoad .l256 .xmm0 (at_ .rdx 0), .vmovdquLoad .l256 .xmm2 (at_ .rdx 32)] ++ zl ++
+ [.alu .add .r8 (.imm dz)] ++ toY (gath1 ++ bf ++ scat1) ++
+ [.vmovdquStore .l256 (at_ .rdx 0) .xmm0, .vmovdquStore .l256 (at_ .rdx 32) .xmm1,
+ .alu .add .rdx (.imm 64)] ++ [.alu .sub .rcx (.imm 1)] =
+ ybody21 .xmm2 zl (gath1 ++ bf ++ scat1) dz by simp [List.append_assoc]]
+ have hR := fun x hx => layF1_next hblk F zi hi (x := x) hx
+ refine WP.mono (ystep21 hY (zs := [.xmm13, .xmm12]) (by decide) (by decide) (by decide) (by decide)
+ (by decide) (j := 16 * i) (by omega) (R := layF blk F 1 zi (8 * (i + 1)))
+ (ζ := fun l e => zetas (zi (8 * i + 2 * l + e + 2 * (e / 2)))) hb'.consts hdx' hS' hwf'
+ (fun s' k' => hzl i hi s' (by rw [k'.gpr, h8'])
+ (by rw [k'.rd, k'.wr]; exact f_in32 (List.mem_append_right _ hw') (hk i hi)) (by rw [k'.mem]; exact hT'))
+ (fun l hl t ht hA hB hz ho => ?_) (fun x hx h => by rw [hR x hx, ite_eq_right (by omega)]))
+ fun u' ⟨hS'', hdx'', h8'', hcx, hzf, hb''⟩ => ⟨⟨hS'', by rw [hdx'', Nat.mul_succ],
+ by rw [h8'', h8', hstep i hi], hb'.trans hb''⟩, hcx, hzf⟩
+ -- the blocks of a lane
+ refine WP.mono (core1_ok hbf ht hA hB hz ho) fun t' ⟨⟨a, b⟩, o⟩ =>
+ ⟨⟨a.congr fun e he => ?_, b.congr fun e he => ?_⟩, o⟩
+ · by_cases h : e % 2 = 0
+ · rw [ite_eq_left h, hR _ (by omega), ite_eq_left (by omega), ite_eq_left (by omega)]
+ exact congrArg Prod.fst (op_idx op _ zi (by omega) (by omega) (by omega))
+ · rw [ite_eq_right h, hR _ (by omega), ite_eq_left (by omega), ite_eq_right (by omega)]
+ exact congrArg Prod.snd (op_idx op _ zi (by omega) (by omega) (by omega))
+ · by_cases h : e % 2 = 0
+ · rw [ite_eq_left h, hR _ (by omega), ite_eq_left (by omega), ite_eq_left (by omega)]
+ exact congrArg Prod.fst (op_idx op _ zi (by omega) (by omega) (by omega))
+ · rw [ite_eq_right h, hR _ (by omega), ite_eq_left (by omega), ite_eq_right (by omega)]
+ exact congrArg Prod.snd (op_idx op _ zi (by omega) (by omega) (by omega))
+
+end
+
+end VG.Proof.MlDsa.X86_64.Arith
diff --git a/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YMul.lean b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YMul.lean
new file mode 100644
index 000000000..32c854216
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YMul.lean
@@ -0,0 +1,392 @@
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.YBase
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.Mul
+
+/-!
+# ML-DSA on x86-64: `vg_mldsa_multiply_ntt_avx2` and `vg_mldsa_multiply_add_ntt_avx2`
+
+Untrusted: everything here is checked by Lean. As `vg_mldsa_multiply_ntt`
+and `vg_mldsa_multiply_add_ntt` (`Mul.lean`) on eight coefficients at a
+time: each iteration of the loop loads eight coefficients of `f`, `g` and
+`h` and, in each lane, does what the SSE2 code's `mulCore` (`mulAddCore`)
+does (`ylanes`), on the coefficients `8i + 4l` to `8i + 4l + 3` of lane
+`l`, and stores the eight results (`YMul.step`); the loop stores the first
+248 (`YMul.loop_ok`), and the last eight, from the coefficients of `h` in
+`ymm6` (`YMul.last`), are stored after MXCSR is loaded back
+(`YMul.fn_ok`).
+-/
+
+namespace VG.Proof.MlDsa.X86_64.Arith
+
+open VG VG.X86_64 VG.Impl.MlDsa.X86_64.Arith
+open VG.Proof.MlDsa.Arith
+open VG.Proof.MlKem.X86_64 (Keep XOnly YOnly ylanes yld_ok yconst_ok WP.keep writesOnly gprPreserved_of ifp ifn
+ ptr_step GOnly wp_rcxLoopY add_ofNat_zero lane_setReg lane_setFlags sx32 State.setMem_ymm xmm_setXmm)
+open VG.Impl.MlKem.X86_64 (xb xmov toY yconst rcxLoop)
+open VG.Spec.MlDsa (q n Poly Zq coeffAt polyAt Reduced)
+
+theorem lane_mulCore : laneSseBlock (toY mulCore) = some mulCore := by decide +kernel
+theorem lane_mulAddCore : laneSseBlock (toY mulAddCore) = some mulAddCore := by decide +kernel
+
+/-- The constants, and `2⁶⁴ mod q` in both lanes of `ymm11`. -/
+theorem ymulPro_ok (s : State) :
+ WP isa (.block ymulPro) s fun s' => YConsts s' ∧ (∀ l < 2, s'.lane .xmm11 l = r2V) ∧
+ (∀ l < 2, s'.lane .xmm6 l = s.lane .xmm6 l) ∧ Keep [.rax] s s' ∧ s'.mem = s.mem := by
+ rw [ymulPro, WP.block_append_iff]
+ refine WP.mono (yconsts_ok s) fun s1 ⟨c1, k1, m1, _, o1⟩ =>
+ WP.mono (yconst_ok .xmm11 _ s1) fun s2 ⟨l2, k2, m2, _, o2⟩ =>
+ ⟨fun l hl => ⟨?_, ?_⟩, fun l hl => by rw [l2 l hl]; decide,
+ fun l hl => by rw [o2 _ (by decide) l hl, o1 _ (by decide) (by decide) l hl],
+ (k1.trans k2).mono (by simp), m2.trans m1⟩
+ · rw [State.proj_xmm, o2 _ (by decide) l hl]; exact (c1 l hl).q
+ · rw [State.proj_xmm, o2 _ (by decide) l hl]; exact (c1 l hl).qinv
+
+namespace YMul
+
+/-- After `i` iterations: the first `8i` coefficients of `h` are `R`'s, the
+others as they were in `s₀`. -/
+structure Inv (h f g : Addr) (s₀ : State) (R : Poly) (i : Nat) (s : State) : Prop where
+ rdi : s.gpr .rdi = h + BitVec.ofNat 64 (32 * i)
+ rsi : s.gpr .rsi = f + BitVec.ofNat 64 (32 * i)
+ rdx : s.gpr .rdx = g + BitVec.ofNat 64 (32 * i)
+ rd : s.rd = s₀.rd
+ wr : s.wr = s₀.wr
+ c : YConsts s
+ r2 : ∀ l < 2, s.lane .xmm11 l = r2V
+ x6 : ∀ l < 2, s.lane .xmm6 l = s₀.lane .xmm6 l
+ frame : Frame [pR h] s₀.mem s.mem
+ done : ∀ k < 8 * i, (coeffAt s.mem h k).toNat = (R[k]!).val
+ rest : ∀ k < 256, 8 * i ≤ k → coeffAt s.mem h k = coeffAt s₀.mem h k
+
+section
+variable {h f g : Addr} {s₀ : State} (hwh : pR h ∈ s₀.wr) (hrf : pR f ∈ s₀.rd ++ s₀.wr)
+ (hrg : pR g ∈ s₀.rd ++ s₀.wr) (hdf : (pR h).Disjoint (pR f)) (hdg : (pR h).Disjoint (pR g))
+ {F G : Poly} (hF : ∀ k < 256, (coeffAt s₀.mem f k).toNat = (F[k]!).val)
+ (hG : ∀ k < 256, (coeffAt s₀.mem g k).toNat = (G[k]!).val)
+ {core : List Instr} {Fv : BitVec 128 → BitVec 128 → BitVec 128 → BitVec 128}
+ (hcore : ∀ s : State, VConsts s → s.xmm .xmm11 = r2V → WP isa (.block core) s fun s' =>
+ s'.xmm .xmm3 = Fv (s.xmm .xmm3) (s.xmm .xmm13) (s.xmm .xmm5) ∧ XOnly [.xmm12, .xmm3, .xmm2, .xmm4] s s')
+ (hY : laneSseBlock (toY core) = some core)
+ {R : Poly} {H : Nat → BitVec 32} (hH : ∀ k < 248, coeffAt s₀.mem h k = H k)
+ (hlane : ∀ i < 64, ∀ x y z : BitVec 128, (∀ e < 4, (dword x e).toNat = (F[4 * i + e]!).val) →
+ (∀ e < 4, (dword y e).toNat = (G[4 * i + e]!).val) → (∀ e < 4, dword z e = H (4 * i + e)) →
+ ∀ e < 4, (dword (Fv x y z) e).toNat = (R[4 * i + e]!).val)
+include hwh hrf hrg hdf hdg hF hG hcore hY hH hlane
+
+theorem step {i : Nat} (hi : i < 31) {s : State} (hI : Inv h f g s₀ R i s) :
+ WP isa (.block (ymulLoads ++ toY core ++ ymulTail ++ ([.alu .sub .rcx (.imm 1)] : List Instr))) s fun s' =>
+ Inv h f g s₀ R (i + 1) s' ∧ s'.gpr .rcx = s.gpr .rcx - 1 ∧ s'.zf = some (s.gpr .rcx - 1 == 0) := by
+ have j0 : 8 * i + 8 ≤ 256 := by omega
+ have e1 : s.gpr .rsi + BitVec.ofNat 64 0 = coeffAddr f (8 * i) := by
+ rw [add_ofNat_zero, hI.rsi]; congr 2; omega
+ have e2 : s.gpr .rdx + BitVec.ofNat 64 0 = coeffAddr g (8 * i) := by
+ rw [add_ofNat_zero, hI.rdx]; congr 2; omega
+ have e3 : s.gpr .rdi + BitVec.ofNat 64 0 = coeffAddr h (8 * i) := by
+ rw [add_ofNat_zero, hI.rdi]; congr 2; omega
+ have mf : ∀ k < 256, coeffAt s.mem f k = coeffAt s₀.mem f k := fun k hk =>
+ coeffAt_frame hI.frame (by simpa using hdf.symm) (by rw [n_eq]; exact hk)
+ have mg : ∀ k < 256, coeffAt s.mem g k = coeffAt s₀.mem g k := fun k hk =>
+ coeffAt_frame hI.frame (by simpa using hdg.symm) (by rw [n_eq]; exact hk)
+ rw [show ymulLoads ++ toY core ++ ymulTail ++ ([.alu .sub .rcx (.imm 1)] : List Instr) =
+ [.vmovdquLoad .l256 .xmm3 (at_ .rsi 0)] ++ [.vmovdquLoad .l256 .xmm13 (at_ .rdx 0)] ++
+ [.vmovdquLoad .l256 .xmm5 (at_ .rdi 0)] ++ (toY core ++ (ymulTail ++ ([.alu .sub .rcx (.imm 1)] : List Instr)))
+ by simp [ymulLoads, List.append_assoc],
+ WP.block_append_iff, WP.block_append_iff, WP.block_append_iff]
+ refine WP.mono (yld_ok (by rw [e1, hI.rd, hI.wr]; exact ⟨_, hrf, pR_contains32 f j0⟩)) fun s1 ⟨L1, o1⟩ => ?_
+ refine WP.mono (yld_ok (by rw [o1.rd, o1.wr, o1.gpr, e2, hI.rd, hI.wr]; exact ⟨_, hrg, pR_contains32 g j0⟩))
+ fun s2 ⟨L2, o2⟩ => ?_
+ have o12 := o1.trans o2
+ refine WP.mono (yld_ok (by
+ rw [o12.rd, o12.wr, o12.gpr, e3, hI.rd, hI.wr]; exact f_in32 (List.mem_append_right _ hwh) j0))
+ fun s3 ⟨L3, o3⟩ => ?_
+ have o13 := o12.trans o3
+ rw [WP.block_append_iff]
+ refine WP.mono (ylanes hY (P := fun l t =>
+ t.xmm .xmm3 = Fv ((s3.proj l).xmm .xmm3) ((s3.proj l).xmm .xmm13) ((s3.proj l).xmm .xmm5))
+ fun l hl => hcore _ (yonly_yconsts o13 hI.c (by decide) (by decide) l hl)
+ (by rw [State.proj_xmm, o13.lane _ (by decide) l hl]; exact hI.r2 l hl))
+ fun s4 ⟨B4, o4⟩ => ?_
+ have o14 := o13.trans o4
+ have g4 : s4.gpr .rdi = coeffAddr h (8 * i) := by rw [o14.gpr, ← e3, add_ofNat_zero]
+ have w0 : InRegions s4.wr (s4.gpr .rdi) 32 := by rw [o14.wr, g4, hI.wr]; exact f_in32 hwh j0
+ -- the lanes of the result
+ have hl : ∀ l < 2, ∀ e < 4, (dword (s4.lane .xmm3 l) e).toNat = (R[8 * i + 4 * l + e]!).val := by
+ intro l hl e he
+ rw [← State.proj_xmm, B4 l hl, State.proj_xmm, State.proj_xmm, State.proj_xmm,
+ o3.lane _ (by decide) l hl, o2.lane _ (by decide) l hl, o3.lane _ (by decide) l hl, L1 l hl,
+ L2 l hl, L3 l hl, o1.gpr, o1.mem, o2.gpr, o2.mem, o1.gpr, o1.mem, e1, e2, e3,
+ show 8 * i + 4 * l + e = 4 * (2 * i + l) + e by omega]
+ refine hlane (2 * i + l) (by omega) _ _ _ (fun e he => ?_) (fun e he => ?_) (fun e he => ?_) e he
+ · rw [dword_readW _ _ he, lane_load, coeffAddr_add, ← coeffAt_eq, mf _ (by omega), hF _ (by omega),
+ show 8 * i + 4 * l + e = 4 * (2 * i + l) + e by omega]
+ · rw [dword_readW _ _ he, lane_load, coeffAddr_add, ← coeffAt_eq, mg _ (by omega), hG _ (by omega),
+ show 8 * i + 4 * l + e = 4 * (2 * i + l) + e by omega]
+ · rw [dword_readW _ _ he, lane_load, coeffAddr_add, ← coeffAt_eq, hI.rest _ (by omega) (by omega),
+ hH _ (by omega), show 8 * i + 4 * l + e = 4 * (2 * i + l) + e by omega]
+ simp only [ymulTail]
+ vrund [State.store256_eq, State.setMem_gpr, State.setMem_wr, State.setMem_mem, State.setMem_rd,
+ State.setMem_ymm, w0, sx32]
+ refine ⟨⟨?_, ?_, ?_, ?_, ?_, fun l hl => ⟨?_, ?_⟩, fun l hl => ?_, fun l hl => ?_, ?_, fun k hk => ?_,
+ fun k hk hk' => ?_⟩, ?_⟩
+ · simp only [RegUpd.gpr_setReg, RegUpd.gpr_setFlags, ite_true, ite_false, reduceCtorEq, State.setMem_gpr]
+ rw [o14.gpr, hI.rdi]; exact ptr_step _ i 32
+ · simp only [RegUpd.gpr_setReg, RegUpd.gpr_setFlags, ite_true, ite_false, reduceCtorEq, State.setMem_gpr]
+ rw [o14.gpr, hI.rsi]; exact ptr_step _ i 32
+ · simp only [RegUpd.gpr_setReg, RegUpd.gpr_setFlags, ite_true, ite_false, reduceCtorEq, State.setMem_gpr]
+ rw [o14.gpr, hI.rdx]; exact ptr_step _ i 32
+ · simp only [RegUpd.rd_setReg, RegUpd.rd_setFlags, State.setMem_rd]; rw [o14.rd, hI.rd]
+ · simp only [RegUpd.wr_setReg, RegUpd.wr_setFlags, State.setMem_wr]; rw [o14.wr, hI.wr]
+ · rw [State.proj_xmm]; simp only [lane_setReg, lane_setFlags, State.setMem_lane]
+ exact (yonly_yconsts o14 hI.c (by decide) (by decide) l hl).q
+ · rw [State.proj_xmm]; simp only [lane_setReg, lane_setFlags, State.setMem_lane]
+ exact (yonly_yconsts o14 hI.c (by decide) (by decide) l hl).qinv
+ · simp only [lane_setReg, lane_setFlags, State.setMem_lane]; rw [o14.lane _ (by decide) l hl]; exact hI.r2 l hl
+ · simp only [lane_setReg, lane_setFlags, State.setMem_lane]; rw [o14.lane _ (by decide) l hl]; exact hI.x6 l hl
+ · simp only [RegUpd.mem_setReg, RegUpd.mem_setFlags, State.setMem_mem]
+ rw [g4, o14.mem]; exact hI.frame.writeW (List.mem_singleton_self _) _ (pR_contains32 _ j0)
+ · simp only [RegUpd.mem_setReg, RegUpd.mem_setFlags, State.setMem_mem]
+ rw [g4, o14.mem, coeffAt_write256 _ _ j0 _ (by omega)]
+ split
+ · rename_i hk'
+ rw [State.ymm, extract_ymm _ _ (by omega)]
+ split
+ · rename_i h4
+ have := hl 0 (by decide) (k - 8 * i) h4
+ rw [show 8 * i + 4 * 0 + (k - 8 * i) = k by omega] at this
+ exact this
+ · rename_i h4
+ have := hl 1 (by decide) (k - 8 * i - 4) (by omega)
+ rw [show 8 * i + 4 * 1 + (k - 8 * i - 4) = k by omega] at this
+ exact this
+ · exact hI.done k (by omega)
+ · simp only [RegUpd.mem_setReg, RegUpd.mem_setFlags, State.setMem_mem]
+ rw [g4, o14.mem, coeffAt_write256 _ _ j0 _ hk, ifn (by omega)]
+ exact hI.rest k hk (by omega)
+ · exact ⟨by rw [o14.gpr], by rw [o14.gpr]⟩
+
+theorem loop_ok (hdi : s₀.gpr .rdi = h) (hsi : s₀.gpr .rsi = f) (hdx : s₀.gpr .rdx = g) (hc : YConsts s₀)
+ (h11 : ∀ l < 2, s₀.lane .xmm11 l = r2V) :
+ WP isa (rcxLoop 31 (ymulLoads ++ toY core ++ ymulTail)) s₀ (Inv h f g s₀ R 31) :=
+ wp_rcxLoopY (N := 31) (by decide) (by decide) _ (fun u o hy _ =>
+ have lu : ∀ r l, u.lane r l = s₀.lane r l := fun r l => by simp only [State.lane]; rw [o.xmm, hy]
+ ⟨by rw [o.keep.gpr (by decide), hdi, Nat.mul_zero, add_ofNat_zero],
+ by rw [o.keep.gpr (by decide), hsi, Nat.mul_zero, add_ofNat_zero],
+ by rw [o.keep.gpr (by decide), hdx, Nat.mul_zero, add_ofNat_zero], o.keep.2.1, o.keep.2.2,
+ fun l hl => ⟨by rw [State.proj_xmm, lu]; exact (hc l hl).q, by rw [State.proj_xmm, lu]; exact (hc l hl).qinv⟩,
+ fun l hl => by rw [lu]; exact h11 l hl, fun l _ => lu _ l,
+ by rw [o.mem]; exact Frame.refl _ _, fun k hk => absurd hk (by omega), fun k _ _ => by rw [o.mem]⟩)
+ fun i hi u hI => step hwh hrf hrg hdf hdg hF hG hcore hY hH hlane hi hI
+
+omit hwh hH in
+/-- The last eight coefficients, with those of `h` in `ymm6`. -/
+theorem last {s : State} (hI : Inv h f g s₀ R 31 s)
+ (hz : ∀ l < 2, ∀ e < 4, dword (s₀.lane .xmm6 l) e = H (248 + 4 * l + e)) :
+ WP isa (.block (ymulLast core)) s fun s' =>
+ (∀ l < 2, ∀ e < 4, (dword (s'.lane .xmm3 l) e).toNat = (R[248 + 4 * l + e]!).val) ∧ s'.gpr = s.gpr ∧
+ s'.mem = s.mem ∧ s'.rd = s.rd ∧ s'.wr = s.wr := by
+ have j0 : 8 * 31 + 8 ≤ 256 := by decide
+ have e1 : s.gpr .rsi + BitVec.ofNat 64 0 = coeffAddr f 248 := by rw [add_ofNat_zero, hI.rsi]
+ have e2 : s.gpr .rdx + BitVec.ofNat 64 0 = coeffAddr g 248 := by rw [add_ofNat_zero, hI.rdx]
+ have mf : ∀ k < 256, coeffAt s.mem f k = coeffAt s₀.mem f k := fun k hk =>
+ coeffAt_frame hI.frame (by simpa using hdf.symm) (by rw [n_eq]; exact hk)
+ have mg : ∀ k < 256, coeffAt s.mem g k = coeffAt s₀.mem g k := fun k hk =>
+ coeffAt_frame hI.frame (by simpa using hdg.symm) (by rw [n_eq]; exact hk)
+ have hY' : laneSseBlock ([.vop (.vmovdqa .l256 .xmm5 .xmm6)] ++ toY core) = some (xmov .xmm5 .xmm6 :: core) := by
+ show (match laneSse _, laneSseBlock (toY core) with | some a, some b => some (a ++ b) | _, _ => none) = _
+ rw [hY]; rfl
+ rw [ymulLast, show ∀ a b c : Instr, ∀ l : List Instr, [a, b, c] ++ l = [a] ++ [b] ++ ([c] ++ l) from
+ fun _ _ _ _ => rfl, WP.block_append_iff, WP.block_append_iff]
+ refine WP.mono (yld_ok (by rw [e1, hI.rd, hI.wr]; exact ⟨_, hrf, pR_contains32 f j0⟩)) fun s1 ⟨L1, o1⟩ => ?_
+ refine WP.mono (yld_ok (by rw [o1.rd, o1.wr, o1.gpr, e2, hI.rd, hI.wr]; exact ⟨_, hrg, pR_contains32 g j0⟩))
+ fun s2 ⟨L2, o2⟩ => ?_
+ have o12 := o1.trans o2
+ refine WP.mono (ylanes hY' (rs := [.xmm5, .xmm12, .xmm3, .xmm2, .xmm4]) (P := fun l t =>
+ t.xmm .xmm3 = Fv ((s2.proj l).xmm .xmm3) ((s2.proj l).xmm .xmm13) ((s2.proj l).xmm .xmm6))
+ fun l hl => ?_) fun s3 ⟨B3, o3⟩ => ⟨fun l hl e he => ?_, (o12.trans o3).gpr, (o12.trans o3).mem,
+ (o12.trans o3).rd, (o12.trans o3).wr⟩
+ · have c2 := yonly_yconsts o12 hI.c (by decide) (by decide) l hl
+ rw [show xmov .xmm5 .xmm6 :: core = [xmov .xmm5 .xmm6] ++ core from rfl, WP.block_append_iff]
+ vrund [eval_movdqa]
+ refine WP.mono (hcore _ (c2.setXmm (by decide) (by decide) _)
+ (by rw [xmm_setXmm, ifn (by decide), State.proj_xmm, o12.lane _ (by decide) l hl]; exact hI.r2 l hl))
+ fun t ⟨ht, ot⟩ => ⟨?_, ?_⟩
+ · rw [ht, xmm_setXmm, xmm_setXmm, xmm_setXmm, ifn (by decide), ifn (by decide), ifp rfl]
+ · refine (XOnly.trans (⟨⟨rfl, rfl, rfl, rfl, rfl⟩, fun r hr => ?_⟩ :
+ XOnly [.xmm5] (s2.proj l) ((s2.proj l).setXmm .xmm5 ((s2.proj l).xmm .xmm6))) ot).mono
+ (rs' := [.xmm5, .xmm12, .xmm3, .xmm2, .xmm4]) (by simp)
+ rw [xmm_setXmm, ifn (by simpa using hr)]
+ · rw [← State.proj_xmm, B3 l hl, State.proj_xmm, State.proj_xmm, State.proj_xmm,
+ o2.lane _ (by decide) l hl, L1 l hl, L2 l hl, o1.gpr, o1.mem, e1, e2,
+ o12.lane _ (by decide) l hl, hI.x6 l hl, show 248 + 4 * l + e = 4 * (62 + l) + e by omega]
+ refine hlane (62 + l) (by omega) _ _ _ (fun e he => ?_) (fun e he => ?_) (fun e he => ?_) e he
+ · rw [dword_readW _ _ he, lane_load, coeffAddr_add, ← coeffAt_eq, mf _ (by omega), hF _ (by omega),
+ show 248 + 4 * l + e = 4 * (62 + l) + e by omega]
+ · rw [dword_readW _ _ he, lane_load, coeffAddr_add, ← coeffAt_eq, mg _ (by omega), hG _ (by omega),
+ show 248 + 4 * l + e = 4 * (62 + l) + e by omega]
+ · rw [hz l hl e he, show 248 + 4 * l + e = 4 * (62 + l) + e by omega]
+
+end
+
+
+/-- The whole function, from its precondition, with a `core` whose lanes are
+those of `t`. -/
+theorem fn_ok {t : Poly → Poly → Poly → Poly} {hPre : Mem → Addr → Prop} {σ : State} (hp : (mulK t hPre).pre σ)
+ {core : List Instr} {Fv : BitVec 128 → BitVec 128 → BitVec 128 → BitVec 128}
+ (hcore : ∀ s : State, VConsts s → s.xmm .xmm11 = r2V → WP isa (.block core) s fun s' =>
+ s'.xmm .xmm3 = Fv (s.xmm .xmm3) (s.xmm .xmm13) (s.xmm .xmm5) ∧ XOnly [.xmm12, .xmm3, .xmm2, .xmm4] s s')
+ (hY : laneSseBlock (toY core) = some core)
+ (hlane : ∀ i < 64, ∀ x y z : BitVec 128,
+ (∀ e < 4, (dword x e).toNat = ((polyAt σ.mem (σ.gpr .rsi))[4 * i + e]!).val) →
+ (∀ e < 4, (dword y e).toNat = ((polyAt σ.mem (σ.gpr .rdx))[4 * i + e]!).val) →
+ (∀ e < 4, dword z e = coeffAt σ.mem (σ.gpr .rdi) (4 * i + e)) →
+ ∀ e < 4, (dword (Fv x y z) e).toNat = ((t (polyAt σ.mem (σ.gpr .rdi)) (polyAt σ.mem (σ.gpr .rsi))
+ (polyAt σ.mem (σ.gpr .rdx)))[4 * i + e]!).val)
+ (hk : writesOnly [.rax, .rdi, .rsi, .rdx, .rcx]
+ (.seq (.block ymulPro) (.seq (rcxLoop 31 (ymulLoads ++ toY core ++ ymulTail)) (.block (ymulLast core)))) =
+ true) :
+ WP isa (ymulFn core) σ fun s' => Keep [.r8, .rax, .r11, .rax, .rdi, .rsi, .rdx, .rcx] σ s' ∧
+ Frame [pR (σ.gpr .rdi)] σ.mem s'.mem ∧ (mulK t hPre).post σ s' := by
+ obtain ⟨hrd, hwr, hdf, hdg, -, -, -, -, redf, redg⟩ := hp
+ generalize eh : σ.gpr .rdi = h at *
+ generalize ef : σ.gpr .rsi = f at *
+ generalize eg : σ.gpr .rdx = g at *
+ let R := t (polyAt σ.mem h) (polyAt σ.mem f) (polyAt σ.mem g)
+ have hwh : pR h ∈ σ.wr := by rw [hwr]; exact List.mem_singleton_self _
+ simp only [ymulFn]
+ rw [show ∀ a b : Instr, [a, b] = [a] ++ [b] from fun _ _ => rfl]
+ refine WP.seq (WP.mono (Q := fun (s1 : State) => s1.gpr .r8 = h ∧
+ (∀ l < 2, s1.lane .xmm6 l = σ.mem.readW (coeffAddr h 248 + BitVec.ofNat 64 (16 * l)) 128) ∧
+ Keep [.r8] σ s1 ∧ s1.mem = σ.mem) ?_ fun s1 ⟨h8, h6, k1, m1⟩ => ?_)
+ · rw [WP.block_append_iff]
+ refine WP.mono (Q := fun (s0 : State) => s0.gpr .r8 = h ∧ s0.gpr .rdi = h ∧ GOnly [.r8] σ s0 ∧
+ s0.ymmHi = σ.ymmHi) (by vrund [eh, RegUpd.ymmHi_setReg]; gonlyd)
+ fun s0 ⟨h80, hd0, o0, y0⟩ => ?_
+ refine WP.mono (yld_ok (by
+ rw [hd0, o0.keep.2.1, o0.keep.2.2]
+ exact ⟨_, List.mem_append_right _ hwh, Offset.contains_base h (by omega) (by omega)⟩))
+ fun s1 ⟨L1, o1⟩ => ⟨by rw [o1.gpr, h80], fun l hl => by rw [L1 l hl, hd0, o0.mem],
+ ⟨fun r hr => by rw [o1.gpr, o0.keep.gpr hr], by rw [o1.rd, o0.keep.2.1], by rw [o1.wr, o0.keep.2.2]⟩,
+ by rw [o1.mem, o0.mem]⟩
+ have hw1 : pR h ∈ s1.wr := by rw [k1.2.2]; exact hwh
+ refine WP.seq (WP.mono (withMxcsrH_ok (r := .r8) ⟨by decide, by decide⟩ [.rax, .rdi, .rsi, .rdx, .rcx]
+ ⟨by decide, by decide⟩ h8 hw1 hk (Q := fun (s3 : State) => Keep [.rax, .r11, .rax, .rdi, .rsi, .rdx, .rcx] s1 s3 ∧
+ s3.gpr .rdi = coeffAddr h 248 ∧ Frame [pR h] σ.mem s3.mem ∧
+ (∀ k < 248, (coeffAt s3.mem h k).toNat = (R[k]!).val) ∧
+ ∀ l < 2, ∀ e < 4, (dword (s3.lane .xmm3 l) e).toNat = (R[248 + 4 * l + e]!).val)
+ fun s2 k2 f2 x2 y2 => ?_) fun s4 ⟨s3, ⟨kk, hdi, fr, dn, ln⟩, f4, k4, x4, y4⟩ => ?_)
+ · have fσ2 : Frame [mxH h] σ.mem s2.mem := by rw [← m1]; exact f2
+ have l2 : ∀ r l, s2.lane r l = s1.lane r l := fun r l => by simp only [State.lane]; rw [x2, y2]
+ refine WP.mono (WP.keep [.rax, .rdi, .rsi, .rdx, .rcx] (WP.seq (WP.mono (ymulPro_ok s2)
+ fun w ⟨cw, xw, x6, kw, mw⟩ => ?_) (Q := fun (s3 : State) => s3.gpr .rdi = coeffAddr h 248 ∧
+ Frame [pR h] σ.mem s3.mem ∧ (∀ k < 248, (coeffAt s3.mem h k).toNat = (R[k]!).val) ∧
+ ∀ l < 2, ∀ e < 4, (dword (s3.lane .xmm3 l) e).toNat = (R[248 + 4 * l + e]!).val)) hk)
+ fun s3 ⟨q3, kk⟩ => ⟨k2.trans kk, q3⟩
+ have gw : ∀ r, r ≠ .rax → r ≠ .r11 → r ≠ .r8 → w.gpr r = σ.gpr r := fun r h1 h2 h3 => by
+ rw [kw.gpr (by simpa using h1), k2.gpr (by simp [h1, h2]), k1.gpr (by simpa using h3)]
+ have rw' : w.rd = σ.rd ∧ w.wr = σ.wr :=
+ ⟨kw.2.1.trans (k2.2.1.trans k1.2.1), kw.2.2.trans (k2.2.2.trans k1.2.2)⟩
+ have fσw : Frame [mxH h] σ.mem w.mem := by rw [mw]; exact fσ2
+ have fσw' : Frame [pR h] σ.mem w.mem :=
+ Frame.sub fσw fun r hr => ⟨pR h, List.mem_singleton_self _, by
+ simp only [List.mem_singleton] at hr; subst hr; exact mxH_sub h⟩
+ refine WP.seq (WP.mono (loop_ok (s₀ := w) (h := h) (f := f) (g := g) (R := R) (F := polyAt σ.mem f)
+ (G := polyAt σ.mem g) (H := coeffAt σ.mem h)
+ (by rw [rw'.2]; exact hwh) (by rw [rw'.1, hrd]; simp) (by rw [rw'.1, hrd]; simp) hdf hdg
+ (fun k hk => by
+ rw [coeffAt_frame fσw' (by simpa using hdf.symm) (by rw [n_eq]; exact hk),
+ polyAt_val redf (by rw [n_eq]; exact hk)])
+ (fun k hk => by
+ rw [coeffAt_frame fσw' (by simpa using hdg.symm) (by rw [n_eq]; exact hk),
+ polyAt_val redg (by rw [n_eq]; exact hk)])
+ hcore hY (fun k hk => Mul.coeffAt_mxH fσw (by omega)) hlane
+ (by rw [gw _ (by decide) (by decide) (by decide), eh]) (by rw [gw _ (by decide) (by decide) (by decide), ef])
+ (by rw [gw _ (by decide) (by decide) (by decide), eg]) cw xw) fun s hI => ?_)
+ refine WP.mono (last (s₀ := w) (h := h) (f := f) (g := g) (R := R) (F := polyAt σ.mem f)
+ (G := polyAt σ.mem g) (H := coeffAt σ.mem h)
+ (by rw [rw'.1, hrd]; simp) (by rw [rw'.1, hrd]; simp) hdf hdg
+ (fun k hk => by
+ rw [coeffAt_frame fσw' (by simpa using hdf.symm) (by rw [n_eq]; exact hk),
+ polyAt_val redf (by rw [n_eq]; exact hk)])
+ (fun k hk => by
+ rw [coeffAt_frame fσw' (by simpa using hdg.symm) (by rw [n_eq]; exact hk),
+ polyAt_val redg (by rw [n_eq]; exact hk)])
+ hcore hY hlane hI (fun l hl e he => by
+ rw [x6 l hl, l2, h6 l hl, dword_readW _ _ he, lane_load, coeffAddr_add, ← coeffAt_eq]))
+ fun s3 ⟨ln, g3, m3, _, _⟩ => ?_
+ refine ⟨by rw [g3, hI.rdi], ?_, fun k hk => by rw [m3]; exact hI.done k (by omega), ln⟩
+ rw [m3]
+ exact Frame.trans fσw' hI.frame
+ · have k14 := (k1.trans kk).trans k4
+ have hdi4 : s4.gpr .rdi = coeffAddr h 248 := by rw [k4.gpr (by simp), hdi]
+ have wh4 : InRegions s4.wr (s4.gpr .rdi) 32 := by
+ rw [hdi4, k14.2.2]; exact f_in32 hwh (by omega)
+ have l4 : ∀ r l, s4.lane r l = s3.lane r l := fun r l => by simp only [State.lane]; rw [x4, y4]
+ simp only [yepi, List.singleton_append]
+ vrund [State.store256_eq, State.setMem_gpr, State.setMem_wr, State.setMem_mem, State.setMem_rd,
+ State.setMem_ymm, wh4]
+ have f4' : Frame [pR h] s3.mem s4.mem := Frame.sub f4 fun r hr => ⟨pR h, List.mem_singleton_self _, by
+ simp only [List.mem_singleton] at hr; subst hr; exact mxH_sub h⟩
+ refine ⟨k14.mono (by simp), (fr.trans f4').writeW (List.mem_singleton_self _) _
+ (by rw [hdi4]; exact pR_contains32 h (by omega)), ?_⟩
+ dsimp only [mulK]
+ rw [eh, ef, eg, show ∀ s : State, (VOp.vzeroupper.exec s).mem = s.mem from fun _ => rfl, State.setMem_mem]
+ refine polyIs_of_toNat fun k hk => ?_
+ rw [n_eq] at hk
+ rw [hdi4, coeffAt_write256 _ _ (j := 248) (by decide) _ hk]
+ split
+ · rw [State.ymm, extract_ymm _ _ (by omega)]
+ split
+ · rename_i h1 h4
+ have := ln 0 (by decide) (k - 248) h4
+ rw [show 248 + 4 * 0 + (k - 248) = k by omega, ← l4] at this
+ exact this
+ · rename_i h1 h4
+ have := ln 1 (by decide) (k - 248 - 4) (by omega)
+ rw [show 248 + 4 * 1 + (k - 248 - 4) = k by omega, ← l4] at this
+ exact this
+ · rw [Mul.coeffAt_mxH f4 (by omega)]
+ exact dn k (by omega)
+
+end YMul
+
+/-! ## The functions -/
+
+theorem mulY_correct (s : State) (hs : mulK'.pre s) :
+ ∃ t s', Exec isa mulAvx2 s t s' ∧ abiPreserved s s' ∧ mulK'.post s s' := by
+ obtain ⟨t, s', he, hk, hf, hq⟩ := YMul.fn_ok hs (core := mulCore) (Fv := fun x y _ => mulV x y)
+ (fun s hc h11 => mulCore_ok hc h11) lane_mulCore
+ (fun i hi x y z hx hy _ e he => by
+ rw [mul_get _ _ (by rw [n_eq]; omega)]
+ exact mul_lane hx hy he)
+ (by decide +kernel)
+ exact ⟨t, s', he, abiPreserved_of_ctl (by decide +kernel) he (gprPreserved_of hk (by decide) hf
+ (by simpa using hs.2.2.2.2.1)), hq⟩
+
+theorem mulAddY_correct (s : State) (hs : mulAddK.pre s) :
+ ∃ t s', Exec isa mulAddAvx2 s t s' ∧ abiPreserved s s' ∧ mulAddK.post s s' := by
+ obtain ⟨t, s', he, hk, hf, hq⟩ := YMul.fn_ok hs (core := mulAddCore) (Fv := mulAddV)
+ (fun s hc h11 => mulAddCore_ok hc h11) lane_mulAddCore
+ (fun i hi x y z hx hy hz e he => by
+ rw [add_get _ _ (by rw [n_eq]; omega), mul_get _ _ (by rw [n_eq]; omega)]
+ exact mulAdd_lane hx hy (c := fun e => (polyAt s.mem (s.gpr .rdi))[4 * i + e]!)
+ (fun e he => by rw [hz e he, polyAt_val hs.2.2.2.2.2.2.2.1 (by rw [n_eq]; omega)]) he)
+ (by decide +kernel)
+ exact ⟨t, s', he, abiPreserved_of_ctl (by decide +kernel) he (gprPreserved_of hk (by decide) hf
+ (by simpa using hs.2.2.2.2.1)), hq⟩
+
+theorem mulY_ct : ConstantTime isa mulK'.pre mulK'.pub mulAvx2 :=
+ VG.Taint.constantTime (A := taint) mulτ mul_agree (by taint_decide)
+
+theorem mulAddY_ct : ConstantTime isa mulAddK.pre mulAddK.pub mulAddAvx2 :=
+ VG.Taint.constantTime (A := taint) mulτ mul_agree (by taint_decide)
+
+theorem mulY_verified : Verified X86_64.target mulAvx2 (Spec.MlDsa.mulContract X86_64.abi) :=
+ Verified.of_correct mulY_correct mulY_ct (by
+ mldsa_implies [Spec.MlDsa.mulContract, Spec.MlDsa.mulSig, mulK, X86_64.abi, X86_64.argRegs]
+ [mulSat] using mulSat)
+
+theorem mulAddY_verified : Verified X86_64.target mulAddAvx2 (Spec.MlDsa.mulAddContract X86_64.abi) :=
+ Verified.of_correct mulAddY_correct mulAddY_ct (by
+ mldsa_implies [Spec.MlDsa.mulAddContract, Spec.MlDsa.mulSig, mulK, X86_64.abi, X86_64.argRegs]
+ [mulSat] using mulSat)
+
+end VG.Proof.MlDsa.X86_64.Arith
diff --git a/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YNtt.lean b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YNtt.lean
new file mode 100644
index 000000000..4e06aaf10
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/MlDsa/X86_64/Arith/YNtt.lean
@@ -0,0 +1,419 @@
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.YLay21
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.NttInv
+
+/-!
+# ML-DSA on x86-64: `vg_mldsa_ntt_avx2` and `vg_mldsa_inv_ntt_avx2`
+
+Untrusted: everything here is checked by Lean. As `vg_mldsa_ntt` and
+`vg_mldsa_inv_ntt` (`Ntt.lean`, `NttInv.lean`): ML-KEM's `withMxcsr` runs
+the code from any MXCSR and keeps what it does (`ymx_correct`); the
+prologue leaves the table of zetas in `scratch` and the constants in both
+lanes (`ypro_ok`); each layer is `nttLayer` or `nttInvLayer` (`ylay_ok`,
+`ylay4_ok`, `ylay2_ok`, `ylay1_ok`), `NTT⁻¹` then multiplies every
+coefficient by `8347681 = 256⁻¹ mod q` (`yscale_ok`), and `vzeroupper`
+keeps the memory (`LIY.epi`).
+-/
+
+namespace VG.Proof.MlDsa.X86_64.Arith
+
+open VG VG.X86_64 VG.Impl.MlDsa.X86_64.Arith
+open VG.Proof.MlDsa.Arith
+open VG.Proof.MlKem.X86_64 (Keep XOnly YOnly ylanes yld_ok yconst_ok ifp ifn sel GOnly WP.keep writesOnly
+ gprPreserved_of withMxcsr_ok mxR add_ofNat_zero wp_rcxLoopY lane_setReg lane_setFlags State.setMem_ymm sx32)
+open VG.Impl.MlKem.X86_64 (xb xmov toY rcxLoop yconst)
+open VG.Spec.MlDsa (q n Poly Zq coeffAt polyAt PolyIs zetas ntt nttInv)
+
+theorem lane_vbfly : laneSseBlock (toY vbfly) = some vbfly := by decide +kernel
+theorem lane_vibfly : laneSseBlock (toY vibfly) = some vibfly := by decide +kernel
+theorem lane_core2f : laneSseBlock (toY (gath2 ++ vbfly ++ scat2)) = some (gath2 ++ vbfly ++ scat2) := by
+ decide +kernel
+theorem lane_core2i : laneSseBlock (toY (gath2 ++ vibfly ++ scat2)) = some (gath2 ++ vibfly ++ scat2) := by
+ decide +kernel
+theorem lane_core1f : laneSseBlock (toY (gath1 ++ vbfly ++ scat1)) = some (gath1 ++ vbfly ++ scat1) := by
+ decide +kernel
+theorem lane_core1i : laneSseBlock (toY (gath1 ++ vibfly ++ scat1)) = some (gath1 ++ vibfly ++ scat1) := by
+ decide +kernel
+theorem lane_vmul3 : laneSseBlock (toY (vmont .xmm3 .xmm13 .xmm12 .xmm2 .xmm4 ++ vcsub .xmm3 .xmm2)) =
+ some (vmont .xmm3 .xmm13 .xmm12 .xmm2 .xmm4 ++ vcsub .xmm3 .xmm2) := by decide +kernel
+
+/-! ## The prologue and the layers -/
+
+/-- The table of zetas and the constants. -/
+theorem ypro_ok {sP : Addr} {s : State} (hsi : s.gpr .rsi = sP) (hw : pR sP ∈ s.wr) :
+ WP isa (.block ypro) s fun s' => Tab zmTab s'.mem sP 256 ∧ YConsts s' ∧
+ Frame [pR sP] s.mem s'.mem ∧ Keep [.r9, .rax] s s' ∧ s'.mxcsr = s.mxcsr := by
+ rw [ypro, WP.block_append_iff]
+ refine WP.mono (dwordTab_ok zmTab (fun k => Nat.lt_trans (zmTab_lt k) (by decide)) (by decide) hsi hw)
+ fun s1 ⟨hT, hf, k1, x1, _⟩ => WP.mono (yconsts_ok s1) fun s2 ⟨hc, k2, m2, x2, _⟩ =>
+ ⟨by rw [m2]; exact hT, hc, by rw [m2]; exact hf, (k1.trans k2).mono (by simp), by rw [x2, x1]⟩
+
+/-- Between the layers: the polynomial `F` at `fP`, the table at `sP`, and
+the constants in both lanes. -/
+structure LIY (fP sP : Addr) (s₀ : State) (F : Poly) (s : State) : Prop where
+ P : PolyIs s.mem fP F
+ T : Tab zmTab s.mem sP 256
+ c : YConsts s
+ keep : Keep [.rax, .rcx, .rdx, .r8] s₀ s
+ frame : Frame [pR fP] s₀.mem s.mem
+
+/-- A layer, then `c`. -/
+theorem LIY.seq {fP sP : Addr} {s₀ : State} (hdi : s₀.gpr .rdi = fP) (hsi : s₀.gpr .rsi = sP)
+ (hwf : pR fP ∈ s₀.wr) (hw : pR sP ∈ s₀.wr) (hd : (pR sP).Disjoint (pR fP)) {l c : Prog isa}
+ {F F' : Poly} {Q : State → Prop}
+ (hl : ∀ s, YConsts s → s.gpr .rdi = fP → s.gpr .rsi = sP → PolyIs s.mem fP F → Tab zmTab s.mem sP 256 →
+ pR fP ∈ s.wr → pR sP ∈ s.wr → WP isa l s fun s' => PolyIs s'.mem fP F' ∧ BInvY fP s s')
+ (hc : ∀ s, LIY fP sP s₀ F' s → WP isa c s Q) {s : State} (hI : LIY fP sP s₀ F s) :
+ WP isa (.seq l c) s Q :=
+ WP.seq (WP.mono (hl s hI.c (by rw [hI.keep.gpr (by decide), hdi]) (by rw [hI.keep.gpr (by decide), hsi]) hI.P
+ hI.T (by rw [hI.keep.2.2]; exact hwf) (by rw [hI.keep.2.2]; exact hw))
+ fun s' ⟨hS, hb⟩ => hc s' ⟨hS, hI.T.frame hb.frame (fun r hr => by rw [List.mem_singleton.mp hr]; exact hd)
+ (by decide), hb.consts, (hI.keep.trans hb.keep).mono (by decide), hI.frame.trans hb.frame⟩)
+
+/-- `vzeroupper` keeps the memory. -/
+theorem LIY.epi {fP sP : Addr} {s₀ : State} {F : Poly} {s : State} (hI : LIY fP sP s₀ F s) :
+ WP isa (.block yepi) s fun s' => PolyIs s'.mem fP F ∧ Frame [pR fP] s₀.mem s'.mem :=
+ WP.mono (Q := fun (u : State) => u.mem = s.mem) (by simp only [yepi]; vrund; rfl)
+ fun u hm => by rw [hm]; exact ⟨hI.P, hI.frame⟩
+
+/-- A layer of `NTT` with `len ≥ 8`, whose first zeta is `zetas k`. -/
+theorem yfwdLay_ok {fP sP : Addr} (hd : (pR sP).Disjoint (pR fP)) (len k : Nat)
+ (hlen : len ∈ [8, 16, 32, 64, 128]) (hk : 128 / len = k) {F : Poly} (s : State) (hc : YConsts s)
+ (hdi : s.gpr .rdi = fP) (hsi : s.gpr .rsi = sP) (hS : PolyIs s.mem fP F) (hT : Tab zmTab s.mem sP 256)
+ (hwf : pR fP ∈ s.wr) (hw : pR sP ∈ s.wr) :
+ WP isa (ylay vbfly len k 4) s fun s' => PolyIs s'.mem fP (nttLayer F len) ∧ BInvY fP s s' := by
+ rw [nttLayer_eq]
+ exact ylay_ok vbfly_spec lane_vbfly nttBlk_ok hlen 4 (fun c => 128 / len + c) (by rw [hk]; rfl)
+ (fun c hc => by
+ simp only [List.mem_cons, List.not_mem_nil, or_false] at hlen
+ rcases hlen with rfl | rfl | rfl | rfl | rfl <;> omega)
+ (fun c _ => step_fwd _ _ 1 (by decide)) hc hdi hsi hS hT hwf hw hd
+
+theorem yfwdLay4_ok {fP sP : Addr} (hd : (pR sP).Disjoint (pR fP)) {F : Poly} (s : State) (hc : YConsts s)
+ (hdi : s.gpr .rdi = fP) (hsi : s.gpr .rsi = sP) (hS : PolyIs s.mem fP F) (hT : Tab zmTab s.mem sP 256)
+ (hwf : pR fP ∈ s.wr) (hw : pR sP ∈ s.wr) :
+ WP isa (ylay4 vbfly 32 0x00 0x55 8) s fun s' => PolyIs s'.mem fP (nttLayer F 4) ∧ BInvY fP s s' := by
+ have h0 : ∀ e < 4, sel 0x00 e = 0 := by decide
+ have h5 : ∀ e < 4, sel 0x55 e = 1 := by decide
+ rw [nttLayer_eq, show 128 / 4 = 32 from rfl]
+ exact ylay4_ok vbfly_spec lane_vbfly nttBlk_ok 32 0x00 0x55 8 (fun c => 32 + c) (fun m => 32 + 2 * m) rfl
+ (fun m _ => by omega) (fun m _ e he => ⟨by rw [h0 e he]; omega, by rw [h5 e he]; omega⟩)
+ (fun m _ => (step_fwd _ _ 2 (by decide)).trans (congrArg _ (by omega))) hc hdi hsi hS hT hwf hw hd
+
+theorem yfwdLay2_ok {fP sP : Addr} (hd : (pR sP).Disjoint (pR fP)) {F : Poly} (s : State) (hc : YConsts s)
+ (hdi : s.gpr .rdi = fP) (hsi : s.gpr .rsi = sP) (hS : PolyIs s.mem fP F) (hT : Tab zmTab s.mem sP 256)
+ (hwf : pR fP ∈ s.wr) (hw : pR sP ∈ s.wr) :
+ WP isa (ylay2 vbfly 64 0xA0 0xF5 16) s fun s' => PolyIs s'.mem fP (nttLayer F 2) ∧ BInvY fP s s' := by
+ have hA : ∀ e < 4, sel 0xA0 e = 2 * (e / 2) := by decide
+ have hF : ∀ e < 4, sel 0xF5 e = 1 + 2 * (e / 2) := by decide
+ rw [nttLayer_eq, show 128 / 2 = 64 from rfl]
+ exact ylay2_ok nttBlk_ok vbfly_spec lane_core2f 64 0xA0 0xF5 16 (fun c => 64 + c) (fun i => 64 + 4 * i) rfl
+ (fun i _ => by omega) (fun i _ e he => ⟨by rw [hA e he]; omega, by rw [hF e he]; omega⟩)
+ (fun i _ => (step_fwd _ _ 4 (by decide)).trans (congrArg _ (by omega))) hc hdi hsi hS hT hwf hw hd
+
+theorem yfwdLay1_ok {fP sP : Addr} (hd : (pR sP).Disjoint (pR fP)) {F : Poly} (s : State) (hc : YConsts s)
+ (hdi : s.gpr .rdi = fP) (hsi : s.gpr .rsi = sP) (hS : PolyIs s.mem fP F) (hT : Tab zmTab s.mem sP 256)
+ (hwf : pR fP ∈ s.wr) (hw : pR sP ∈ s.wr) :
+ WP isa (ylay1 vbfly 128 yzeta8 32) s fun s' => PolyIs s'.mem fP (nttLayer F 1) ∧ BInvY fP s s' := by
+ rw [nttLayer_eq, show 128 / 1 = 128 from rfl]
+ exact ylay1_ok nttBlk_ok vbfly_spec lane_core1f 128 yzeta8 32 (fun c => 128 + c) (fun i => 128 + 8 * i) rfl
+ (fun i _ => by omega)
+ (fun i hi s h8 hin hT => WP.mono (yzeta8_ok (by omega) h8 hin hT) fun _ ⟨z, o⟩ =>
+ ⟨fun l hl => ⟨(z l hl).1.congr fun e he => congrArg zetas (by omega), (z l hl).2⟩, o⟩)
+ (fun i _ => (step_fwd _ _ 8 (by decide)).trans (congrArg _ (by omega))) hc hdi hsi hS hT hwf hw hd
+
+theorem yinvLay_ok {fP sP : Addr} (hd : (pR sP).Disjoint (pR fP)) (len k : Nat)
+ (hlen : len ∈ [8, 16, 32, 64, 128]) (hk : 256 / len - 1 = k) {F : Poly} (s : State) (hc : YConsts s)
+ (hdi : s.gpr .rdi = fP) (hsi : s.gpr .rsi = sP) (hS : PolyIs s.mem fP F) (hT : Tab zmTab s.mem sP 256)
+ (hwf : pR fP ∈ s.wr) (hw : pR sP ∈ s.wr) :
+ WP isa (ylay vibfly len k (-4)) s fun s' => PolyIs s'.mem fP (nttInvLayer F len) ∧ BInvY fP s s' := by
+ have hl : 128 / len ≥ 1 ∧ 256 / len = 2 * (128 / len) ∧ 256 / len ≤ 32 := by
+ simp only [List.mem_cons, List.not_mem_nil, or_false] at hlen
+ rcases hlen with rfl | rfl | rfl | rfl | rfl <;> decide
+ rw [nttInvLayer_eq]
+ exact ylay_ok vibfly_spec lane_vibfly nttInvBlk_ok hlen (-4) (fun c => 256 / len - 1 - c) (by rw [hk]; rfl)
+ (fun c _ => by omega)
+ (fun c hc' => (congrArg (· + _) (congrArg (coeffAddr sP) (show 256 / len - 1 - c =
+ 256 / len - 1 - (c + 1) + 1 by omega))).trans (step_bwd _ _ 1 (by decide)))
+ hc hdi hsi hS hT hwf hw hd
+
+theorem yinvLay4_ok {fP sP : Addr} (hd : (pR sP).Disjoint (pR fP)) {F : Poly} (s : State) (hc : YConsts s)
+ (hdi : s.gpr .rdi = fP) (hsi : s.gpr .rsi = sP) (hS : PolyIs s.mem fP F) (hT : Tab zmTab s.mem sP 256)
+ (hwf : pR fP ∈ s.wr) (hw : pR sP ∈ s.wr) :
+ WP isa (ylay4 vibfly 62 0x55 0x00 (-8)) s fun s' => PolyIs s'.mem fP (nttInvLayer F 4) ∧ BInvY fP s s' := by
+ have h0 : ∀ e < 4, sel 0x00 e = 0 := by decide
+ have h5 : ∀ e < 4, sel 0x55 e = 1 := by decide
+ rw [nttInvLayer_eq, show 256 / 4 - 1 = 63 from rfl, show 128 / 4 = 32 from rfl]
+ exact ylay4_ok vibfly_spec lane_vibfly nttInvBlk_ok 62 0x55 0x00 (-8) (fun c => 63 - c) (fun m => 62 - 2 * m)
+ rfl (fun m _ => by omega) (fun m _ e he => ⟨by rw [h5 e he]; omega, by rw [h0 e he]; omega⟩)
+ (fun m _ => (congrArg (· + _) (congrArg (coeffAddr sP) (show 62 - 2 * m = 62 - 2 * (m + 1) + 2 by
+ omega))).trans (step_bwd _ _ 2 (by decide))) hc hdi hsi hS hT hwf hw hd
+
+theorem yinvLay2_ok {fP sP : Addr} (hd : (pR sP).Disjoint (pR fP)) {F : Poly} (s : State) (hc : YConsts s)
+ (hdi : s.gpr .rdi = fP) (hsi : s.gpr .rsi = sP) (hS : PolyIs s.mem fP F) (hT : Tab zmTab s.mem sP 256)
+ (hwf : pR fP ∈ s.wr) (hw : pR sP ∈ s.wr) :
+ WP isa (ylay2 vibfly 124 0x5F 0x0A (-16)) s fun s' => PolyIs s'.mem fP (nttInvLayer F 2) ∧
+ BInvY fP s s' := by
+ have hA : ∀ e < 4, sel 0x5F e = 3 - 2 * (e / 2) := by decide
+ have hB : ∀ e < 4, sel 0x0A e = 2 - 2 * (e / 2) := by decide
+ rw [nttInvLayer_eq, show 256 / 2 - 1 = 127 from rfl, show 128 / 2 = 64 from rfl]
+ exact ylay2_ok nttInvBlk_ok vibfly_spec lane_core2i 124 0x5F 0x0A (-16) (fun c => 127 - c)
+ (fun i => 124 - 4 * i) rfl (fun i _ => by omega)
+ (fun i _ e he => ⟨by rw [hA e he]; omega, by rw [hB e he]; omega⟩)
+ (fun i _ => (congrArg (· + _) (congrArg (coeffAddr sP) (show 124 - 4 * i = 124 - 4 * (i + 1) + 4 by
+ omega))).trans (step_bwd _ _ 4 (by decide))) hc hdi hsi hS hT hwf hw hd
+
+theorem yinvLay1_ok {fP sP : Addr} (hd : (pR sP).Disjoint (pR fP)) {F : Poly} (s : State) (hc : YConsts s)
+ (hdi : s.gpr .rdi = fP) (hsi : s.gpr .rsi = sP) (hS : PolyIs s.mem fP F) (hT : Tab zmTab s.mem sP 256)
+ (hwf : pR fP ∈ s.wr) (hw : pR sP ∈ s.wr) :
+ WP isa (ylay1 vibfly 248 yzeta8R (-32)) s fun s' => PolyIs s'.mem fP (nttInvLayer F 1) ∧
+ BInvY fP s s' := by
+ rw [nttInvLayer_eq, show 256 / 1 - 1 = 255 from rfl, show 128 / 1 = 128 from rfl]
+ exact ylay1_ok nttInvBlk_ok vibfly_spec lane_core1i 248 yzeta8R (-32) (fun c => 255 - c)
+ (fun i => 248 - 8 * i) rfl (fun i _ => by omega)
+ (fun i hi s h8 hin hT => WP.mono (yzeta8R_ok (by omega) h8 hin hT) fun _ ⟨z, o⟩ =>
+ ⟨fun l hl => ⟨(z l hl).1.congr fun e he => congrArg zetas (by omega), (z l hl).2⟩, o⟩)
+ (fun i _ => (congrArg (· + _) (congrArg (coeffAddr sP) (show 248 - 8 * i = 248 - 8 * (i + 1) + 8 by
+ omega))).trans (step_bwd _ _ 8 (by decide))) hc hdi hsi hS hT hwf hw hd
+
+/-! ## The multiplication by `256⁻¹` -/
+
+/-- The coefficients of `G` before `8i` multiplied by `8347681`. -/
+def YScaled (m : Mem) (fP : Addr) (G : Poly) (i : Nat) : Prop :=
+ ∀ k < 256, (coeffAt m fP k).toNat = (if k < 8 * i then G[k]! * 8347681 else G[k]!).val
+
+/-- `8347681 · 2³² mod q` in each doubleword. -/
+theorem scale_lanes : ZLanes (ofDwords 16382#32 16382#32 16382#32 16382#32) (fun _ => 8347681) ∧
+ ZOdd (ofDwords 16382#32 16382#32 16382#32 16382#32) (ofDwords 16382#32 16382#32 16382#32 16382#32) :=
+ ⟨fun i hi => by rcases cases4 hi with rfl | rfl | rfl | rfl <;> decide,
+ fun j hj => by rcases (by omega : j = 0 ∨ j = 1) with rfl | rfl <;> decide⟩
+
+theorem mov12_ok (t : State) :
+ WP isa (.block [xmov .xmm12 .xmm13]) t fun t' => t'.xmm .xmm12 = t.xmm .xmm13 ∧ XOnly [.xmm12] t t' := by
+ simp only [xmov, xb]
+ vrun [eval_movdqa]
+ exact ⟨by first | trivial | simp, by xonly⟩
+
+/-- The body of the loop of `yscale`. -/
+abbrev sbodyY : List Instr :=
+ [.vmovdquLoad .l256 .xmm3 (at_ .rdx 0)] ++ toY (vmont .xmm3 .xmm13 .xmm12 .xmm2 .xmm4 ++ vcsub .xmm3 .xmm2) ++
+ [.vmovdquStore .l256 (at_ .rdx 0) .xmm3, .alu .add .rdx (.imm 32)] ++ [.alu .sub .rcx (.imm 1)]
+
+theorem yscale_step {fP : Addr} {G : Poly} {i : Nat} (hi : i < 32) {s : State} (hc : YConsts s)
+ (hz : ∀ l < 2, ZLanes (s.lane .xmm13 l) (fun _ => 8347681))
+ (ho : ∀ l < 2, ZOdd (s.lane .xmm13 l) (s.lane .xmm12 l))
+ (hdx : s.gpr .rdx = coeffAddr fP (8 * i)) (hS : YScaled s.mem fP G i) (hw : pR fP ∈ s.wr) :
+ WP isa (.block sbodyY) s fun s' =>
+ YScaled s'.mem fP G (i + 1) ∧ s'.gpr .rdx = coeffAddr fP (8 * (i + 1)) ∧
+ Frame [pR fP] s.mem s'.mem ∧ YConsts s' ∧ (∀ l < 2, s'.lane .xmm13 l = s.lane .xmm13 l) ∧
+ (∀ l < 2, s'.lane .xmm12 l = s.lane .xmm12 l) ∧ Keep [.rdx, .rcx] s s' ∧
+ s'.gpr .rcx = s.gpr .rcx - 1 ∧ s'.zf = some (s.gpr .rcx - 1 == 0) ∧ s'.mxcsr = s.mxcsr := by
+ have j0 : 8 * i + 8 ≤ 256 := by omega
+ have r0 : InRegions (s.rd ++ s.wr) (s.gpr .rdx + BitVec.ofNat 64 0) 32 := by
+ rw [hdx, add_ofNat_zero]; exact f_in32 (List.mem_append_right _ hw) j0
+ rw [sbodyY, List.append_assoc, List.append_assoc, WP.block_append_iff]
+ refine WP.mono (yld_ok r0) fun s1 ⟨L1, o1⟩ => ?_
+ rw [WP.block_append_iff]
+ refine WP.mono (ylanes lane_vmul3 (P := fun l t =>
+ t.xmm .xmm3 = csubV (montV (s1.lane .xmm3 l) (s1.lane .xmm13 l) (s1.lane .xmm12 l)))
+ fun l hl => vmul3_ok (yonly_yconsts o1 hc (by decide) (by decide) l hl)) fun s2 ⟨V2, o2⟩ => ?_
+ have o12 := o1.trans o2
+ have hv : ∀ l < 2, ∀ e < 4, (dword (s2.lane .xmm3 l) e).toNat = (G[8 * i + 4 * l + e]! * 8347681).val := by
+ intro l hl e he
+ have hx : DLanes (s1.lane .xmm3 l) (fun e => G[8 * i + 4 * l + e]!) := fun e he => by
+ rw [L1 l hl, hdx, add_ofNat_zero, dword_readW _ _ he, lane_load, coeffAddr_add, ← coeffAt_eq,
+ hS _ (by omega), ifn (by omega)]
+ have hz' : ZLanes (s1.lane .xmm13 l) (fun _ => 8347681) := by
+ rw [o1.lane _ (by decide) l hl]; exact hz l hl
+ have ho' : ZOdd (s1.lane .xmm13 l) (s1.lane .xmm12 l) := by
+ rw [o1.lane _ (by decide) l hl, o1.lane _ (by decide) l hl]; exact ho l hl
+ have e2 : s2.lane .xmm3 l = _ := V2 l hl
+ rw [e2, dword_csubV _ he, mulZ (hx e he) (hz' e he) (dword_montV ho' (prod_lt hx hz') he)]
+ dsimp only
+ rw [Fin.mul_comm]
+ have w0 : InRegions s2.wr (s2.gpr .rdx) 32 := by rw [o12.wr, o12.gpr, hdx]; exact f_in32 hw j0
+ vrund [State.store256_eq, State.setMem_gpr, State.setMem_wr, State.setMem_mem, State.setMem_rd, State.setMem_ymm,
+ w0, sx32]
+ have g2 : s2.gpr .rdx = coeffAddr fP (8 * i) := by rw [o12.gpr, hdx]
+ rw [g2, o12.mem]
+ refine ⟨fun k hk => ?_, ?_, ?_, ?_, ?_, ?_, ⟨fun r hr => ?_, ?_, ?_⟩, ?_, ?_, ?_⟩
+ · rw [coeffAt_write256 _ _ j0 _ hk]
+ split
+ · rename_i h
+ rw [ifp (show k < 8 * (i + 1) by omega), State.ymm, extract_ymm _ _ (by omega)]
+ split
+ · have := hv 0 (by decide) (k - 8 * i) (by omega)
+ rw [show 8 * i + 4 * 0 + (k - 8 * i) = k by omega] at this; exact this
+ · have := hv 1 (by decide) (k - 8 * i - 4) (by omega)
+ rw [show 8 * i + 4 * 1 + (k - 8 * i - 4) = k by omega] at this; exact this
+ · rename_i h
+ rw [hS k hk]
+ by_cases h' : k < 8 * i
+ · rw [ifp h', ifp (by omega)]
+ · rw [ifn h', ifn (by omega)]
+ · rw [show (32 : BitVec 64) = BitVec.ofNat 64 (4 * 8) from rfl, coeffAddr_add,
+ show 8 * i + 8 = 8 * (i + 1) by omega]
+ · exact (Frame.refl _ _).writeW (List.mem_singleton_self _) _ (pR_contains32 fP j0)
+ · exact ylanes_gpr (s := s2) (fun r l => by simp only [lane_setReg, lane_setFlags, State.setMem_lane]) o12 hc
+ (by decide) (by decide)
+ · intro l hl; simp only [lane_setReg, lane_setFlags, State.setMem_lane]; exact o12.lane _ (by decide) l hl
+ · intro l hl; simp only [lane_setReg, lane_setFlags, State.setMem_lane]; exact o12.lane _ (by decide) l hl
+ · simp only [List.mem_cons, List.not_mem_nil, or_false, not_or] at hr
+ simp only [RegUpd.gpr_setReg, RegUpd.gpr_setFlags, hr.1, hr.2, ite_false, State.setMem_gpr]
+ rw [o12.gpr]
+ · simp only [RegUpd.rd_setReg, RegUpd.rd_setFlags, State.setMem_rd]; rw [o12.rd]
+ · simp only [RegUpd.wr_setReg, RegUpd.wr_setFlags, State.setMem_wr]; rw [o12.wr]
+ · rw [o12.gpr]
+ · rw [o12.gpr]
+ · exact o12.mxcsr
+
+/-- Every coefficient times `8347681`. -/
+theorem yscale_ok {fP sP : Addr} (_hd : (pR sP).Disjoint (pR fP)) {G : Poly} (s : State) (hc : YConsts s)
+ (hdi : s.gpr .rdi = fP) (_hsi : s.gpr .rsi = sP) (hS : PolyIs s.mem fP G) (_hT : Tab zmTab s.mem sP 256)
+ (hwf : pR fP ∈ s.wr) (_hw : pR sP ∈ s.wr) :
+ WP isa yscale s fun s' => PolyIs s'.mem fP (G.map (· * 8347681)) ∧ BInvY fP s s' := by
+ refine WP.seq ?_
+ rw [WP.block_append_iff, WP.block_append_iff]
+ refine WP.mono (Q := fun (w : State) => w.gpr .rdx = fP ∧ GOnly [.rdx] s w ∧ w.ymmHi = s.ymmHi)
+ (by vrund [hdi]; exact ⟨by gonlyd, rfl⟩) fun w ⟨hdx, og, hy⟩ => ?_
+ refine WP.mono (yconst_ok .xmm13 16382 w) fun w1 ⟨l1, k1, m1, x1, o1⟩ => ?_
+ refine WP.mono (ylanes (by decide) (P := fun l t => t.xmm .xmm12 = w1.lane .xmm13 l)
+ fun l _ => mov12_ok (w1.proj l)) fun w2 ⟨l2, o2⟩ => ?_
+ have cw : YConsts w := ylanes_gpr (s := s) (og.lane hy) (YOnly.refl [] s) hc (by decide) (by decide)
+ have cw2 : YConsts w2 := yonly_yconsts o2 (fun l hl =>
+ ⟨by rw [State.proj_xmm, o1 _ (by decide) l hl]; exact (cw l hl).q,
+ by rw [State.proj_xmm, o1 _ (by decide) l hl]; exact (cw l hl).qinv⟩) (by decide) (by decide)
+ have z13 : ∀ l < 2, w2.lane .xmm13 l = ofDwords 16382#32 16382#32 16382#32 16382#32 := fun l hl => by
+ rw [o2.lane _ (by decide) l hl, l1 l hl]; rfl
+ have z12 : ∀ l < 2, w2.lane .xmm12 l = ofDwords 16382#32 16382#32 16382#32 16382#32 := fun l hl => by
+ have e : w2.lane .xmm12 l = _ := l2 l hl
+ rw [e, l1 l hl]; rfl
+ have dx2 : w2.gpr .rdx = fP := by rw [o2.gpr, k1.gpr (by decide), hdx]
+ have mw2 : w2.mem = s.mem := by rw [o2.mem, m1, og.mem]
+ refine WP.mono (wp_rcxLoopY (N := 32) (by decide) (by decide)
+ (fun i u => YScaled u.mem fP G i ∧ u.gpr .rdx = coeffAddr fP (8 * i) ∧ YConsts u ∧
+ (∀ l < 2, u.lane .xmm13 l = w2.lane .xmm13 l) ∧ (∀ l < 2, u.lane .xmm12 l = w2.lane .xmm12 l) ∧
+ Keep [.rcx, .rdx] w2 u ∧ Frame [pR fP] w2.mem u.mem ∧ u.mxcsr = w2.mxcsr)
+ (fun u o hu _ => ⟨fun k hk => by
+ rw [o.mem, mw2, ifn (by omega)]; exact polyIs_toNat hS (by rw [n_eq]; exact hk),
+ by rw [o.keep.gpr (by decide), dx2, Nat.mul_zero, coeffAddr, Nat.mul_zero, add_ofNat_zero],
+ ylanes_gpr (s := w2) (o.lane hu) (YOnly.refl [] w2) cw2 (by decide) (by decide),
+ fun l _ => o.lane hu _ l, fun l _ => o.lane hu _ l, o.keep.mono (by simp),
+ by rw [o.mem]; exact Frame.refl _ _, o.mxcsr⟩)
+ (fun i hi u ⟨hS', hdx', hc', hz', hzo', hk', hf', hx'⟩ => WP.mono (yscale_step hi hc'
+ (fun l hl => by rw [hz' l hl, z13 l hl]; exact scale_lanes.1)
+ (fun l hl => by rw [hz' l hl, hzo' l hl, z13 l hl, z12 l hl]; exact scale_lanes.2) hdx' hS'
+ (by rw [hk'.2.2, o2.wr, k1.2.2, og.keep.2.2]; exact hwf))
+ fun u' ⟨hS'', hdx'', hf'', hc'', hz'', hzo'', hk'', hcx, hzf, hx''⟩ =>
+ ⟨⟨hS'', hdx'', hc'', fun l hl => by rw [hz'' l hl, hz' l hl], fun l hl => by rw [hzo'' l hl, hzo' l hl],
+ (hk'.trans hk'').mono (by simp), hf'.trans hf'', by rw [hx'', hx']⟩, hcx, hzf⟩))
+ fun u ⟨hS', _, hc', _, _, hk', hf', hx'⟩ => ?_
+ have kw2 : Keep [.rdx, .rax] s w2 :=
+ ((og.keep.trans k1).trans (⟨fun r _ => by rw [o2.gpr], o2.rd, o2.wr⟩ : Keep [] w1 w2)).mono (by simp)
+ refine ⟨polyIs_of_toNat fun k hk => ?_, ⟨(kw2.trans hk').mono (by simp), by rw [← mw2]; exact hf', hc',
+ by rw [hx', o2.mxcsr, x1, og.mxcsr]⟩⟩
+ rw [n_eq] at hk
+ rw [hS' k hk, ifp (by omega), map_mul_get _ _ (by rw [n_eq]; exact hk)]
+
+/-! ## The functions -/
+
+/-- The code in `withMxcsr`, from its state `s1`: the prologue, then the
+layers `l`, which leave `G`. -/
+theorem ynttBody_ok {t : Poly → Poly} {s s1 : State} (hs : (inPlaceK t).pre s) {l : Prog isa} {G : Poly}
+ (k1 : Keep [.rax, .r11] s s1) (f1 : Frame [mxR (s.gpr .rsi)] s.mem s1.mem)
+ (hl : ∀ s2, LIY (s.gpr .rdi) (s.gpr .rsi) s2 (polyAt s.mem (s.gpr .rdi)) s2 → s2.gpr .rdi = s.gpr .rdi →
+ s2.gpr .rsi = s.gpr .rsi → pR (s.gpr .rdi) ∈ s2.wr → pR (s.gpr .rsi) ∈ s2.wr →
+ WP isa l s2 fun s3 => PolyIs s3.mem (s.gpr .rdi) G ∧ Frame [pR (s.gpr .rdi)] s2.mem s3.mem) :
+ WP isa (.seq (.block ypro) l) s1 fun s' =>
+ PolyIs s'.mem (s.gpr .rdi) G ∧ Frame [pR (s.gpr .rdi), pR (s.gpr .rsi)] s.mem s'.mem := by
+ have hw : pR (s.gpr .rsi) ∈ s.wr := by rw [hs.2.1]; simp
+ have hwf : pR (s.gpr .rdi) ∈ s.wr := by rw [hs.2.1]; simp
+ have hd : (pR (s.gpr .rdi)).Disjoint (pR (s.gpr .rsi)) := hs.2.2.1
+ have hdi1 : s1.gpr .rdi = s.gpr .rdi := k1.gpr (by decide)
+ have hsi1 : s1.gpr .rsi = s.gpr .rsi := k1.gpr (by decide)
+ have hF1 : PolyIs s1.mem (s.gpr .rdi) (polyAt s.mem (s.gpr .rdi)) :=
+ polyIs_frame f1 (fun r hr => by rw [List.mem_singleton.mp hr]; exact hd.sub_right (mx_sub' _))
+ ⟨hs.2.2.2.2.2, rfl⟩
+ refine WP.seq (WP.mono (ypro_ok hsi1 (by rw [k1.2.2]; exact hw)) fun s2 ⟨hT, hc, hf2, k2, _⟩ => ?_)
+ have hF2 : PolyIs s2.mem (s.gpr .rdi) (polyAt s.mem (s.gpr .rdi)) :=
+ polyIs_frame hf2 (fun r hr => by rw [List.mem_singleton.mp hr]; exact hd) hF1
+ refine WP.mono (hl s2 ⟨hF2, hT, hc, Keep.refl _ _, Frame.refl _ _⟩
+ (by rw [k2.gpr (by decide), hdi1]) (by rw [k2.gpr (by decide), hsi1])
+ (by rw [k2.2.2, k1.2.2]; exact hwf) (by rw [k2.2.2, k1.2.2]; exact hw)) fun s3 ⟨hP, hf3⟩ => ⟨hP, ?_⟩
+ refine (frame_fs f1 ?_).trans ((frame_fs hf2 ?_).trans (frame_fs hf3 ?_)) <;>
+ intro r hr <;> simp only [List.mem_singleton] at hr <;> subst hr
+ exacts [.inr (mx_sub' _), .inr fun _ h => h, .inl fun _ h => h]
+
+/-- `withMxcsr` around the body, and the ABI. -/
+theorem ymx_correct {t : Poly → Poly} {l : Prog isa} (s : State) (hs : (inPlaceK t).pre s)
+ (hk : writesOnly [.rax, .rcx, .rdx, .r8, .r9] (.seq (.block ypro) l) = true)
+ (hctl : ctlOk (VG.Impl.MlKem.X86_64.withMxcsr .rsi 768 (.seq (.block ypro) l)) = true)
+ (hk' : writesOnly [.rax, .rcx, .rdx, .r8, .r9, .r11]
+ (VG.Impl.MlKem.X86_64.withMxcsr .rsi 768 (.seq (.block ypro) l)) = true)
+ (hl : ∀ s1, Keep [.rax, .r11] s s1 → Frame [mxR (s.gpr .rsi)] s.mem s1.mem →
+ WP isa (.seq (.block ypro) l) s1 fun s' => PolyIs s'.mem (s.gpr .rdi) (t (polyAt s.mem (s.gpr .rdi))) ∧
+ Frame [pR (s.gpr .rdi), pR (s.gpr .rsi)] s.mem s'.mem) :
+ ∃ tr s', Exec isa (VG.Impl.MlKem.X86_64.withMxcsr .rsi 768 (.seq (.block ypro) l)) s tr s' ∧
+ abiPreserved s s' ∧ (inPlaceK t).post s s' := by
+ have hw : pR (s.gpr .rsi) ∈ s.wr := by rw [hs.2.1]; simp
+ have hd : (pR (s.gpr .rdi)).Disjoint (pR (s.gpr .rsi)) := hs.2.2.1
+ have hW := withMxcsr_ok (c := .seq (.block ypro) l) (by decide) [.rax, .rcx, .rdx, .r8, .r9] (by decide) rfl hw
+ hk (hl)
+ obtain ⟨tr, s', he, ⟨s2, ⟨hP, hf⟩, hf', -⟩, hk⟩ := WP.keep [.rax, .rcx, .rdx, .r8, .r9, .r11] hW hk'
+ refine ⟨tr, s', he, abiPreserved_of_ctl hctl he (gprPreserved_of hk (by decide)
+ (hf.trans (hf'.sub fun r hr => ⟨_, List.mem_cons_of_mem _ (List.mem_singleton_self _), ?_⟩))
+ (by simpa using ⟨hs.2.2.2.1, hs.2.2.2.2.1⟩)), ?_⟩
+ · rw [List.mem_singleton.mp hr]; exact mx_sub' _
+ · exact polyIs_frame hf' (fun r hr => by
+ rw [List.mem_singleton.mp hr]; exact hd.sub_right (mx_sub' _)) hP
+
+theorem nttY_correct (s : State) (hs : (inPlaceK ntt).pre s) :
+ ∃ t s', Exec isa nttAvx2 s t s' ∧ abiPreserved s s' ∧ (inPlaceK ntt).post s s' := by
+ have hd : (pR (s.gpr .rsi)).Disjoint (pR (s.gpr .rdi)) := hs.2.2.1.symm
+ refine ymx_correct s hs (by decide +kernel) (by decide +kernel) (by decide +kernel) fun s1 k1 f1 =>
+ WP.mono (ynttBody_ok hs k1 f1 (G := nttLens.foldl nttLayer (polyAt s.mem (s.gpr .rdi)))
+ fun s2 hI hdi hsi hwf hw => ?_) fun s' ⟨hP, hf⟩ => ⟨by rw [ntt_eq_layers]; exact hP, hf⟩
+ simp only [nttLens, List.foldl_cons, List.foldl_nil]
+ refine LIY.seq hdi hsi hwf hw hd (yfwdLay_ok hd 128 1 (by decide) (by decide)) ?_ hI
+ refine fun _ hI => LIY.seq hdi hsi hwf hw hd (yfwdLay_ok hd 64 2 (by decide) (by decide)) ?_ hI
+ refine fun _ hI => LIY.seq hdi hsi hwf hw hd (yfwdLay_ok hd 32 4 (by decide) (by decide)) ?_ hI
+ refine fun _ hI => LIY.seq hdi hsi hwf hw hd (yfwdLay_ok hd 16 8 (by decide) (by decide)) ?_ hI
+ refine fun _ hI => LIY.seq hdi hsi hwf hw hd (yfwdLay_ok hd 8 16 (by decide) (by decide)) ?_ hI
+ refine fun _ hI => LIY.seq hdi hsi hwf hw hd (yfwdLay4_ok hd) ?_ hI
+ refine fun _ hI => LIY.seq hdi hsi hwf hw hd (yfwdLay2_ok hd) ?_ hI
+ exact fun _ hI => LIY.seq hdi hsi hwf hw hd (yfwdLay1_ok hd) (fun _ hI => hI.epi) hI
+
+theorem nttInvY_correct (s : State) (hs : (inPlaceK nttInv).pre s) :
+ ∃ t s', Exec isa nttInvAvx2 s t s' ∧ abiPreserved s s' ∧ (inPlaceK nttInv).post s s' := by
+ have hd : (pR (s.gpr .rsi)).Disjoint (pR (s.gpr .rdi)) := hs.2.2.1.symm
+ refine ymx_correct s hs (by decide +kernel) (by decide +kernel) (by decide +kernel) fun s1 k1 f1 =>
+ WP.mono (ynttBody_ok hs k1 f1
+ (G := (nttInvLens.foldl nttInvLayer (polyAt s.mem (s.gpr .rdi))).map (· * 8347681))
+ fun s2 hI hdi hsi hwf hw => ?_) fun s' ⟨hP, hf⟩ => ⟨by rw [nttInv_eq_layers]; exact hP, hf⟩
+ simp only [nttInvLens, List.foldl_cons, List.foldl_nil]
+ refine LIY.seq hdi hsi hwf hw hd (yinvLay1_ok hd) ?_ hI
+ refine fun _ hI => LIY.seq hdi hsi hwf hw hd (yinvLay2_ok hd) ?_ hI
+ refine fun _ hI => LIY.seq hdi hsi hwf hw hd (yinvLay4_ok hd) ?_ hI
+ refine fun _ hI => LIY.seq hdi hsi hwf hw hd (yinvLay_ok hd 8 31 (by decide) (by decide)) ?_ hI
+ refine fun _ hI => LIY.seq hdi hsi hwf hw hd (yinvLay_ok hd 16 15 (by decide) (by decide)) ?_ hI
+ refine fun _ hI => LIY.seq hdi hsi hwf hw hd (yinvLay_ok hd 32 7 (by decide) (by decide)) ?_ hI
+ refine fun _ hI => LIY.seq hdi hsi hwf hw hd (yinvLay_ok hd 64 3 (by decide) (by decide)) ?_ hI
+ refine fun _ hI => LIY.seq hdi hsi hwf hw hd (yinvLay_ok hd 128 1 (by decide) (by decide)) ?_ hI
+ exact fun _ hI => LIY.seq hdi hsi hwf hw hd (yscale_ok hd) (fun _ hI => hI.epi) hI
+
+theorem nttY_ct : ConstantTime isa (inPlaceK ntt).pre (inPlaceK ntt).pub nttAvx2 :=
+ VG.Taint.constantTime (A := taint) (X86_64.Taint.ofRegs [.rdi, .rsi, .rsp]) inPlace_agree (by taint_decide)
+
+theorem nttInvY_ct : ConstantTime isa (inPlaceK nttInv).pre (inPlaceK nttInv).pub nttInvAvx2 :=
+ VG.Taint.constantTime (A := taint) (X86_64.Taint.ofRegs [.rdi, .rsi, .rsp]) inPlace_agree (by taint_decide)
+
+theorem nttY_verified : Verified X86_64.target nttAvx2 (Spec.MlDsa.nttContract X86_64.abi) :=
+ Verified.of_correct nttY_correct nttY_ct (by
+ mldsa_implies [Spec.MlDsa.nttContract, Spec.MlDsa.inPlaceContract, Spec.MlDsa.inPlaceSig, inPlaceK,
+ X86_64.abi, X86_64.argRegs] [inPlaceSat] using inPlaceSat)
+
+theorem nttInvY_verified : Verified X86_64.target nttInvAvx2 (Spec.MlDsa.nttInvContract X86_64.abi) :=
+ Verified.of_correct nttInvY_correct nttInvY_ct (by
+ mldsa_implies [Spec.MlDsa.nttInvContract, Spec.MlDsa.inPlaceContract, Spec.MlDsa.inPlaceSig, inPlaceK,
+ X86_64.abi, X86_64.argRegs] [inPlaceSat] using inPlaceSat)
+
+end VG.Proof.MlDsa.X86_64.Arith
diff --git a/lean/VerifiedGarbage/Variants/MlDsaArith/X86_64/Avx2.lean b/lean/VerifiedGarbage/Variants/MlDsaArith/X86_64/Avx2.lean
new file mode 100644
index 000000000..5b74ee5fe
--- /dev/null
+++ b/lean/VerifiedGarbage/Variants/MlDsaArith/X86_64/Avx2.lean
@@ -0,0 +1,18 @@
+import VerifiedGarbage.Proof.MlDsa.X86_64.Arith.BackendAvx2
+
+/-!
+# ML-DSA's polynomial arithmetic on x86-64: AVX2
+
+A variant of `MlDsaArith` on x86-64 (see `TCB/Emit.lean`):
+`vg_mldsa_ntt_avx2`, `vg_mldsa_inv_ntt_avx2`,
+`vg_mldsa_multiply_ntt_avx2`, `vg_mldsa_multiply_add_ntt_avx2`,
+`vg_mldsa_add_avx2` and `vg_mldsa_sub_avx2`, on eight coefficients at a time
+in AVX2 registers, which need AVX and AVX2; key generation, signing and
+verification calling them need them too.
+-/
+
+namespace VG.Variants.MlDsaArith.X86_64.Avx2
+
+def variant : Proof.MlDsa.X86_64.ArithImpl := .avx2
+
+end VG.Variants.MlDsaArith.X86_64.Avx2
diff --git a/src/asm/x86_64/mldsa.rs b/src/asm/x86_64/mldsa.rs
index 01e804f36..541b9d25a 100644
--- a/src/asm/x86_64/mldsa.rs
+++ b/src/asm/x86_64/mldsa.rs
@@ -1754,6 +1754,1688 @@ pub(crate) unsafe extern "sysv64" fn vg_mldsa_sub(f: *mut [u32; 256], g: *const
)
}
+/// The CPU features `vg_mldsa_ntt_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA_NTT_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// The ML-DSA number-theoretic transform, `NTT` (FIPS 204 Algorithm 41), of the polynomial `*f` (256 coefficients less than `q` = 8380417), in place.
+///
+/// Contract: `VG.Spec.MlDsa.nttContract`. Constant time: only the pointers may affect timing, not the data.
+///
+/// The function computes on eight coefficients at a time in AVX2 registers, with a table of the 256 zetas that it stores in `scratch`. It sets MXCSR to `0x1FBF` around its multiplications (Intel's mitigation of MXCSR-configuration-dependent timing) and loads the caller's MXCSR back before returning.
+///
+/// # Safety
+///
+/// * `f` must be valid for reads and writes of 1024 bytes.
+/// * `scratch` must be valid for reads and writes of 1024 bytes.
+/// * Each of the 256 `u32`s of `f` must be less than `q` = 8380417.
+/// * `scratch` is working space: on return it may hold intermediate values, which the caller must destroy (FIPS 204 §3.6.3).
+/// * `f` and `scratch` must not overlap each other (distinct Rust objects never do).
+/// * Neither `f` nor `scratch` may overlap the return address on the stack, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa_ntt_avx2(f: *mut [u32; 256], scratch: *mut [u64; 128]) {
+ core::arch::naked_asm!(
+ "stmxcsr DWORD PTR [rsi+768]",
+ "mov r11d, DWORD PTR [rsi+768]",
+ "and r11d, 65535",
+ "mov eax, 8127",
+ "mov DWORD PTR [rsi+772], eax",
+ "ldmxcsr DWORD PTR [rsi+772]",
+ "lfence",
+ "movabs r9, 111012023893504",
+ "mov QWORD PTR [rsi], r9",
+ "movabs r9, 33764919763013891",
+ "mov QWORD PTR [rsi+8], r9",
+ "movabs r9, 32652304184483396",
+ "mov QWORD PTR [rsi+16], r9",
+ "movabs r9, 2003464812134697",
+ "mov QWORD PTR [rsi+24], r9",
+ "movabs r9, 10107995079564843",
+ "mov QWORD PTR [rsi+32], r9",
+ "movabs r9, 27008953388524718",
+ "mov QWORD PTR [rsi+40], r9",
+ "movabs r9, 23603259066260085",
+ "mov QWORD PTR [rsi+48], r9",
+ "movabs r9, 11510954738022985",
+ "mov QWORD PTR [rsi+56], r9",
+ "movabs r9, 4398527550166616",
+ "mov QWORD PTR [rsi+64], r9",
+ "movabs r9, 15401443493111205",
+ "mov QWORD PTR [rsi+72], r9",
+ "movabs r9, 31185040284548497",
+ "mov QWORD PTR [rsi+80], r9",
+ "movabs r9, 26937467947448680",
+ "mov QWORD PTR [rsi+88], r9",
+ "movabs r9, 19416172761943511",
+ "mov QWORD PTR [rsi+96], r9",
+ "movabs r9, 21916122901808376",
+ "mov QWORD PTR [rsi+104], r9",
+ "movabs r9, 35910200088776757",
+ "mov QWORD PTR [rsi+112], r9",
+ "movabs r9, 1202612321726977",
+ "mov QWORD PTR [rsi+120], r9",
+ "movabs r9, 411354790447719",
+ "mov QWORD PTR [rsi+128], r9",
+ "movabs r9, 15163111458665677",
+ "mov QWORD PTR [rsi+136], r9",
+ "movabs r9, 20565458766169348",
+ "mov QWORD PTR [rsi+144], r9",
+ "movabs r9, 16816682460325845",
+ "mov QWORD PTR [rsi+152], r9",
+ "movabs r9, 22920956268049798",
+ "mov QWORD PTR [rsi+160], r9",
+ "movabs r9, 23677166863944342",
+ "mov QWORD PTR [rsi+168], r9",
+ "movabs r9, 34703121006855168",
+ "mov QWORD PTR [rsi+176], r9",
+ "movabs r9, 33677345376425628",
+ "mov QWORD PTR [rsi+184], r9",
+ "movabs r9, 28933472397947454",
+ "mov QWORD PTR [rsi+192], r9",
+ "movabs r9, 19579390106369566",
+ "mov QWORD PTR [rsi+200], r9",
+ "movabs r9, 26799599498134591",
+ "mov QWORD PTR [rsi+208], r9",
+ "movabs r9, 15889643835192413",
+ "mov QWORD PTR [rsi+216], r9",
+ "movabs r9, 2282148053410728",
+ "mov QWORD PTR [rsi+224], r9",
+ "movabs r9, 16668952760323958",
+ "mov QWORD PTR [rsi+232], r9",
+ "movabs r9, 25011900965946676",
+ "mov QWORD PTR [rsi+240], r9",
+ "movabs r9, 23977247637478740",
+ "mov QWORD PTR [rsi+248], r9",
+ "movabs r9, 29427887555995366",
+ "mov QWORD PTR [rsi+256], r9",
+ "movabs r9, 22931526182748624",
+ "mov QWORD PTR [rsi+264], r9",
+ "movabs r9, 14929091579459166",
+ "mov QWORD PTR [rsi+272], r9",
+ "movabs r9, 29185144592086471",
+ "mov QWORD PTR [rsi+280], r9",
+ "movabs r9, 8329290213797750",
+ "mov QWORD PTR [rsi+288], r9",
+ "movabs r9, 31697782066745459",
+ "mov QWORD PTR [rsi+296], r9",
+ "movabs r9, 22432987854353025",
+ "mov QWORD PTR [rsi+304], r9",
+ "movabs r9, 545125843890401",
+ "mov QWORD PTR [rsi+312], r9",
+ "movabs r9, 31769864501989618",
+ "mov QWORD PTR [rsi+320], r9",
+ "movabs r9, 11662103226140216",
+ "mov QWORD PTR [rsi+328], r9",
+ "movabs r9, 20130185304250276",
+ "mov QWORD PTR [rsi+336], r9",
+ "movabs r9, 25354781094156910",
+ "mov QWORD PTR [rsi+344], r9",
+ "movabs r9, 30717142252233347",
+ "mov QWORD PTR [rsi+352], r9",
+ "movabs r9, 30375073877558844",
+ "mov QWORD PTR [rsi+360], r9",
+ "movabs r9, 5794237307816926",
+ "mov QWORD PTR [rsi+368], r9",
+ "movabs r9, 29849966874477923",
+ "mov QWORD PTR [rsi+376], r9",
+ "movabs r9, 1137925820308458",
+ "mov QWORD PTR [rsi+384], r9",
+ "movabs r9, 13305774323778583",
+ "mov QWORD PTR [rsi+392], r9",
+ "movabs r9, 31268732009491712",
+ "mov QWORD PTR [rsi+400], r9",
+ "movabs r9, 17002134848261444",
+ "mov QWORD PTR [rsi+408], r9",
+ "movabs r9, 35956774717033419",
+ "mov QWORD PTR [rsi+416], r9",
+ "movabs r9, 22036141462600008",
+ "mov QWORD PTR [rsi+424], r9",
+ "movabs r9, 35087477629023596",
+ "mov QWORD PTR [rsi+432], r9",
+ "movabs r9, 30337763489061025",
+ "mov QWORD PTR [rsi+440], r9",
+ "movabs r9, 20732429908239468",
+ "mov QWORD PTR [rsi+448], r9",
+ "movabs r9, 28041905903253186",
+ "mov QWORD PTR [rsi+456], r9",
+ "movabs r9, 35231517950811284",
+ "mov QWORD PTR [rsi+464], r9",
+ "movabs r9, 5760968484459269",
+ "mov QWORD PTR [rsi+472], r9",
+ "movabs r9, 29186403016613413",
+ "mov QWORD PTR [rsi+480], r9",
+ "movabs r9, 29809972144732485",
+ "mov QWORD PTR [rsi+488], r9",
+ "movabs r9, 19324591173389987",
+ "mov QWORD PTR [rsi+496], r9",
+ "movabs r9, 16492506917666904",
+ "mov QWORD PTR [rsi+504], r9",
+ "movabs r9, 14635985826474643",
+ "mov QWORD PTR [rsi+512], r9",
+ "movabs r9, 16398082059229396",
+ "mov QWORD PTR [rsi+520], r9",
+ "movabs r9, 9638297459285875",
+ "mov QWORD PTR [rsi+528], r9",
+ "movabs r9, 20692959164533664",
+ "mov QWORD PTR [rsi+536], r9",
+ "movabs r9, 10455835889373941",
+ "mov QWORD PTR [rsi+544], r9",
+ "movabs r9, 15088997507073265",
+ "mov QWORD PTR [rsi+552], r9",
+ "movabs r9, 19847271512942753",
+ "mov QWORD PTR [rsi+560], r9",
+ "movabs r9, 22278162875259735",
+ "mov QWORD PTR [rsi+568], r9",
+ "movabs r9, 7984765110959710",
+ "mov QWORD PTR [rsi+576], r9",
+ "movabs r9, 3517724245221606",
+ "mov QWORD PTR [rsi+584], r9",
+ "movabs r9, 29065087369580419",
+ "mov QWORD PTR [rsi+592], r9",
+ "movabs r9, 33749496538019589",
+ "mov QWORD PTR [rsi+600], r9",
+ "movabs r9, 22582830675910690",
+ "mov QWORD PTR [rsi+608], r9",
+ "movabs r9, 13774157688799364",
+ "mov QWORD PTR [rsi+616], r9",
+ "movabs r9, 33738338209470846",
+ "mov QWORD PTR [rsi+624], r9",
+ "movabs r9, 20549610337740179",
+ "mov QWORD PTR [rsi+632], r9",
+ "movabs r9, 1232604074686745",
+ "mov QWORD PTR [rsi+640], r9",
+ "movabs r9, 17645078572608834",
+ "mov QWORD PTR [rsi+648], r9",
+ "movabs r9, 21638646536106727",
+ "mov QWORD PTR [rsi+656], r9",
+ "movabs r9, 872067341384903",
+ "mov QWORD PTR [rsi+664], r9",
+ "movabs r9, 11559822875647717",
+ "mov QWORD PTR [rsi+672], r9",
+ "movabs r9, 5433172289935931",
+ "mov QWORD PTR [rsi+680], r9",
+ "movabs r9, 5358487101890844",
+ "mov QWORD PTR [rsi+688], r9",
+ "movabs r9, 6854656137752657",
+ "mov QWORD PTR [rsi+696], r9",
+ "movabs r9, 5370830838457625",
+ "mov QWORD PTR [rsi+704], r9",
+ "movabs r9, 20753904747165841",
+ "mov QWORD PTR [rsi+712], r9",
+ "movabs r9, 8027804982718602",
+ "mov QWORD PTR [rsi+720], r9",
+ "movabs r9, 31479735164668747",
+ "mov QWORD PTR [rsi+728], r9",
+ "movabs r9, 5314055668205759",
+ "mov QWORD PTR [rsi+736], r9",
+ "movabs r9, 29850847345983039",
+ "mov QWORD PTR [rsi+744], r9",
+ "movabs r9, 5636951310400997",
+ "mov QWORD PTR [rsi+752], r9",
+ "movabs r9, 27564133741392515",
+ "mov QWORD PTR [rsi+760], r9",
+ "movabs r9, 8233800205883732",
+ "mov QWORD PTR [rsi+768], r9",
+ "movabs r9, 30088883024233849",
+ "mov QWORD PTR [rsi+776], r9",
+ "movabs r9, 3338009929245701",
+ "mov QWORD PTR [rsi+784], r9",
+ "movabs r9, 14628791756398056",
+ "mov QWORD PTR [rsi+792], r9",
+ "movabs r9, 23830870862829877",
+ "mov QWORD PTR [rsi+800], r9",
+ "movabs r9, 28061014216302585",
+ "mov QWORD PTR [rsi+808], r9",
+ "movabs r9, 19997999096164636",
+ "mov QWORD PTR [rsi+816], r9",
+ "movabs r9, 19771555530215640",
+ "mov QWORD PTR [rsi+824], r9",
+ "movabs r9, 10447056982320729",
+ "mov QWORD PTR [rsi+832], r9",
+ "movabs r9, 35286145636332471",
+ "mov QWORD PTR [rsi+840], r9",
+ "movabs r9, 14470225858518424",
+ "mov QWORD PTR [rsi+848], r9",
+ "movabs r9, 30807937853347003",
+ "mov QWORD PTR [rsi+856], r9",
+ "movabs r9, 699409659546815",
+ "mov QWORD PTR [rsi+864], r9",
+ "movabs r9, 12945035726727688",
+ "mov QWORD PTR [rsi+872], r9",
+ "movabs r9, 7098008983067813",
+ "mov QWORD PTR [rsi+880], r9",
+ "movabs r9, 28266511219523944",
+ "mov QWORD PTR [rsi+888], r9",
+ "movabs r9, 15135022374814013",
+ "mov QWORD PTR [rsi+896], r9",
+ "movabs r9, 1158610381635861",
+ "mov QWORD PTR [rsi+904], r9",
+ "movabs r9, 31802227079365879",
+ "mov QWORD PTR [rsi+912], r9",
+ "movabs r9, 2027559572878823",
+ "mov QWORD PTR [rsi+920], r9",
+ "movabs r9, 7402805639339334",
+ "mov QWORD PTR [rsi+928], r9",
+ "movabs r9, 8205002449640623",
+ "mov QWORD PTR [rsi+936], r9",
+ "movabs r9, 31250542829661849",
+ "mov QWORD PTR [rsi+944], r9",
+ "movabs r9, 19527171898598875",
+ "mov QWORD PTR [rsi+952], r9",
+ "movabs r9, 26390134497937253",
+ "mov QWORD PTR [rsi+960], r9",
+ "movabs r9, 26173917256840158",
+ "mov QWORD PTR [rsi+968], r9",
+ "movabs r9, 31797902045269139",
+ "mov QWORD PTR [rsi+976], r9",
+ "movabs r9, 20765007236602922",
+ "mov QWORD PTR [rsi+984], r9",
+ "movabs r9, 16834811519265361",
+ "mov QWORD PTR [rsi+992], r9",
+ "movabs r9, 30142973844857679",
+ "mov QWORD PTR [rsi+1000], r9",
+ "movabs r9, 6014775284471242",
+ "mov QWORD PTR [rsi+1008], r9",
+ "movabs r9, 8490214048855735",
+ "mov QWORD PTR [rsi+1016], r9",
+ "mov eax, 8380417",
+ "vmovq xmm15, rax",
+ "vpbroadcastd ymm15, xmm15",
+ "mov eax, -58728449",
+ "vmovq xmm14, rax",
+ "vpbroadcastd ymm14, xmm14",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 4",
+ "mov eax, 1",
+ "20:",
+ "vbroadcasti128 ymm13, XMMWORD PTR [r8]",
+ "vpshufd ymm13, ymm13, 0",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, 4",
+ "mov ecx, 16",
+ "21:",
+ "vmovdqu ymm0, YMMWORD PTR [rdx]",
+ "vmovdqu ymm1, YMMWORD PTR [rdx+512]",
+ "vpshufd ymm4, ymm1, 245",
+ "vpmuludq ymm1, ymm1, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm1, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm1, ymm1, ymm2",
+ "vpsrlq ymm1, ymm1, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm1, ymm1, ymm4",
+ "vpsubd ymm1, ymm1, ymm15",
+ "vpsrad ymm2, ymm1, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm1, ymm1, ymm2",
+ "vmovdqa ymm3, ymm0",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpsubd ymm3, ymm3, ymm1",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqu YMMWORD PTR [rdx], ymm0",
+ "vmovdqu YMMWORD PTR [rdx+512], ymm3",
+ "add rdx, 32",
+ "sub rcx, 1",
+ "jne 21b",
+ "add rdx, 512",
+ "sub rax, 1",
+ "jne 20b",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 8",
+ "mov eax, 2",
+ "22:",
+ "vbroadcasti128 ymm13, XMMWORD PTR [r8]",
+ "vpshufd ymm13, ymm13, 0",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, 4",
+ "mov ecx, 8",
+ "23:",
+ "vmovdqu ymm0, YMMWORD PTR [rdx]",
+ "vmovdqu ymm1, YMMWORD PTR [rdx+256]",
+ "vpshufd ymm4, ymm1, 245",
+ "vpmuludq ymm1, ymm1, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm1, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm1, ymm1, ymm2",
+ "vpsrlq ymm1, ymm1, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm1, ymm1, ymm4",
+ "vpsubd ymm1, ymm1, ymm15",
+ "vpsrad ymm2, ymm1, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm1, ymm1, ymm2",
+ "vmovdqa ymm3, ymm0",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpsubd ymm3, ymm3, ymm1",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqu YMMWORD PTR [rdx], ymm0",
+ "vmovdqu YMMWORD PTR [rdx+256], ymm3",
+ "add rdx, 32",
+ "sub rcx, 1",
+ "jne 23b",
+ "add rdx, 256",
+ "sub rax, 1",
+ "jne 22b",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 16",
+ "mov eax, 4",
+ "24:",
+ "vbroadcasti128 ymm13, XMMWORD PTR [r8]",
+ "vpshufd ymm13, ymm13, 0",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, 4",
+ "mov ecx, 4",
+ "25:",
+ "vmovdqu ymm0, YMMWORD PTR [rdx]",
+ "vmovdqu ymm1, YMMWORD PTR [rdx+128]",
+ "vpshufd ymm4, ymm1, 245",
+ "vpmuludq ymm1, ymm1, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm1, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm1, ymm1, ymm2",
+ "vpsrlq ymm1, ymm1, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm1, ymm1, ymm4",
+ "vpsubd ymm1, ymm1, ymm15",
+ "vpsrad ymm2, ymm1, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm1, ymm1, ymm2",
+ "vmovdqa ymm3, ymm0",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpsubd ymm3, ymm3, ymm1",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqu YMMWORD PTR [rdx], ymm0",
+ "vmovdqu YMMWORD PTR [rdx+128], ymm3",
+ "add rdx, 32",
+ "sub rcx, 1",
+ "jne 25b",
+ "add rdx, 128",
+ "sub rax, 1",
+ "jne 24b",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 32",
+ "mov eax, 8",
+ "26:",
+ "vbroadcasti128 ymm13, XMMWORD PTR [r8]",
+ "vpshufd ymm13, ymm13, 0",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, 4",
+ "mov ecx, 2",
+ "27:",
+ "vmovdqu ymm0, YMMWORD PTR [rdx]",
+ "vmovdqu ymm1, YMMWORD PTR [rdx+64]",
+ "vpshufd ymm4, ymm1, 245",
+ "vpmuludq ymm1, ymm1, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm1, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm1, ymm1, ymm2",
+ "vpsrlq ymm1, ymm1, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm1, ymm1, ymm4",
+ "vpsubd ymm1, ymm1, ymm15",
+ "vpsrad ymm2, ymm1, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm1, ymm1, ymm2",
+ "vmovdqa ymm3, ymm0",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpsubd ymm3, ymm3, ymm1",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqu YMMWORD PTR [rdx], ymm0",
+ "vmovdqu YMMWORD PTR [rdx+64], ymm3",
+ "add rdx, 32",
+ "sub rcx, 1",
+ "jne 27b",
+ "add rdx, 64",
+ "sub rax, 1",
+ "jne 26b",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 64",
+ "mov eax, 16",
+ "28:",
+ "vbroadcasti128 ymm13, XMMWORD PTR [r8]",
+ "vpshufd ymm13, ymm13, 0",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, 4",
+ "mov ecx, 1",
+ "29:",
+ "vmovdqu ymm0, YMMWORD PTR [rdx]",
+ "vmovdqu ymm1, YMMWORD PTR [rdx+32]",
+ "vpshufd ymm4, ymm1, 245",
+ "vpmuludq ymm1, ymm1, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm1, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm1, ymm1, ymm2",
+ "vpsrlq ymm1, ymm1, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm1, ymm1, ymm4",
+ "vpsubd ymm1, ymm1, ymm15",
+ "vpsrad ymm2, ymm1, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm1, ymm1, ymm2",
+ "vmovdqa ymm3, ymm0",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpsubd ymm3, ymm3, ymm1",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqu YMMWORD PTR [rdx], ymm0",
+ "vmovdqu YMMWORD PTR [rdx+32], ymm3",
+ "add rdx, 32",
+ "sub rcx, 1",
+ "jne 29b",
+ "add rdx, 32",
+ "sub rax, 1",
+ "jne 28b",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 128",
+ "mov ecx, 16",
+ "210:",
+ "vmovdqu ymm4, YMMWORD PTR [rdx]",
+ "vmovdqu ymm5, YMMWORD PTR [rdx+32]",
+ "vbroadcasti128 ymm13, XMMWORD PTR [r8]",
+ "vpshufd ymm2, ymm13, 85",
+ "vpshufd ymm13, ymm13, 0",
+ "vpblendd ymm13, ymm13, ymm2, 240",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, 8",
+ "vperm2i128 ymm0, ymm4, ymm5, 32",
+ "vperm2i128 ymm1, ymm4, ymm5, 49",
+ "vpshufd ymm4, ymm1, 245",
+ "vpmuludq ymm1, ymm1, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm1, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm1, ymm1, ymm2",
+ "vpsrlq ymm1, ymm1, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm1, ymm1, ymm4",
+ "vpsubd ymm1, ymm1, ymm15",
+ "vpsrad ymm2, ymm1, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm1, ymm1, ymm2",
+ "vmovdqa ymm3, ymm0",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpsubd ymm3, ymm3, ymm1",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vperm2i128 ymm4, ymm0, ymm3, 32",
+ "vperm2i128 ymm5, ymm0, ymm3, 49",
+ "vmovdqu YMMWORD PTR [rdx], ymm4",
+ "vmovdqu YMMWORD PTR [rdx+32], ymm5",
+ "add rdx, 64",
+ "sub rcx, 1",
+ "jne 210b",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 256",
+ "mov ecx, 16",
+ "211:",
+ "vmovdqu ymm0, YMMWORD PTR [rdx]",
+ "vmovdqu ymm1, YMMWORD PTR [rdx+32]",
+ "vbroadcasti128 ymm13, XMMWORD PTR [r8]",
+ "vpshufd ymm2, ymm13, 245",
+ "vpshufd ymm13, ymm13, 160",
+ "vpblendd ymm13, ymm13, ymm2, 240",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, 16",
+ "vmovdqa ymm2, ymm0",
+ "vpunpcklqdq ymm0, ymm0, ymm1",
+ "vpunpckhqdq ymm2, ymm2, ymm1",
+ "vmovdqa ymm1, ymm2",
+ "vpshufd ymm4, ymm1, 245",
+ "vpmuludq ymm1, ymm1, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm1, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm1, ymm1, ymm2",
+ "vpsrlq ymm1, ymm1, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm1, ymm1, ymm4",
+ "vpsubd ymm1, ymm1, ymm15",
+ "vpsrad ymm2, ymm1, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm1, ymm1, ymm2",
+ "vmovdqa ymm3, ymm0",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpsubd ymm3, ymm3, ymm1",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqa ymm1, ymm0",
+ "vpunpcklqdq ymm0, ymm0, ymm3",
+ "vpunpckhqdq ymm1, ymm1, ymm3",
+ "vmovdqu YMMWORD PTR [rdx], ymm0",
+ "vmovdqu YMMWORD PTR [rdx+32], ymm1",
+ "add rdx, 64",
+ "sub rcx, 1",
+ "jne 211b",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 512",
+ "mov ecx, 16",
+ "212:",
+ "vmovdqu ymm0, YMMWORD PTR [rdx]",
+ "vmovdqu ymm2, YMMWORD PTR [rdx+32]",
+ "vmovdqu ymm13, YMMWORD PTR [r8]",
+ "vpermq ymm13, ymm13, 216",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, 32",
+ "vpshufd ymm0, ymm0, 216",
+ "vpshufd ymm2, ymm2, 216",
+ "vmovdqa ymm1, ymm0",
+ "vpunpcklqdq ymm0, ymm0, ymm2",
+ "vpunpckhqdq ymm1, ymm1, ymm2",
+ "vpshufd ymm4, ymm1, 245",
+ "vpmuludq ymm1, ymm1, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm1, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm1, ymm1, ymm2",
+ "vpsrlq ymm1, ymm1, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm1, ymm1, ymm4",
+ "vpsubd ymm1, ymm1, ymm15",
+ "vpsrad ymm2, ymm1, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm1, ymm1, ymm2",
+ "vmovdqa ymm3, ymm0",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpsubd ymm3, ymm3, ymm1",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqa ymm1, ymm0",
+ "vpunpckldq ymm0, ymm0, ymm3",
+ "vpunpckhdq ymm1, ymm1, ymm3",
+ "vmovdqu YMMWORD PTR [rdx], ymm0",
+ "vmovdqu YMMWORD PTR [rdx+32], ymm1",
+ "add rdx, 64",
+ "sub rcx, 1",
+ "jne 212b",
+ "vzeroupper",
+ "lfence",
+ "mov DWORD PTR [rsi+768], r11d",
+ "ldmxcsr DWORD PTR [rsi+768]",
+ "ret",
+ )
+}
+
+/// The CPU features `vg_mldsa_inv_ntt_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA_INV_NTT_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// The inverse of the ML-DSA number-theoretic transform, `NTT⁻¹` (FIPS 204 Algorithm 42), of `*f` (256 coefficients less than `q` = 8380417), in place.
+///
+/// Contract: `VG.Spec.MlDsa.nttInvContract`. Constant time: only the pointers may affect timing, not the data.
+///
+/// The function computes on eight coefficients at a time in AVX2 registers, with a table of the 256 zetas that it stores in `scratch`. It sets MXCSR to `0x1FBF` around its multiplications (Intel's mitigation of MXCSR-configuration-dependent timing) and loads the caller's MXCSR back before returning.
+///
+/// # Safety
+///
+/// * `f` must be valid for reads and writes of 1024 bytes.
+/// * `scratch` must be valid for reads and writes of 1024 bytes.
+/// * Each of the 256 `u32`s of `f` must be less than `q` = 8380417.
+/// * `scratch` is working space: on return it may hold intermediate values, which the caller must destroy (FIPS 204 §3.6.3).
+/// * `f` and `scratch` must not overlap each other (distinct Rust objects never do).
+/// * Neither `f` nor `scratch` may overlap the return address on the stack, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa_inv_ntt_avx2(f: *mut [u32; 256], scratch: *mut [u64; 128]) {
+ core::arch::naked_asm!(
+ "stmxcsr DWORD PTR [rsi+768]",
+ "mov r11d, DWORD PTR [rsi+768]",
+ "and r11d, 65535",
+ "mov eax, 8127",
+ "mov DWORD PTR [rsi+772], eax",
+ "ldmxcsr DWORD PTR [rsi+772]",
+ "lfence",
+ "movabs r9, 111012023893504",
+ "mov QWORD PTR [rsi], r9",
+ "movabs r9, 33764919763013891",
+ "mov QWORD PTR [rsi+8], r9",
+ "movabs r9, 32652304184483396",
+ "mov QWORD PTR [rsi+16], r9",
+ "movabs r9, 2003464812134697",
+ "mov QWORD PTR [rsi+24], r9",
+ "movabs r9, 10107995079564843",
+ "mov QWORD PTR [rsi+32], r9",
+ "movabs r9, 27008953388524718",
+ "mov QWORD PTR [rsi+40], r9",
+ "movabs r9, 23603259066260085",
+ "mov QWORD PTR [rsi+48], r9",
+ "movabs r9, 11510954738022985",
+ "mov QWORD PTR [rsi+56], r9",
+ "movabs r9, 4398527550166616",
+ "mov QWORD PTR [rsi+64], r9",
+ "movabs r9, 15401443493111205",
+ "mov QWORD PTR [rsi+72], r9",
+ "movabs r9, 31185040284548497",
+ "mov QWORD PTR [rsi+80], r9",
+ "movabs r9, 26937467947448680",
+ "mov QWORD PTR [rsi+88], r9",
+ "movabs r9, 19416172761943511",
+ "mov QWORD PTR [rsi+96], r9",
+ "movabs r9, 21916122901808376",
+ "mov QWORD PTR [rsi+104], r9",
+ "movabs r9, 35910200088776757",
+ "mov QWORD PTR [rsi+112], r9",
+ "movabs r9, 1202612321726977",
+ "mov QWORD PTR [rsi+120], r9",
+ "movabs r9, 411354790447719",
+ "mov QWORD PTR [rsi+128], r9",
+ "movabs r9, 15163111458665677",
+ "mov QWORD PTR [rsi+136], r9",
+ "movabs r9, 20565458766169348",
+ "mov QWORD PTR [rsi+144], r9",
+ "movabs r9, 16816682460325845",
+ "mov QWORD PTR [rsi+152], r9",
+ "movabs r9, 22920956268049798",
+ "mov QWORD PTR [rsi+160], r9",
+ "movabs r9, 23677166863944342",
+ "mov QWORD PTR [rsi+168], r9",
+ "movabs r9, 34703121006855168",
+ "mov QWORD PTR [rsi+176], r9",
+ "movabs r9, 33677345376425628",
+ "mov QWORD PTR [rsi+184], r9",
+ "movabs r9, 28933472397947454",
+ "mov QWORD PTR [rsi+192], r9",
+ "movabs r9, 19579390106369566",
+ "mov QWORD PTR [rsi+200], r9",
+ "movabs r9, 26799599498134591",
+ "mov QWORD PTR [rsi+208], r9",
+ "movabs r9, 15889643835192413",
+ "mov QWORD PTR [rsi+216], r9",
+ "movabs r9, 2282148053410728",
+ "mov QWORD PTR [rsi+224], r9",
+ "movabs r9, 16668952760323958",
+ "mov QWORD PTR [rsi+232], r9",
+ "movabs r9, 25011900965946676",
+ "mov QWORD PTR [rsi+240], r9",
+ "movabs r9, 23977247637478740",
+ "mov QWORD PTR [rsi+248], r9",
+ "movabs r9, 29427887555995366",
+ "mov QWORD PTR [rsi+256], r9",
+ "movabs r9, 22931526182748624",
+ "mov QWORD PTR [rsi+264], r9",
+ "movabs r9, 14929091579459166",
+ "mov QWORD PTR [rsi+272], r9",
+ "movabs r9, 29185144592086471",
+ "mov QWORD PTR [rsi+280], r9",
+ "movabs r9, 8329290213797750",
+ "mov QWORD PTR [rsi+288], r9",
+ "movabs r9, 31697782066745459",
+ "mov QWORD PTR [rsi+296], r9",
+ "movabs r9, 22432987854353025",
+ "mov QWORD PTR [rsi+304], r9",
+ "movabs r9, 545125843890401",
+ "mov QWORD PTR [rsi+312], r9",
+ "movabs r9, 31769864501989618",
+ "mov QWORD PTR [rsi+320], r9",
+ "movabs r9, 11662103226140216",
+ "mov QWORD PTR [rsi+328], r9",
+ "movabs r9, 20130185304250276",
+ "mov QWORD PTR [rsi+336], r9",
+ "movabs r9, 25354781094156910",
+ "mov QWORD PTR [rsi+344], r9",
+ "movabs r9, 30717142252233347",
+ "mov QWORD PTR [rsi+352], r9",
+ "movabs r9, 30375073877558844",
+ "mov QWORD PTR [rsi+360], r9",
+ "movabs r9, 5794237307816926",
+ "mov QWORD PTR [rsi+368], r9",
+ "movabs r9, 29849966874477923",
+ "mov QWORD PTR [rsi+376], r9",
+ "movabs r9, 1137925820308458",
+ "mov QWORD PTR [rsi+384], r9",
+ "movabs r9, 13305774323778583",
+ "mov QWORD PTR [rsi+392], r9",
+ "movabs r9, 31268732009491712",
+ "mov QWORD PTR [rsi+400], r9",
+ "movabs r9, 17002134848261444",
+ "mov QWORD PTR [rsi+408], r9",
+ "movabs r9, 35956774717033419",
+ "mov QWORD PTR [rsi+416], r9",
+ "movabs r9, 22036141462600008",
+ "mov QWORD PTR [rsi+424], r9",
+ "movabs r9, 35087477629023596",
+ "mov QWORD PTR [rsi+432], r9",
+ "movabs r9, 30337763489061025",
+ "mov QWORD PTR [rsi+440], r9",
+ "movabs r9, 20732429908239468",
+ "mov QWORD PTR [rsi+448], r9",
+ "movabs r9, 28041905903253186",
+ "mov QWORD PTR [rsi+456], r9",
+ "movabs r9, 35231517950811284",
+ "mov QWORD PTR [rsi+464], r9",
+ "movabs r9, 5760968484459269",
+ "mov QWORD PTR [rsi+472], r9",
+ "movabs r9, 29186403016613413",
+ "mov QWORD PTR [rsi+480], r9",
+ "movabs r9, 29809972144732485",
+ "mov QWORD PTR [rsi+488], r9",
+ "movabs r9, 19324591173389987",
+ "mov QWORD PTR [rsi+496], r9",
+ "movabs r9, 16492506917666904",
+ "mov QWORD PTR [rsi+504], r9",
+ "movabs r9, 14635985826474643",
+ "mov QWORD PTR [rsi+512], r9",
+ "movabs r9, 16398082059229396",
+ "mov QWORD PTR [rsi+520], r9",
+ "movabs r9, 9638297459285875",
+ "mov QWORD PTR [rsi+528], r9",
+ "movabs r9, 20692959164533664",
+ "mov QWORD PTR [rsi+536], r9",
+ "movabs r9, 10455835889373941",
+ "mov QWORD PTR [rsi+544], r9",
+ "movabs r9, 15088997507073265",
+ "mov QWORD PTR [rsi+552], r9",
+ "movabs r9, 19847271512942753",
+ "mov QWORD PTR [rsi+560], r9",
+ "movabs r9, 22278162875259735",
+ "mov QWORD PTR [rsi+568], r9",
+ "movabs r9, 7984765110959710",
+ "mov QWORD PTR [rsi+576], r9",
+ "movabs r9, 3517724245221606",
+ "mov QWORD PTR [rsi+584], r9",
+ "movabs r9, 29065087369580419",
+ "mov QWORD PTR [rsi+592], r9",
+ "movabs r9, 33749496538019589",
+ "mov QWORD PTR [rsi+600], r9",
+ "movabs r9, 22582830675910690",
+ "mov QWORD PTR [rsi+608], r9",
+ "movabs r9, 13774157688799364",
+ "mov QWORD PTR [rsi+616], r9",
+ "movabs r9, 33738338209470846",
+ "mov QWORD PTR [rsi+624], r9",
+ "movabs r9, 20549610337740179",
+ "mov QWORD PTR [rsi+632], r9",
+ "movabs r9, 1232604074686745",
+ "mov QWORD PTR [rsi+640], r9",
+ "movabs r9, 17645078572608834",
+ "mov QWORD PTR [rsi+648], r9",
+ "movabs r9, 21638646536106727",
+ "mov QWORD PTR [rsi+656], r9",
+ "movabs r9, 872067341384903",
+ "mov QWORD PTR [rsi+664], r9",
+ "movabs r9, 11559822875647717",
+ "mov QWORD PTR [rsi+672], r9",
+ "movabs r9, 5433172289935931",
+ "mov QWORD PTR [rsi+680], r9",
+ "movabs r9, 5358487101890844",
+ "mov QWORD PTR [rsi+688], r9",
+ "movabs r9, 6854656137752657",
+ "mov QWORD PTR [rsi+696], r9",
+ "movabs r9, 5370830838457625",
+ "mov QWORD PTR [rsi+704], r9",
+ "movabs r9, 20753904747165841",
+ "mov QWORD PTR [rsi+712], r9",
+ "movabs r9, 8027804982718602",
+ "mov QWORD PTR [rsi+720], r9",
+ "movabs r9, 31479735164668747",
+ "mov QWORD PTR [rsi+728], r9",
+ "movabs r9, 5314055668205759",
+ "mov QWORD PTR [rsi+736], r9",
+ "movabs r9, 29850847345983039",
+ "mov QWORD PTR [rsi+744], r9",
+ "movabs r9, 5636951310400997",
+ "mov QWORD PTR [rsi+752], r9",
+ "movabs r9, 27564133741392515",
+ "mov QWORD PTR [rsi+760], r9",
+ "movabs r9, 8233800205883732",
+ "mov QWORD PTR [rsi+768], r9",
+ "movabs r9, 30088883024233849",
+ "mov QWORD PTR [rsi+776], r9",
+ "movabs r9, 3338009929245701",
+ "mov QWORD PTR [rsi+784], r9",
+ "movabs r9, 14628791756398056",
+ "mov QWORD PTR [rsi+792], r9",
+ "movabs r9, 23830870862829877",
+ "mov QWORD PTR [rsi+800], r9",
+ "movabs r9, 28061014216302585",
+ "mov QWORD PTR [rsi+808], r9",
+ "movabs r9, 19997999096164636",
+ "mov QWORD PTR [rsi+816], r9",
+ "movabs r9, 19771555530215640",
+ "mov QWORD PTR [rsi+824], r9",
+ "movabs r9, 10447056982320729",
+ "mov QWORD PTR [rsi+832], r9",
+ "movabs r9, 35286145636332471",
+ "mov QWORD PTR [rsi+840], r9",
+ "movabs r9, 14470225858518424",
+ "mov QWORD PTR [rsi+848], r9",
+ "movabs r9, 30807937853347003",
+ "mov QWORD PTR [rsi+856], r9",
+ "movabs r9, 699409659546815",
+ "mov QWORD PTR [rsi+864], r9",
+ "movabs r9, 12945035726727688",
+ "mov QWORD PTR [rsi+872], r9",
+ "movabs r9, 7098008983067813",
+ "mov QWORD PTR [rsi+880], r9",
+ "movabs r9, 28266511219523944",
+ "mov QWORD PTR [rsi+888], r9",
+ "movabs r9, 15135022374814013",
+ "mov QWORD PTR [rsi+896], r9",
+ "movabs r9, 1158610381635861",
+ "mov QWORD PTR [rsi+904], r9",
+ "movabs r9, 31802227079365879",
+ "mov QWORD PTR [rsi+912], r9",
+ "movabs r9, 2027559572878823",
+ "mov QWORD PTR [rsi+920], r9",
+ "movabs r9, 7402805639339334",
+ "mov QWORD PTR [rsi+928], r9",
+ "movabs r9, 8205002449640623",
+ "mov QWORD PTR [rsi+936], r9",
+ "movabs r9, 31250542829661849",
+ "mov QWORD PTR [rsi+944], r9",
+ "movabs r9, 19527171898598875",
+ "mov QWORD PTR [rsi+952], r9",
+ "movabs r9, 26390134497937253",
+ "mov QWORD PTR [rsi+960], r9",
+ "movabs r9, 26173917256840158",
+ "mov QWORD PTR [rsi+968], r9",
+ "movabs r9, 31797902045269139",
+ "mov QWORD PTR [rsi+976], r9",
+ "movabs r9, 20765007236602922",
+ "mov QWORD PTR [rsi+984], r9",
+ "movabs r9, 16834811519265361",
+ "mov QWORD PTR [rsi+992], r9",
+ "movabs r9, 30142973844857679",
+ "mov QWORD PTR [rsi+1000], r9",
+ "movabs r9, 6014775284471242",
+ "mov QWORD PTR [rsi+1008], r9",
+ "movabs r9, 8490214048855735",
+ "mov QWORD PTR [rsi+1016], r9",
+ "mov eax, 8380417",
+ "vmovq xmm15, rax",
+ "vpbroadcastd ymm15, xmm15",
+ "mov eax, -58728449",
+ "vmovq xmm14, rax",
+ "vpbroadcastd ymm14, xmm14",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 992",
+ "mov ecx, 16",
+ "20:",
+ "vmovdqu ymm0, YMMWORD PTR [rdx]",
+ "vmovdqu ymm2, YMMWORD PTR [rdx+32]",
+ "vmovdqu ymm13, YMMWORD PTR [r8]",
+ "vpermq ymm13, ymm13, 39",
+ "vpshufd ymm13, ymm13, 177",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, -32",
+ "vpshufd ymm0, ymm0, 216",
+ "vpshufd ymm2, ymm2, 216",
+ "vmovdqa ymm1, ymm0",
+ "vpunpcklqdq ymm0, ymm0, ymm2",
+ "vpunpckhqdq ymm1, ymm1, ymm2",
+ "vpsubd ymm3, ymm1, ymm0",
+ "vpaddd ymm3, ymm3, ymm15",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqa ymm1, ymm0",
+ "vpunpckldq ymm0, ymm0, ymm3",
+ "vpunpckhdq ymm1, ymm1, ymm3",
+ "vmovdqu YMMWORD PTR [rdx], ymm0",
+ "vmovdqu YMMWORD PTR [rdx+32], ymm1",
+ "add rdx, 64",
+ "sub rcx, 1",
+ "jne 20b",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 496",
+ "mov ecx, 16",
+ "21:",
+ "vmovdqu ymm0, YMMWORD PTR [rdx]",
+ "vmovdqu ymm1, YMMWORD PTR [rdx+32]",
+ "vbroadcasti128 ymm13, XMMWORD PTR [r8]",
+ "vpshufd ymm2, ymm13, 10",
+ "vpshufd ymm13, ymm13, 95",
+ "vpblendd ymm13, ymm13, ymm2, 240",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, -16",
+ "vmovdqa ymm2, ymm0",
+ "vpunpcklqdq ymm0, ymm0, ymm1",
+ "vpunpckhqdq ymm2, ymm2, ymm1",
+ "vmovdqa ymm1, ymm2",
+ "vpsubd ymm3, ymm1, ymm0",
+ "vpaddd ymm3, ymm3, ymm15",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqa ymm1, ymm0",
+ "vpunpcklqdq ymm0, ymm0, ymm3",
+ "vpunpckhqdq ymm1, ymm1, ymm3",
+ "vmovdqu YMMWORD PTR [rdx], ymm0",
+ "vmovdqu YMMWORD PTR [rdx+32], ymm1",
+ "add rdx, 64",
+ "sub rcx, 1",
+ "jne 21b",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 248",
+ "mov ecx, 16",
+ "22:",
+ "vmovdqu ymm4, YMMWORD PTR [rdx]",
+ "vmovdqu ymm5, YMMWORD PTR [rdx+32]",
+ "vbroadcasti128 ymm13, XMMWORD PTR [r8]",
+ "vpshufd ymm2, ymm13, 0",
+ "vpshufd ymm13, ymm13, 85",
+ "vpblendd ymm13, ymm13, ymm2, 240",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, -8",
+ "vperm2i128 ymm0, ymm4, ymm5, 32",
+ "vperm2i128 ymm1, ymm4, ymm5, 49",
+ "vpsubd ymm3, ymm1, ymm0",
+ "vpaddd ymm3, ymm3, ymm15",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vperm2i128 ymm4, ymm0, ymm3, 32",
+ "vperm2i128 ymm5, ymm0, ymm3, 49",
+ "vmovdqu YMMWORD PTR [rdx], ymm4",
+ "vmovdqu YMMWORD PTR [rdx+32], ymm5",
+ "add rdx, 64",
+ "sub rcx, 1",
+ "jne 22b",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 124",
+ "mov eax, 16",
+ "23:",
+ "vbroadcasti128 ymm13, XMMWORD PTR [r8]",
+ "vpshufd ymm13, ymm13, 0",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, -4",
+ "mov ecx, 1",
+ "24:",
+ "vmovdqu ymm0, YMMWORD PTR [rdx]",
+ "vmovdqu ymm1, YMMWORD PTR [rdx+32]",
+ "vpsubd ymm3, ymm1, ymm0",
+ "vpaddd ymm3, ymm3, ymm15",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqu YMMWORD PTR [rdx], ymm0",
+ "vmovdqu YMMWORD PTR [rdx+32], ymm3",
+ "add rdx, 32",
+ "sub rcx, 1",
+ "jne 24b",
+ "add rdx, 32",
+ "sub rax, 1",
+ "jne 23b",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 60",
+ "mov eax, 8",
+ "25:",
+ "vbroadcasti128 ymm13, XMMWORD PTR [r8]",
+ "vpshufd ymm13, ymm13, 0",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, -4",
+ "mov ecx, 2",
+ "26:",
+ "vmovdqu ymm0, YMMWORD PTR [rdx]",
+ "vmovdqu ymm1, YMMWORD PTR [rdx+64]",
+ "vpsubd ymm3, ymm1, ymm0",
+ "vpaddd ymm3, ymm3, ymm15",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqu YMMWORD PTR [rdx], ymm0",
+ "vmovdqu YMMWORD PTR [rdx+64], ymm3",
+ "add rdx, 32",
+ "sub rcx, 1",
+ "jne 26b",
+ "add rdx, 64",
+ "sub rax, 1",
+ "jne 25b",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 28",
+ "mov eax, 4",
+ "27:",
+ "vbroadcasti128 ymm13, XMMWORD PTR [r8]",
+ "vpshufd ymm13, ymm13, 0",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, -4",
+ "mov ecx, 4",
+ "28:",
+ "vmovdqu ymm0, YMMWORD PTR [rdx]",
+ "vmovdqu ymm1, YMMWORD PTR [rdx+128]",
+ "vpsubd ymm3, ymm1, ymm0",
+ "vpaddd ymm3, ymm3, ymm15",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqu YMMWORD PTR [rdx], ymm0",
+ "vmovdqu YMMWORD PTR [rdx+128], ymm3",
+ "add rdx, 32",
+ "sub rcx, 1",
+ "jne 28b",
+ "add rdx, 128",
+ "sub rax, 1",
+ "jne 27b",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 12",
+ "mov eax, 2",
+ "29:",
+ "vbroadcasti128 ymm13, XMMWORD PTR [r8]",
+ "vpshufd ymm13, ymm13, 0",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, -4",
+ "mov ecx, 8",
+ "210:",
+ "vmovdqu ymm0, YMMWORD PTR [rdx]",
+ "vmovdqu ymm1, YMMWORD PTR [rdx+256]",
+ "vpsubd ymm3, ymm1, ymm0",
+ "vpaddd ymm3, ymm3, ymm15",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqu YMMWORD PTR [rdx], ymm0",
+ "vmovdqu YMMWORD PTR [rdx+256], ymm3",
+ "add rdx, 32",
+ "sub rcx, 1",
+ "jne 210b",
+ "add rdx, 256",
+ "sub rax, 1",
+ "jne 29b",
+ "mov rdx, rdi",
+ "mov r8, rsi",
+ "add r8, 4",
+ "mov eax, 1",
+ "211:",
+ "vbroadcasti128 ymm13, XMMWORD PTR [r8]",
+ "vpshufd ymm13, ymm13, 0",
+ "vpshufd ymm12, ymm13, 245",
+ "add r8, -4",
+ "mov ecx, 16",
+ "212:",
+ "vmovdqu ymm0, YMMWORD PTR [rdx]",
+ "vmovdqu ymm1, YMMWORD PTR [rdx+512]",
+ "vpsubd ymm3, ymm1, ymm0",
+ "vpaddd ymm3, ymm3, ymm15",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqu YMMWORD PTR [rdx], ymm0",
+ "vmovdqu YMMWORD PTR [rdx+512], ymm3",
+ "add rdx, 32",
+ "sub rcx, 1",
+ "jne 212b",
+ "add rdx, 512",
+ "sub rax, 1",
+ "jne 211b",
+ "mov rdx, rdi",
+ "mov eax, 16382",
+ "vmovq xmm13, rax",
+ "vpbroadcastd ymm13, xmm13",
+ "vmovdqa ymm12, ymm13",
+ "mov ecx, 32",
+ "213:",
+ "vmovdqu ymm3, YMMWORD PTR [rdx]",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqu YMMWORD PTR [rdx], ymm3",
+ "add rdx, 32",
+ "sub rcx, 1",
+ "jne 213b",
+ "vzeroupper",
+ "lfence",
+ "mov DWORD PTR [rsi+768], r11d",
+ "ldmxcsr DWORD PTR [rsi+768]",
+ "ret",
+ )
+}
+
+/// The CPU features `vg_mldsa_multiply_ntt_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA_MULTIPLY_NTT_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// The product of two elements of `T_q`, `MultiplyNTT` (FIPS 204 Algorithm 45): writes the coefficientwise product of `*f` and `*g` modulo `q` = 8380417 to `*h`.
+///
+/// Contract: `VG.Spec.MlDsa.mulContract`. Constant time: only the pointers may affect timing, not the data.
+///
+/// The function computes on eight coefficients at a time in AVX2 registers. It sets MXCSR to `0x1FBF` around its multiplications (Intel's mitigation of MXCSR-configuration-dependent timing), through the last 8 bytes of `h`, which it stores last, and loads the caller's MXCSR back before returning.
+///
+/// # Safety
+///
+/// * `h` must be valid for reads and writes of 1024 bytes.
+/// * `f` must be valid for reads of 1024 bytes.
+/// * `g` must be valid for reads of 1024 bytes.
+/// * Each of the 256 `u32`s of `f` must be less than `q` = 8380417.
+/// * Each of the 256 `u32`s of `g` must be less than `q` = 8380417.
+/// * `h` must not overlap `f` or `g` (distinct Rust objects never do).
+/// * None of `h`, `f` and `g` may overlap the return address on the stack, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa_multiply_ntt_avx2(h: *mut [u32; 256], f: *const [u32; 256], g: *const [u32; 256]) {
+ core::arch::naked_asm!(
+ "mov r8, rdi",
+ "vmovdqu ymm6, YMMWORD PTR [rdi+992]",
+ "stmxcsr DWORD PTR [r8+1016]",
+ "mov r11d, DWORD PTR [r8+1016]",
+ "and r11d, 65535",
+ "mov eax, 8127",
+ "mov DWORD PTR [r8+1020], eax",
+ "ldmxcsr DWORD PTR [r8+1020]",
+ "lfence",
+ "mov eax, 8380417",
+ "vmovq xmm15, rax",
+ "vpbroadcastd ymm15, xmm15",
+ "mov eax, -58728449",
+ "vmovq xmm14, rax",
+ "vpbroadcastd ymm14, xmm14",
+ "mov eax, 2365951",
+ "vmovq xmm11, rax",
+ "vpbroadcastd ymm11, xmm11",
+ "mov ecx, 31",
+ "20:",
+ "vmovdqu ymm3, YMMWORD PTR [rsi]",
+ "vmovdqu ymm13, YMMWORD PTR [rdx]",
+ "vmovdqu ymm5, YMMWORD PTR [rdi]",
+ "vpshufd ymm12, ymm13, 245",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm11",
+ "vpmuludq ymm4, ymm4, ymm11",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqu YMMWORD PTR [rdi], ymm3",
+ "add rdi, 32",
+ "add rsi, 32",
+ "add rdx, 32",
+ "sub rcx, 1",
+ "jne 20b",
+ "vmovdqu ymm3, YMMWORD PTR [rsi]",
+ "vmovdqu ymm13, YMMWORD PTR [rdx]",
+ "vmovdqa ymm5, ymm6",
+ "vpshufd ymm12, ymm13, 245",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm11",
+ "vpmuludq ymm4, ymm4, ymm11",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "lfence",
+ "mov DWORD PTR [r8+1016], r11d",
+ "ldmxcsr DWORD PTR [r8+1016]",
+ "vmovdqu YMMWORD PTR [rdi], ymm3",
+ "vzeroupper",
+ "ret",
+ )
+}
+
+/// The CPU features `vg_mldsa_multiply_add_ntt_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA_MULTIPLY_ADD_NTT_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// Adds the product of two elements of `T_q` to a third, `AddNTT(h, MultiplyNTT(f, g))` (FIPS 204 Algorithms 44 and 45): adds the coefficientwise product of `*f` and `*g` to `*h`, modulo `q` = 8380417.
+///
+/// Contract: `VG.Spec.MlDsa.mulAddContract`. Constant time: only the pointers may affect timing, not the data.
+///
+/// The function computes on eight coefficients at a time in AVX2 registers. It sets MXCSR to `0x1FBF` around its multiplications (Intel's mitigation of MXCSR-configuration-dependent timing), through the last 8 bytes of `h`, which it stores last, and loads the caller's MXCSR back before returning.
+///
+/// # Safety
+///
+/// * `h` must be valid for reads and writes of 1024 bytes.
+/// * `f` must be valid for reads of 1024 bytes.
+/// * `g` must be valid for reads of 1024 bytes.
+/// * Each of the 256 `u32`s of `h` must be less than `q` = 8380417.
+/// * Each of the 256 `u32`s of `f` must be less than `q` = 8380417.
+/// * Each of the 256 `u32`s of `g` must be less than `q` = 8380417.
+/// * `h` must not overlap `f` or `g` (distinct Rust objects never do).
+/// * None of `h`, `f` and `g` may overlap the return address on the stack, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa_multiply_add_ntt_avx2(h: *mut [u32; 256], f: *const [u32; 256], g: *const [u32; 256]) {
+ core::arch::naked_asm!(
+ "mov r8, rdi",
+ "vmovdqu ymm6, YMMWORD PTR [rdi+992]",
+ "stmxcsr DWORD PTR [r8+1016]",
+ "mov r11d, DWORD PTR [r8+1016]",
+ "and r11d, 65535",
+ "mov eax, 8127",
+ "mov DWORD PTR [r8+1020], eax",
+ "ldmxcsr DWORD PTR [r8+1020]",
+ "lfence",
+ "mov eax, 8380417",
+ "vmovq xmm15, rax",
+ "vpbroadcastd ymm15, xmm15",
+ "mov eax, -58728449",
+ "vmovq xmm14, rax",
+ "vpbroadcastd ymm14, xmm14",
+ "mov eax, 2365951",
+ "vmovq xmm11, rax",
+ "vpbroadcastd ymm11, xmm11",
+ "mov ecx, 31",
+ "20:",
+ "vmovdqu ymm3, YMMWORD PTR [rsi]",
+ "vmovdqu ymm13, YMMWORD PTR [rdx]",
+ "vmovdqu ymm5, YMMWORD PTR [rdi]",
+ "vpshufd ymm12, ymm13, 245",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm11",
+ "vpmuludq ymm4, ymm4, ymm11",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vpaddd ymm3, ymm3, ymm5",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vmovdqu YMMWORD PTR [rdi], ymm3",
+ "add rdi, 32",
+ "add rsi, 32",
+ "add rdx, 32",
+ "sub rcx, 1",
+ "jne 20b",
+ "vmovdqu ymm3, YMMWORD PTR [rsi]",
+ "vmovdqu ymm13, YMMWORD PTR [rdx]",
+ "vmovdqa ymm5, ymm6",
+ "vpshufd ymm12, ymm13, 245",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm13",
+ "vpmuludq ymm4, ymm4, ymm12",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpshufd ymm4, ymm3, 245",
+ "vpmuludq ymm3, ymm3, ymm11",
+ "vpmuludq ymm4, ymm4, ymm11",
+ "vpmuludq ymm2, ymm3, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm3, ymm3, ymm2",
+ "vpsrlq ymm3, ymm3, 32",
+ "vpmuludq ymm2, ymm4, ymm14",
+ "vpmuludq ymm2, ymm2, ymm15",
+ "vpaddq ymm4, ymm4, ymm2",
+ "vpor ymm3, ymm3, ymm4",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "vpaddd ymm3, ymm3, ymm5",
+ "vpsubd ymm3, ymm3, ymm15",
+ "vpsrad ymm2, ymm3, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm3, ymm3, ymm2",
+ "lfence",
+ "mov DWORD PTR [r8+1016], r11d",
+ "ldmxcsr DWORD PTR [r8+1016]",
+ "vmovdqu YMMWORD PTR [rdi], ymm3",
+ "vzeroupper",
+ "ret",
+ )
+}
+
+/// The CPU features `vg_mldsa_add_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA_ADD_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// Adds the polynomial `*g` to `*f` modulo `q` = 8380417, coefficient by coefficient (FIPS 204 Algorithm 44).
+///
+/// Contract: `VG.Spec.MlDsa.addContract`. Constant time: only the pointers may affect timing, not the data.
+///
+/// The function computes on eight coefficients at a time in AVX2 registers.
+///
+/// # Safety
+///
+/// * `f` must be valid for reads and writes of 1024 bytes.
+/// * `g` must be valid for reads of 1024 bytes.
+/// * Each of the 256 `u32`s of `f` must be less than `q` = 8380417.
+/// * Each of the 256 `u32`s of `g` must be less than `q` = 8380417.
+/// * `f` must not overlap `g` (distinct Rust objects never do).
+/// * Neither `f` nor `g` may overlap the return address on the stack, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa_add_avx2(f: *mut [u32; 256], g: *const [u32; 256]) {
+ core::arch::naked_asm!(
+ "mov eax, 8380417",
+ "vmovq xmm15, rax",
+ "vpbroadcastd ymm15, xmm15",
+ "mov ecx, 32",
+ "20:",
+ "vmovdqu ymm0, YMMWORD PTR [rdi]",
+ "vmovdqu ymm1, YMMWORD PTR [rsi]",
+ "vpaddd ymm0, ymm0, ymm1",
+ "vpsubd ymm0, ymm0, ymm15",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vmovdqu YMMWORD PTR [rdi], ymm0",
+ "add rdi, 32",
+ "add rsi, 32",
+ "sub rcx, 1",
+ "jne 20b",
+ "vzeroupper",
+ "ret",
+ )
+}
+
+/// The CPU features `vg_mldsa_sub_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA_SUB_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// Subtracts the polynomial `*g` from `*f` modulo `q` = 8380417, coefficient by coefficient.
+///
+/// Contract: `VG.Spec.MlDsa.subContract`. Constant time: only the pointers may affect timing, not the data.
+///
+/// The function computes on eight coefficients at a time in AVX2 registers.
+///
+/// # Safety
+///
+/// * `f` must be valid for reads and writes of 1024 bytes.
+/// * `g` must be valid for reads of 1024 bytes.
+/// * Each of the 256 `u32`s of `f` must be less than `q` = 8380417.
+/// * Each of the 256 `u32`s of `g` must be less than `q` = 8380417.
+/// * `f` must not overlap `g` (distinct Rust objects never do).
+/// * Neither `f` nor `g` may overlap the return address on the stack, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa_sub_avx2(f: *mut [u32; 256], g: *const [u32; 256]) {
+ core::arch::naked_asm!(
+ "mov eax, 8380417",
+ "vmovq xmm15, rax",
+ "vpbroadcastd ymm15, xmm15",
+ "mov ecx, 32",
+ "20:",
+ "vmovdqu ymm0, YMMWORD PTR [rdi]",
+ "vmovdqu ymm1, YMMWORD PTR [rsi]",
+ "vpsubd ymm0, ymm0, ymm1",
+ "vpsrad ymm2, ymm0, 31",
+ "vpand ymm2, ymm2, ymm15",
+ "vpaddd ymm0, ymm0, ymm2",
+ "vmovdqu YMMWORD PTR [rdi], ymm0",
+ "add rdi, 32",
+ "add rsi, 32",
+ "sub rcx, 1",
+ "jne 20b",
+ "vzeroupper",
+ "ret",
+ )
+}
+
/// `SimpleBitPack(f, b)` (FIPS 204 Algorithm 16): writes the 256 coefficients of `*f` to `out` as `bitlen b`-bit little-endian fields.
///
/// Contract: `VG.Spec.MlDsa.simpleBitPackContract`. Constant time: only the pointers, `b` and `len` may affect timing, not the data.
diff --git a/src/asm/x86_64/mldsa44.rs b/src/asm/x86_64/mldsa44.rs
index 63ea03f6e..90e8d05f4 100644
--- a/src/asm/x86_64/mldsa44.rs
+++ b/src/asm/x86_64/mldsa44.rs
@@ -2,6 +2,3460 @@
//! Verified `mldsa44` functions for `x86_64`.
#![allow(dead_code)]
+/// The CPU features `vg_mldsa44_keygen_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA44_KEYGEN_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// ML-DSA-44 key generation from a seed, `ML-DSA.KeyGen_internal(ξ)` (FIPS 204 Algorithm 6): with the 32-byte seed `ξ` at `seed`, writes the public key to `*pk` and the private key to `*sk`. Returns 1 on success. Returns 0 if a loop reaches its bound, which is at least the limit of FIPS 204 Appendix C, Table 3 (this happens with probability about 2^-256 or less): the outputs are then unspecified, and the caller must destroy them and treat the operation as failed.
+///
+/// Contract: `VG.Spec.MlDsa.keyGenContract`. Constant time but for `ρ` and rejections: timing may depend on the pointers, on `ρ` (the first 32 bytes of the public key), and on which half-bytes of the SHAKE256 outputs `RejBoundedPoly` rejects (`rejBoundedLeak`, which is independent of the coefficients it samples), but not on anything else of the seed or the keys.
+///
+/// The function saves its caller's callee-saved registers in `scratch`; its calls use the 32 bytes of stack below its return address.
+///
+/// It samples every polynomial of `A` and of `s1` and `s2` whatever the samplers return, and zeroes the polynomial of a sampler that fails rather than branching on it: its timing does not depend on whether key generation fails.
+///
+/// # Safety
+///
+/// * `seed` must be valid for reads of 32 bytes.
+/// * `pk` must be valid for reads and writes of 1312 bytes.
+/// * `sk` must be valid for reads and writes of 2560 bytes.
+/// * `scratch` must be valid for reads and writes of 77824 bytes.
+/// * `seed` must be random bytes from an approved RBG (FIPS 204 §3.6.1), or a seed so generated before.
+/// * `scratch` is working space: on return it holds intermediate values, which the caller must destroy (FIPS 204 §3.6.3).
+/// * `pk`, `sk` and `scratch` must not overlap each other or `seed` (distinct Rust objects never do).
+/// * None of `seed`, `pk`, `sk` and `scratch` may overlap the return address on the stack or the 32 bytes of stack below it, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa44_keygen_avx2(seed: *const [u8; 32], pk: *mut [u8; 1312], sk: *mut [u8; 2560], scratch: *mut [u64; 9728]) -> u32 {
+ core::arch::naked_asm!(
+ "mov QWORD PTR [rcx+840], rbx",
+ "mov QWORD PTR [rcx+848], rbp",
+ "mov QWORD PTR [rcx+856], r12",
+ "mov QWORD PTR [rcx+864], r13",
+ "mov QWORD PTR [rcx+872], r14",
+ "mov QWORD PTR [rcx+880], r15",
+ "mov rbx, rcx",
+ "mov rbp, rdi",
+ "mov r12, rsi",
+ "mov r13, rdx",
+ "mov r15d, 1",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+896], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+897], al",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbp",
+ "add rcx, 0",
+ "mov r8d, 32",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 32",
+ "mov rcx, rbx",
+ "add rcx, 896",
+ "mov r8d, 2",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 34",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbx",
+ "add rcx, 1024",
+ "mov r8d, 128",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 1024",
+ "mov ecx, 32",
+ "20:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 20b",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov rsi, rbx",
+ "add rsi, 1056",
+ "mov ecx, 64",
+ "21:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 21b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1281], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 4096",
+ "mov ecx, 256",
+ "22:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 22b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 5120",
+ "mov ecx, 256",
+ "23:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 23b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov ecx, 256",
+ "24:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 24b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 7168",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov ecx, 256",
+ "25:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 25b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov ecx, 256",
+ "26:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 26b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 9216",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov ecx, 256",
+ "27:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 27b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 10240",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 10240",
+ "mov ecx, 256",
+ "28:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 28b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 11264",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 11264",
+ "mov ecx, 256",
+ "29:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 29b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 12288",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 12288",
+ "mov ecx, 256",
+ "210:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 210b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 13312",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 13312",
+ "mov ecx, 256",
+ "211:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 211b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 14336",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 14336",
+ "mov ecx, 256",
+ "212:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 212b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 15360",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 15360",
+ "mov ecx, 256",
+ "213:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 213b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 16384",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov ecx, 256",
+ "214:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 214b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 17408",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov ecx, 256",
+ "215:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 215b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 18432",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov ecx, 256",
+ "216:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 216b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 19456",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov ecx, 256",
+ "217:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 217b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov ecx, 256",
+ "218:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 218b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 21504",
+ "mov ecx, 256",
+ "219:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 219b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov ecx, 256",
+ "220:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 220b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 23552",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov ecx, 256",
+ "221:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 221b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov ecx, 256",
+ "222:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 222b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov ecx, 256",
+ "223:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 223b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 26624",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov ecx, 256",
+ "224:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 224b",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 27648",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov ecx, 256",
+ "225:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 225b",
+ "mov rdi, r12",
+ "add rdi, 0",
+ "mov rsi, rbx",
+ "add rsi, 1024",
+ "mov ecx, 32",
+ "226:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 226b",
+ "mov rdi, r13",
+ "add rdi, 0",
+ "mov rsi, rbx",
+ "add rsi, 1024",
+ "mov ecx, 32",
+ "227:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 227b",
+ "mov rdi, r13",
+ "add rdi, 32",
+ "mov rsi, rbx",
+ "add rsi, 1120",
+ "mov ecx, 32",
+ "228:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 228b",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 128",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 21504",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 224",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 320",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 416",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 512",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 608",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 704",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 800",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 21504",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 7168",
+ "mov rdx, rbx",
+ "add rdx, 23552",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov rdx, rbx",
+ "add rdx, 30720",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 32",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 896",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 9216",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 10240",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 11264",
+ "mov rdx, rbx",
+ "add rdx, 23552",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov rdx, rbx",
+ "add rdx, 30720",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 352",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 1312",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 12288",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 13312",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 14336",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 15360",
+ "mov rdx, rbx",
+ "add rdx, 23552",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov rdx, rbx",
+ "add rdx, 30720",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 672",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 1728",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 16384",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 17408",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 18432",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 19456",
+ "mov rdx, rbx",
+ "add rdx, 23552",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 27648",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov rdx, rbx",
+ "add rdx, 30720",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 992",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 2144",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, r12",
+ "add rcx, 0",
+ "mov r8d, 1312",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 88",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, r13",
+ "add rcx, 64",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov eax, r15d",
+ "mov r15, QWORD PTR [rbx+880]",
+ "mov r14, QWORD PTR [rbx+872]",
+ "mov r13, QWORD PTR [rbx+864]",
+ "mov r12, QWORD PTR [rbx+856]",
+ "mov rbp, QWORD PTR [rbx+848]",
+ "mov rbx, QWORD PTR [rbx+840]",
+ "ret",
+ vg_keccak_absorb = sym super::sha3::vg_keccak_absorb,
+ vg_keccak_pad = sym super::sha3::vg_keccak_pad,
+ vg_keccak_squeeze = sym super::sha3::vg_keccak_squeeze,
+ vg_mldsa_rej_ntt_poly = sym super::mldsa::vg_mldsa_rej_ntt_poly,
+ vg_mldsa_rej_bounded_poly = sym super::mldsa::vg_mldsa_rej_bounded_poly,
+ vg_mldsa_bit_pack = sym super::mldsa::vg_mldsa_bit_pack,
+ vg_mldsa_ntt_avx2 = sym super::mldsa::vg_mldsa_ntt_avx2,
+ vg_mldsa_multiply_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_ntt_avx2,
+ vg_mldsa_multiply_add_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_add_ntt_avx2,
+ vg_mldsa_inv_ntt_avx2 = sym super::mldsa::vg_mldsa_inv_ntt_avx2,
+ vg_mldsa_add_avx2 = sym super::mldsa::vg_mldsa_add_avx2,
+ vg_mldsa_power2round = sym super::mldsa::vg_mldsa_power2round,
+ vg_mldsa_simple_bit_pack = sym super::mldsa::vg_mldsa_simple_bit_pack,
+ )
+}
+
+/// The CPU features `vg_mldsa44_sign_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA44_SIGN_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// ML-DSA-44 signing of a message representative, `ML-DSA.Sign_internal(sk, M′, rnd)` (FIPS 204 Algorithm 7) with `μ` computed by the caller: with the private key `*sk`, the 64-byte message representative `μ = H(tr ‖ M′, 64)` at `mu` (for the public key hash `tr`, bytes 64–127 of `*sk`) and the randomness `*rnd`, writes the signature to `*sig`. Returns 1 on success. Returns 0 if a loop reaches its bound, which is at least the limit of FIPS 204 Appendix C, Table 3 (this happens with probability about 2^-256 or less): the outputs are then unspecified, and the caller must destroy them and treat the operation as failed.
+///
+/// Contract: `VG.Spec.MlDsa.signContract`. Constant time but for `ρ` and the rejection sampling: timing may depend on the pointers, on `ρ` (the first 32 bytes of `*sk`), on the number of iterations of the signing loop and the commitment hash of each, and on the hint of the signature (`signLeak`), but not on anything else of the key, the message representative or the randomness.
+///
+/// The function saves its caller's callee-saved registers in `scratch`; its calls use the 24 bytes of stack below its return address.
+///
+/// The signing loop runs at most 814 iterations (FIPS 204 Appendix C). Each iteration computes every validity check and combines them without branching: the one branch on their result is the only place an iteration's outcome affects timing.
+///
+/// # Safety
+///
+/// * `sk` must be valid for reads of 2560 bytes.
+/// * `mu` must be valid for reads of 64 bytes.
+/// * `rnd` must be valid for reads of 32 bytes.
+/// * `sig` must be valid for reads and writes of 2420 bytes.
+/// * `scratch` must be valid for reads and writes of 77824 bytes.
+/// * `sk` must have been written by `vg_mldsa44_keygen`.
+/// * `rnd` must be fresh random bytes (FIPS 204 §3.6.1), or 32 zero bytes for deterministic signing.
+/// * `scratch` is working space: on return it holds intermediate values, which the caller must destroy (FIPS 204 §3.6.3).
+/// * `sig` and `scratch` must not overlap each other, `sk`, `mu` or `rnd` (distinct Rust objects never do).
+/// * None of `sk`, `mu`, `rnd`, `sig` and `scratch` may overlap the return address on the stack or the 24 bytes of stack below it, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa44_sign_avx2(sk: *const [u8; 2560], mu: *const [u8; 64], rnd: *const [u8; 32], sig: *mut [u8; 2420], scratch: *mut [u64; 9728]) -> u32 {
+ core::arch::naked_asm!(
+ "mov QWORD PTR [r8+840], rbx",
+ "mov QWORD PTR [r8+848], rbp",
+ "mov QWORD PTR [r8+856], r12",
+ "mov QWORD PTR [r8+864], r13",
+ "mov QWORD PTR [r8+872], r14",
+ "mov QWORD PTR [r8+880], r15",
+ "mov rbx, r8",
+ "mov rbp, rdi",
+ "mov r12, rsi",
+ "mov r13, rdx",
+ "mov r14, rcx",
+ "mov r15d, 1",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbp",
+ "add rsi, 0",
+ "mov ecx, 32",
+ "20:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 20b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 38912",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 39936",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 40960",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 41984",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 43008",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 44032",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 45056",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 46080",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 48128",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 49152",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 50176",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 51200",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 52224",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 53248",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 54272",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "test r15d, r15d",
+ "jne 21f",
+ "jmp 22f",
+ "21:",
+ "mov rdi, rbp",
+ "add rdi, 128",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 26624",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 224",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 27648",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 320",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 28672",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 416",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 29696",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 512",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 30720",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 608",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 31744",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 704",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 32768",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 800",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 33792",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 896",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 34816",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1312",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 35840",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1728",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 36864",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 2144",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 37888",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbp",
+ "add rcx, 32",
+ "mov r8d, 32",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 32",
+ "mov rcx, r13",
+ "add rcx, 0",
+ "mov r8d, 32",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 64",
+ "mov rcx, r12",
+ "add rcx, 0",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 128",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbx",
+ "add rcx, 960",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx+896], rax",
+ "mov eax, 814",
+ "mov QWORD PTR [rbx+888], rax",
+ "23:",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 0",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 131072",
+ "mov rdx, rbx",
+ "add rdx, 14336",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov rsi, rbx",
+ "add rsi, 14336",
+ "mov ecx, 1024",
+ "24:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 24b",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 1",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 131072",
+ "mov rdx, rbx",
+ "add rdx, 15360",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov rsi, rbx",
+ "add rsi, 15360",
+ "mov ecx, 1024",
+ "25:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 25b",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 2",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 131072",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov rsi, rbx",
+ "add rsi, 16384",
+ "mov ecx, 1024",
+ "26:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 26b",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 3",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 131072",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 21504",
+ "mov rsi, rbx",
+ "add rsi, 17408",
+ "mov ecx, 1024",
+ "27:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 27b",
+ "mov rdi, rbx",
+ "add rdi, 21504",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov rsi, rbx",
+ "add rsi, 38912",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov rsi, rbx",
+ "add rsi, 39936",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov rsi, rbx",
+ "add rsi, 40960",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov rsi, rbx",
+ "add rsi, 41984",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov rsi, rbx",
+ "add rsi, 43008",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov rsi, rbx",
+ "add rsi, 44032",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov rsi, rbx",
+ "add rsi, 45056",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov rsi, rbx",
+ "add rsi, 46080",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 48128",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 49152",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 50176",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 51200",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 52224",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 53248",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 54272",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov esi, 95232",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 43",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "mov ecx, 192",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov esi, 95232",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 43",
+ "mov rdx, rbx",
+ "add rdx, 2240",
+ "mov ecx, 192",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov esi, 95232",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 43",
+ "mov rdx, rbx",
+ "add rdx, 2432",
+ "mov ecx, 192",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov esi, 95232",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 43",
+ "mov rdx, rbx",
+ "add rdx, 2624",
+ "mov ecx, 192",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, r12",
+ "add rcx, 0",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 64",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "mov r8d, 768",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 16",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbx",
+ "add rcx, 1040",
+ "mov r8d, 32",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov rdi, rbx",
+ "add rdi, 1040",
+ "mov esi, 32",
+ "mov edx, 39",
+ "mov rcx, rbx",
+ "add rcx, 5120",
+ "mov r8, rbx",
+ "add r8, 3072",
+ "call {vg_mldsa_sample_in_ball}",
+ "test eax, eax",
+ "jne 28f",
+ "mov r15d, 0",
+ "mov eax, 1",
+ "mov QWORD PTR [rbx+888], rax",
+ "jmp 29f",
+ "28:",
+ "mov rdi, rbx",
+ "add rdi, 5120",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov r15d, 1",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx+904], rax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 26624",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 14336",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 14336",
+ "mov esi, 130994",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 27648",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 15360",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 15360",
+ "mov esi, 130994",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 28672",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov esi, 130994",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 29696",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov esi, 130994",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 30720",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov esi, 95232",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 95154",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 31744",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov esi, 95232",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 95154",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 32768",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov esi, 95232",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 95154",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 33792",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov esi, 95232",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 95154",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 34816",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 95232",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 22528",
+ "mov ecx, 1024",
+ "210:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 210b",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 22528",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 22528",
+ "mov edx, 95232",
+ "mov rcx, rbx",
+ "add rcx, 10240",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 35840",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 95232",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov ecx, 1024",
+ "211:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 211b",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov edx, 95232",
+ "mov rcx, rbx",
+ "add rcx, 11264",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 36864",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 95232",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "mov ecx, 1024",
+ "212:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 212b",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "mov edx, 95232",
+ "mov rcx, rbx",
+ "add rcx, 12288",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 37888",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 95232",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "mov ecx, 1024",
+ "213:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 213b",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "mov edx, 95232",
+ "mov rcx, rbx",
+ "add rcx, 13312",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov eax, DWORD PTR [rbx+904]",
+ "sub rax, 81",
+ "shr rax, 63",
+ "and r15d, eax",
+ "test r15d, r15d",
+ "jne 214f",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 4",
+ "mov QWORD PTR [rbx+896], rax",
+ "jmp 215f",
+ "214:",
+ "mov eax, 1",
+ "mov QWORD PTR [rbx+888], rax",
+ "215:",
+ "29:",
+ "mov rax, QWORD PTR [rbx+888]",
+ "sub rax, 1",
+ "mov QWORD PTR [rbx+888], rax",
+ "jne 23b",
+ "test r15d, r15d",
+ "jne 216f",
+ "jmp 217f",
+ "216:",
+ "mov rdi, r14",
+ "add rdi, 0",
+ "mov rsi, rbx",
+ "add rsi, 1040",
+ "mov ecx, 32",
+ "218:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 218b",
+ "mov rdi, rbx",
+ "add rdi, 14336",
+ "mov esi, 131071",
+ "mov edx, 131072",
+ "mov rcx, r14",
+ "add rcx, 32",
+ "mov r8d, 576",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 15360",
+ "mov esi, 131071",
+ "mov edx, 131072",
+ "mov rcx, r14",
+ "add rcx, 608",
+ "mov r8d, 576",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov esi, 131071",
+ "mov edx, 131072",
+ "mov rcx, r14",
+ "add rcx, 1184",
+ "mov r8d, 576",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov esi, 131071",
+ "mov edx, 131072",
+ "mov rcx, r14",
+ "add rcx, 1760",
+ "mov r8d, 576",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 10240",
+ "mov esi, 1024",
+ "mov edx, 80",
+ "mov rcx, r14",
+ "add rcx, 2336",
+ "mov r8d, 84",
+ "call {vg_mldsa_hint_bit_pack}",
+ "217:",
+ "22:",
+ "mov eax, r15d",
+ "mov r15, QWORD PTR [rbx+880]",
+ "mov r14, QWORD PTR [rbx+872]",
+ "mov r13, QWORD PTR [rbx+864]",
+ "mov r12, QWORD PTR [rbx+856]",
+ "mov rbp, QWORD PTR [rbx+848]",
+ "mov rbx, QWORD PTR [rbx+840]",
+ "ret",
+ vg_mldsa_rej_ntt_poly = sym super::mldsa::vg_mldsa_rej_ntt_poly,
+ vg_mldsa_bit_unpack = sym super::mldsa::vg_mldsa_bit_unpack,
+ vg_mldsa_ntt_avx2 = sym super::mldsa::vg_mldsa_ntt_avx2,
+ vg_keccak_absorb = sym super::sha3::vg_keccak_absorb,
+ vg_keccak_pad = sym super::sha3::vg_keccak_pad,
+ vg_keccak_squeeze = sym super::sha3::vg_keccak_squeeze,
+ vg_mldsa_expand_mask_poly = sym super::mldsa::vg_mldsa_expand_mask_poly,
+ vg_mldsa_multiply_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_ntt_avx2,
+ vg_mldsa_multiply_add_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_add_ntt_avx2,
+ vg_mldsa_inv_ntt_avx2 = sym super::mldsa::vg_mldsa_inv_ntt_avx2,
+ vg_mldsa_high_bits = sym super::mldsa::vg_mldsa_high_bits,
+ vg_mldsa_simple_bit_pack = sym super::mldsa::vg_mldsa_simple_bit_pack,
+ vg_mldsa_sample_in_ball = sym super::mldsa::vg_mldsa_sample_in_ball,
+ vg_mldsa_add_avx2 = sym super::mldsa::vg_mldsa_add_avx2,
+ vg_mldsa_norm_lt = sym super::mldsa::vg_mldsa_norm_lt,
+ vg_mldsa_sub_avx2 = sym super::mldsa::vg_mldsa_sub_avx2,
+ vg_mldsa_low_bits = sym super::mldsa::vg_mldsa_low_bits,
+ vg_mldsa_make_hint = sym super::mldsa::vg_mldsa_make_hint,
+ vg_mldsa_bit_pack = sym super::mldsa::vg_mldsa_bit_pack,
+ vg_mldsa_hint_bit_pack = sym super::mldsa::vg_mldsa_hint_bit_pack,
+ )
+}
+
+/// The CPU features `vg_mldsa44_verify_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA44_VERIFY_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// ML-DSA-44 verification of a signature of a message representative, `ML-DSA.Verify_internal(pk, M′, σ)` (FIPS 204 Algorithm 8) with `μ` computed by the caller: with the public key `*pk`, the 64-byte message representative `μ = H(H(pk, 64) ‖ M′, 64)` at `mu` and the signature `*sig`, returns 1 if the signature is valid, and 0 if it is not or if a loop reaches its bound, which is at least the limit of FIPS 204 Appendix C, Table 3 (this happens with probability about 2^-256 or less).
+///
+/// Contract: `VG.Spec.MlDsa.verifyContract`. Not constant time: timing may depend on the public key, the message representative and the signature.
+///
+/// It calls the `vg_mldsa_*` primitives and the SHAKE256 sponge. The samplers' results are combined without a branch, so the only branches depend on the public key and the signature.
+///
+/// # Safety
+///
+/// * `pk` must be valid for reads of 1312 bytes.
+/// * `mu` must be valid for reads of 64 bytes.
+/// * `sig` must be valid for reads of 2420 bytes.
+/// * `scratch` must be valid for reads and writes of 77824 bytes.
+/// * `scratch` is working space: on return it holds intermediate values, which the caller must destroy (FIPS 204 §3.6.3).
+/// * `scratch` must not overlap `pk`, `mu` or `sig` (distinct Rust objects never do).
+/// * None of `pk`, `mu`, `sig` and `scratch` may overlap the return address on the stack or the 24 bytes of stack below it, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa44_verify_avx2(pk: *const [u8; 1312], mu: *const [u8; 64], sig: *const [u8; 2420], scratch: *mut [u64; 9728]) -> u32 {
+ core::arch::naked_asm!(
+ "mov QWORD PTR [rcx+840], rbx",
+ "mov QWORD PTR [rcx+848], rbp",
+ "mov QWORD PTR [rcx+856], r12",
+ "mov QWORD PTR [rcx+864], r13",
+ "mov QWORD PTR [rcx+872], r14",
+ "mov QWORD PTR [rcx+880], r15",
+ "mov rbx, rcx",
+ "mov rbp, rdi",
+ "mov r12, rsi",
+ "mov r13, rdx",
+ "mov r15d, 1",
+ "mov rdi, r13",
+ "add rdi, 2336",
+ "mov esi, 84",
+ "mov edx, 80",
+ "mov rcx, rbx",
+ "add rcx, 8192",
+ "mov r8d, 1024",
+ "call {vg_mldsa_hint_bit_unpack}",
+ "mov r15d, eax",
+ "test r15d, r15d",
+ "jne 20f",
+ "jmp 21f",
+ "20:",
+ "mov rdi, r13",
+ "add rdi, 32",
+ "mov esi, 576",
+ "mov edx, 131071",
+ "mov ecx, 131072",
+ "mov r8, rbx",
+ "add r8, 16384",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov esi, 130994",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, r13",
+ "add rdi, 608",
+ "mov esi, 576",
+ "mov edx, 131071",
+ "mov ecx, 131072",
+ "mov r8, rbx",
+ "add r8, 17408",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov esi, 130994",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, r13",
+ "add rdi, 1184",
+ "mov esi, 576",
+ "mov edx, 131071",
+ "mov ecx, 131072",
+ "mov r8, rbx",
+ "add r8, 18432",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov esi, 130994",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, r13",
+ "add rdi, 1760",
+ "mov esi, 576",
+ "mov edx, 131071",
+ "mov ecx, 131072",
+ "mov r8, rbx",
+ "add r8, 19456",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov esi, 130994",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "test r15d, r15d",
+ "jne 22f",
+ "jmp 23f",
+ "22:",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbp",
+ "add rsi, 0",
+ "mov ecx, 32",
+ "24:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 24b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 28672",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov ecx, 256",
+ "25:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 25b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov ecx, 256",
+ "26:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 26b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 30720",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov ecx, 256",
+ "27:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 27b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 31744",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov ecx, 256",
+ "28:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 28b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 36864",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov ecx, 256",
+ "29:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 29b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 37888",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov ecx, 256",
+ "210:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 210b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 38912",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov ecx, 256",
+ "211:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 211b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 39936",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov ecx, 256",
+ "212:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 212b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 45056",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 45056",
+ "mov ecx, 256",
+ "213:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 213b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 46080",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov ecx, 256",
+ "214:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 214b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 47104",
+ "mov ecx, 256",
+ "215:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 215b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 48128",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 48128",
+ "mov ecx, 256",
+ "216:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 216b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 53248",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 53248",
+ "mov ecx, 256",
+ "217:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 217b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 54272",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 54272",
+ "mov ecx, 256",
+ "218:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 218b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 55296",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 55296",
+ "mov ecx, 256",
+ "219:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 219b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 56320",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 56320",
+ "mov ecx, 256",
+ "220:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 220b",
+ "mov rdi, r13",
+ "add rdi, 0",
+ "mov esi, 32",
+ "mov edx, 39",
+ "mov rcx, rbx",
+ "add rcx, 23552",
+ "mov r8, rbx",
+ "add r8, 4096",
+ "call {vg_mldsa_sample_in_ball}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov ecx, 256",
+ "221:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 221b",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 28672",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 30720",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 31744",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 32",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 95232",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 43",
+ "mov rdx, rbx",
+ "add rdx, 1024",
+ "mov ecx, 192",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 36864",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 37888",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 38912",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 39936",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 352",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 95232",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 43",
+ "mov rdx, rbx",
+ "add rdx, 1216",
+ "mov ecx, 192",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 45056",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 46080",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 48128",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 672",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 10240",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 95232",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 43",
+ "mov rdx, rbx",
+ "add rdx, 1408",
+ "mov ecx, 192",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 53248",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 54272",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 55296",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 56320",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 992",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 11264",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 95232",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 43",
+ "mov rdx, rbx",
+ "add rdx, 1600",
+ "mov ecx, 192",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, r12",
+ "add rcx, 0",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 64",
+ "mov rcx, rbx",
+ "add rcx, 1024",
+ "mov r8d, 768",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 16",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "mov r8d, 32",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "mov rdi, r13",
+ "add rdi, 0",
+ "mov ecx, 32",
+ "mov edx, 0",
+ "222:",
+ "movzx eax, BYTE PTR [rsi]",
+ "movzx r8d, BYTE PTR [rdi]",
+ "xor rax, r8",
+ "or rdx, rax",
+ "add rsi, 1",
+ "add rdi, 1",
+ "sub rcx, 1",
+ "jne 222b",
+ "sub rdx, 1",
+ "sbb rax, rax",
+ "and r15d, eax",
+ "23:",
+ "21:",
+ "mov eax, r15d",
+ "mov r15, QWORD PTR [rbx+880]",
+ "mov r14, QWORD PTR [rbx+872]",
+ "mov r13, QWORD PTR [rbx+864]",
+ "mov r12, QWORD PTR [rbx+856]",
+ "mov rbp, QWORD PTR [rbx+848]",
+ "mov rbx, QWORD PTR [rbx+840]",
+ "ret",
+ vg_mldsa_hint_bit_unpack = sym super::mldsa::vg_mldsa_hint_bit_unpack,
+ vg_mldsa_bit_unpack = sym super::mldsa::vg_mldsa_bit_unpack,
+ vg_mldsa_norm_lt = sym super::mldsa::vg_mldsa_norm_lt,
+ vg_mldsa_rej_ntt_poly = sym super::mldsa::vg_mldsa_rej_ntt_poly,
+ vg_mldsa_sample_in_ball = sym super::mldsa::vg_mldsa_sample_in_ball,
+ vg_mldsa_ntt_avx2 = sym super::mldsa::vg_mldsa_ntt_avx2,
+ vg_mldsa_multiply_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_ntt_avx2,
+ vg_mldsa_multiply_add_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_add_ntt_avx2,
+ vg_mldsa_unpack_t1 = sym super::mldsa::vg_mldsa_unpack_t1,
+ vg_mldsa_sub_avx2 = sym super::mldsa::vg_mldsa_sub_avx2,
+ vg_mldsa_inv_ntt_avx2 = sym super::mldsa::vg_mldsa_inv_ntt_avx2,
+ vg_mldsa_use_hint = sym super::mldsa::vg_mldsa_use_hint,
+ vg_mldsa_simple_bit_pack = sym super::mldsa::vg_mldsa_simple_bit_pack,
+ vg_keccak_absorb = sym super::sha3::vg_keccak_absorb,
+ vg_keccak_pad = sym super::sha3::vg_keccak_pad,
+ vg_keccak_squeeze = sym super::sha3::vg_keccak_squeeze,
+ )
+}
+
/// ML-DSA-44 key generation from a seed, `ML-DSA.KeyGen_internal(ξ)` (FIPS 204 Algorithm 6): with the 32-byte seed `ξ` at `seed`, writes the public key to `*pk` and the private key to `*sk`. Returns 1 on success. Returns 0 if a loop reaches its bound, which is at least the limit of FIPS 204 Appendix C, Table 3 (this happens with probability about 2^-256 or less): the outputs are then unspecified, and the caller must destroy them and treat the operation as failed.
///
/// Contract: `VG.Spec.MlDsa.keyGenContract`. Constant time but for `ρ` and rejections: timing may depend on the pointers, on `ρ` (the first 32 bytes of the public key), and on which half-bytes of the SHAKE256 outputs `RejBoundedPoly` rejects (`rejBoundedLeak`, which is independent of the coefficients it samples), but not on anything else of the seed or the keys.
diff --git a/src/asm/x86_64/mldsa65.rs b/src/asm/x86_64/mldsa65.rs
index 6ff94ded7..6452825aa 100644
--- a/src/asm/x86_64/mldsa65.rs
+++ b/src/asm/x86_64/mldsa65.rs
@@ -2,6 +2,5175 @@
//! Verified `mldsa65` functions for `x86_64`.
#![allow(dead_code)]
+/// The CPU features `vg_mldsa65_keygen_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA65_KEYGEN_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// ML-DSA-65 key generation from a seed, `ML-DSA.KeyGen_internal(ξ)` (FIPS 204 Algorithm 6): with the 32-byte seed `ξ` at `seed`, writes the public key to `*pk` and the private key to `*sk`. Returns 1 on success. Returns 0 if a loop reaches its bound, which is at least the limit of FIPS 204 Appendix C, Table 3 (this happens with probability about 2^-256 or less): the outputs are then unspecified, and the caller must destroy them and treat the operation as failed.
+///
+/// Contract: `VG.Spec.MlDsa.keyGenContract`. Constant time but for `ρ` and rejections: timing may depend on the pointers, on `ρ` (the first 32 bytes of the public key), and on which half-bytes of the SHAKE256 outputs `RejBoundedPoly` rejects (`rejBoundedLeak`, which is independent of the coefficients it samples), but not on anything else of the seed or the keys.
+///
+/// The function saves its caller's callee-saved registers in `scratch`; its calls use the 32 bytes of stack below its return address.
+///
+/// It samples every polynomial of `A` and of `s1` and `s2` whatever the samplers return, and zeroes the polynomial of a sampler that fails rather than branching on it: its timing does not depend on whether key generation fails.
+///
+/// # Safety
+///
+/// * `seed` must be valid for reads of 32 bytes.
+/// * `pk` must be valid for reads and writes of 1952 bytes.
+/// * `sk` must be valid for reads and writes of 4032 bytes.
+/// * `scratch` must be valid for reads and writes of 103424 bytes.
+/// * `seed` must be random bytes from an approved RBG (FIPS 204 §3.6.1), or a seed so generated before.
+/// * `scratch` is working space: on return it holds intermediate values, which the caller must destroy (FIPS 204 §3.6.3).
+/// * `pk`, `sk` and `scratch` must not overlap each other or `seed` (distinct Rust objects never do).
+/// * None of `seed`, `pk`, `sk` and `scratch` may overlap the return address on the stack or the 32 bytes of stack below it, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa65_keygen_avx2(seed: *const [u8; 32], pk: *mut [u8; 1952], sk: *mut [u8; 4032], scratch: *mut [u64; 12928]) -> u32 {
+ core::arch::naked_asm!(
+ "mov QWORD PTR [rcx+840], rbx",
+ "mov QWORD PTR [rcx+848], rbp",
+ "mov QWORD PTR [rcx+856], r12",
+ "mov QWORD PTR [rcx+864], r13",
+ "mov QWORD PTR [rcx+872], r14",
+ "mov QWORD PTR [rcx+880], r15",
+ "mov rbx, rcx",
+ "mov rbp, rdi",
+ "mov r12, rsi",
+ "mov r13, rdx",
+ "mov r15d, 1",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+896], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+897], al",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbp",
+ "add rcx, 0",
+ "mov r8d, 32",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 32",
+ "mov rcx, rbx",
+ "add rcx, 896",
+ "mov r8d, 2",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 34",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbx",
+ "add rcx, 1024",
+ "mov r8d, 128",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 1024",
+ "mov ecx, 32",
+ "20:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 20b",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov rsi, rbx",
+ "add rsi, 1056",
+ "mov ecx, 64",
+ "21:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 21b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1281], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 4096",
+ "mov ecx, 256",
+ "22:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 22b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 5120",
+ "mov ecx, 256",
+ "23:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 23b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov ecx, 256",
+ "24:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 24b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 7168",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov ecx, 256",
+ "25:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 25b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov ecx, 256",
+ "26:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 26b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 9216",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov ecx, 256",
+ "27:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 27b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 10240",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 10240",
+ "mov ecx, 256",
+ "28:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 28b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 11264",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 11264",
+ "mov ecx, 256",
+ "29:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 29b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 12288",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 12288",
+ "mov ecx, 256",
+ "210:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 210b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 13312",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 13312",
+ "mov ecx, 256",
+ "211:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 211b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 14336",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 14336",
+ "mov ecx, 256",
+ "212:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 212b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 15360",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 15360",
+ "mov ecx, 256",
+ "213:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 213b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 16384",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov ecx, 256",
+ "214:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 214b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 17408",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov ecx, 256",
+ "215:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 215b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 18432",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov ecx, 256",
+ "216:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 216b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 19456",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov ecx, 256",
+ "217:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 217b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 20480",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov ecx, 256",
+ "218:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 218b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 21504",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 21504",
+ "mov ecx, 256",
+ "219:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 219b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 22528",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov ecx, 256",
+ "220:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 220b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov ecx, 256",
+ "221:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 221b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov ecx, 256",
+ "222:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 222b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov ecx, 256",
+ "223:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 223b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov ecx, 256",
+ "224:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 224b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 27648",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov ecx, 256",
+ "225:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 225b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 28672",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov ecx, 256",
+ "226:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 226b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov ecx, 256",
+ "227:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 227b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 30720",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov ecx, 256",
+ "228:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 228b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 31744",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov ecx, 256",
+ "229:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 229b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 32768",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov ecx, 256",
+ "230:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 230b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 33792",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov ecx, 256",
+ "231:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 231b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 4",
+ "mov rdx, rbx",
+ "add rdx, 34816",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov ecx, 256",
+ "232:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 232b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 4",
+ "mov rdx, rbx",
+ "add rdx, 35840",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov ecx, 256",
+ "233:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 233b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 4",
+ "mov rdx, rbx",
+ "add rdx, 36864",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov ecx, 256",
+ "234:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 234b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 4",
+ "mov rdx, rbx",
+ "add rdx, 37888",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov ecx, 256",
+ "235:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 235b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 4",
+ "mov rdx, rbx",
+ "add rdx, 38912",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov ecx, 256",
+ "236:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 236b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 4",
+ "mov rdx, rbx",
+ "add rdx, 39936",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov ecx, 256",
+ "237:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 237b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 4",
+ "mov rdx, rbx",
+ "add rdx, 40960",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 40960",
+ "mov ecx, 256",
+ "238:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 238b",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 4",
+ "mov rdx, rbx",
+ "add rdx, 41984",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 41984",
+ "mov ecx, 256",
+ "239:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 239b",
+ "mov eax, 8",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 4",
+ "mov rdx, rbx",
+ "add rdx, 43008",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 43008",
+ "mov ecx, 256",
+ "240:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 240b",
+ "mov eax, 9",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 4",
+ "mov rdx, rbx",
+ "add rdx, 44032",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 44032",
+ "mov ecx, 256",
+ "241:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 241b",
+ "mov eax, 10",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 4",
+ "mov rdx, rbx",
+ "add rdx, 45056",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 45056",
+ "mov ecx, 256",
+ "242:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 242b",
+ "mov rdi, r12",
+ "add rdi, 0",
+ "mov rsi, rbx",
+ "add rsi, 1024",
+ "mov ecx, 32",
+ "243:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 243b",
+ "mov rdi, r13",
+ "add rdi, 0",
+ "mov rsi, rbx",
+ "add rsi, 1024",
+ "mov ecx, 32",
+ "244:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 244b",
+ "mov rdi, r13",
+ "add rdi, 32",
+ "mov rsi, rbx",
+ "add rsi, 1120",
+ "mov ecx, 32",
+ "245:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 245b",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov esi, 4",
+ "mov edx, 4",
+ "mov rcx, r13",
+ "add rcx, 128",
+ "mov r8d, 128",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov esi, 4",
+ "mov edx, 4",
+ "mov rcx, r13",
+ "add rcx, 256",
+ "mov r8d, 128",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov esi, 4",
+ "mov edx, 4",
+ "mov rcx, r13",
+ "add rcx, 384",
+ "mov r8d, 128",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov esi, 4",
+ "mov edx, 4",
+ "mov rcx, r13",
+ "add rcx, 512",
+ "mov r8d, 128",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov esi, 4",
+ "mov edx, 4",
+ "mov rcx, r13",
+ "add rcx, 640",
+ "mov r8d, 128",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov esi, 4",
+ "mov edx, 4",
+ "mov rcx, r13",
+ "add rcx, 768",
+ "mov r8d, 128",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 40960",
+ "mov esi, 4",
+ "mov edx, 4",
+ "mov rcx, r13",
+ "add rcx, 896",
+ "mov r8d, 128",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 41984",
+ "mov esi, 4",
+ "mov edx, 4",
+ "mov rcx, r13",
+ "add rcx, 1024",
+ "mov r8d, 128",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 43008",
+ "mov esi, 4",
+ "mov edx, 4",
+ "mov rcx, r13",
+ "add rcx, 1152",
+ "mov r8d, 128",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 44032",
+ "mov esi, 4",
+ "mov edx, 4",
+ "mov rcx, r13",
+ "add rcx, 1280",
+ "mov r8d, 128",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 45056",
+ "mov esi, 4",
+ "mov edx, 4",
+ "mov rcx, r13",
+ "add rcx, 1408",
+ "mov r8d, 128",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "mov rdx, rbx",
+ "add rdx, 34816",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 35840",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "mov rdx, rbx",
+ "add rdx, 36864",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 7168",
+ "mov rdx, rbx",
+ "add rdx, 37888",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "mov rdx, rbx",
+ "add rdx, 38912",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 39936",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 48128",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 47104",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 32",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 48128",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 1536",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 9216",
+ "mov rdx, rbx",
+ "add rdx, 34816",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 10240",
+ "mov rdx, rbx",
+ "add rdx, 35840",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 11264",
+ "mov rdx, rbx",
+ "add rdx, 36864",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 12288",
+ "mov rdx, rbx",
+ "add rdx, 37888",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 13312",
+ "mov rdx, rbx",
+ "add rdx, 38912",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 40960",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 48128",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 47104",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 352",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 48128",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 1952",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 14336",
+ "mov rdx, rbx",
+ "add rdx, 34816",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 15360",
+ "mov rdx, rbx",
+ "add rdx, 35840",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 16384",
+ "mov rdx, rbx",
+ "add rdx, 36864",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 17408",
+ "mov rdx, rbx",
+ "add rdx, 37888",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 18432",
+ "mov rdx, rbx",
+ "add rdx, 38912",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 41984",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 48128",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 47104",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 672",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 48128",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 2368",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 19456",
+ "mov rdx, rbx",
+ "add rdx, 34816",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 20480",
+ "mov rdx, rbx",
+ "add rdx, 35840",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 21504",
+ "mov rdx, rbx",
+ "add rdx, 36864",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 22528",
+ "mov rdx, rbx",
+ "add rdx, 37888",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 38912",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 43008",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 48128",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 47104",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 992",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 48128",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 2784",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "mov rdx, rbx",
+ "add rdx, 34816",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "mov rdx, rbx",
+ "add rdx, 35840",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov rdx, rbx",
+ "add rdx, 36864",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 27648",
+ "mov rdx, rbx",
+ "add rdx, 37888",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 28672",
+ "mov rdx, rbx",
+ "add rdx, 38912",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 44032",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 48128",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 47104",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 1312",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 48128",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 3200",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov rdx, rbx",
+ "add rdx, 34816",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 30720",
+ "mov rdx, rbx",
+ "add rdx, 35840",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 31744",
+ "mov rdx, rbx",
+ "add rdx, 36864",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 32768",
+ "mov rdx, rbx",
+ "add rdx, 37888",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 33792",
+ "mov rdx, rbx",
+ "add rdx, 38912",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 45056",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 48128",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 47104",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 1632",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 48128",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 3616",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, r12",
+ "add rcx, 0",
+ "mov r8d, 1952",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 48",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, r13",
+ "add rcx, 64",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov eax, r15d",
+ "mov r15, QWORD PTR [rbx+880]",
+ "mov r14, QWORD PTR [rbx+872]",
+ "mov r13, QWORD PTR [rbx+864]",
+ "mov r12, QWORD PTR [rbx+856]",
+ "mov rbp, QWORD PTR [rbx+848]",
+ "mov rbx, QWORD PTR [rbx+840]",
+ "ret",
+ vg_keccak_absorb = sym super::sha3::vg_keccak_absorb,
+ vg_keccak_pad = sym super::sha3::vg_keccak_pad,
+ vg_keccak_squeeze = sym super::sha3::vg_keccak_squeeze,
+ vg_mldsa_rej_ntt_poly = sym super::mldsa::vg_mldsa_rej_ntt_poly,
+ vg_mldsa_rej_bounded_poly = sym super::mldsa::vg_mldsa_rej_bounded_poly,
+ vg_mldsa_bit_pack = sym super::mldsa::vg_mldsa_bit_pack,
+ vg_mldsa_ntt_avx2 = sym super::mldsa::vg_mldsa_ntt_avx2,
+ vg_mldsa_multiply_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_ntt_avx2,
+ vg_mldsa_multiply_add_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_add_ntt_avx2,
+ vg_mldsa_inv_ntt_avx2 = sym super::mldsa::vg_mldsa_inv_ntt_avx2,
+ vg_mldsa_add_avx2 = sym super::mldsa::vg_mldsa_add_avx2,
+ vg_mldsa_power2round = sym super::mldsa::vg_mldsa_power2round,
+ vg_mldsa_simple_bit_pack = sym super::mldsa::vg_mldsa_simple_bit_pack,
+ )
+}
+
+/// The CPU features `vg_mldsa65_sign_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA65_SIGN_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// ML-DSA-65 signing of a message representative, `ML-DSA.Sign_internal(sk, M′, rnd)` (FIPS 204 Algorithm 7) with `μ` computed by the caller: with the private key `*sk`, the 64-byte message representative `μ = H(tr ‖ M′, 64)` at `mu` (for the public key hash `tr`, bytes 64–127 of `*sk`) and the randomness `*rnd`, writes the signature to `*sig`. Returns 1 on success. Returns 0 if a loop reaches its bound, which is at least the limit of FIPS 204 Appendix C, Table 3 (this happens with probability about 2^-256 or less): the outputs are then unspecified, and the caller must destroy them and treat the operation as failed.
+///
+/// Contract: `VG.Spec.MlDsa.signContract`. Constant time but for `ρ` and the rejection sampling: timing may depend on the pointers, on `ρ` (the first 32 bytes of `*sk`), on the number of iterations of the signing loop and the commitment hash of each, and on the hint of the signature (`signLeak`), but not on anything else of the key, the message representative or the randomness.
+///
+/// The function saves its caller's callee-saved registers in `scratch`; its calls use the 24 bytes of stack below its return address.
+///
+/// The signing loop runs at most 814 iterations (FIPS 204 Appendix C). Each iteration computes every validity check and combines them without branching: the one branch on their result is the only place an iteration's outcome affects timing.
+///
+/// # Safety
+///
+/// * `sk` must be valid for reads of 4032 bytes.
+/// * `mu` must be valid for reads of 64 bytes.
+/// * `rnd` must be valid for reads of 32 bytes.
+/// * `sig` must be valid for reads and writes of 3309 bytes.
+/// * `scratch` must be valid for reads and writes of 103424 bytes.
+/// * `sk` must have been written by `vg_mldsa65_keygen`.
+/// * `rnd` must be fresh random bytes (FIPS 204 §3.6.1), or 32 zero bytes for deterministic signing.
+/// * `scratch` is working space: on return it holds intermediate values, which the caller must destroy (FIPS 204 §3.6.3).
+/// * `sig` and `scratch` must not overlap each other, `sk`, `mu` or `rnd` (distinct Rust objects never do).
+/// * None of `sk`, `mu`, `rnd`, `sig` and `scratch` may overlap the return address on the stack or the 24 bytes of stack below it, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa65_sign_avx2(sk: *const [u8; 4032], mu: *const [u8; 64], rnd: *const [u8; 32], sig: *mut [u8; 3309], scratch: *mut [u64; 12928]) -> u32 {
+ core::arch::naked_asm!(
+ "mov QWORD PTR [r8+840], rbx",
+ "mov QWORD PTR [r8+848], rbp",
+ "mov QWORD PTR [r8+856], r12",
+ "mov QWORD PTR [r8+864], r13",
+ "mov QWORD PTR [r8+872], r14",
+ "mov QWORD PTR [r8+880], r15",
+ "mov rbx, r8",
+ "mov rbp, rdi",
+ "mov r12, rsi",
+ "mov r13, rdx",
+ "mov r14, rcx",
+ "mov r15d, 1",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbp",
+ "add rsi, 0",
+ "mov ecx, 32",
+ "20:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 20b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 50176",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 51200",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 52224",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 53248",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 54272",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 55296",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 56320",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 57344",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 58368",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 59392",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 60416",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 61440",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 62464",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 63488",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 64512",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 65536",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 66560",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 67584",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 68608",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 69632",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 70656",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 71680",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 72704",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 73728",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 74752",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 75776",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 76800",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 77824",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 78848",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 79872",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "test r15d, r15d",
+ "jne 21f",
+ "jmp 22f",
+ "21:",
+ "mov rdi, rbp",
+ "add rdi, 128",
+ "mov esi, 128",
+ "mov edx, 4",
+ "mov ecx, 4",
+ "mov r8, rbx",
+ "add r8, 32768",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 256",
+ "mov esi, 128",
+ "mov edx, 4",
+ "mov ecx, 4",
+ "mov r8, rbx",
+ "add r8, 33792",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 384",
+ "mov esi, 128",
+ "mov edx, 4",
+ "mov ecx, 4",
+ "mov r8, rbx",
+ "add r8, 34816",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 512",
+ "mov esi, 128",
+ "mov edx, 4",
+ "mov ecx, 4",
+ "mov r8, rbx",
+ "add r8, 35840",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 640",
+ "mov esi, 128",
+ "mov edx, 4",
+ "mov ecx, 4",
+ "mov r8, rbx",
+ "add r8, 36864",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 768",
+ "mov esi, 128",
+ "mov edx, 4",
+ "mov ecx, 4",
+ "mov r8, rbx",
+ "add r8, 37888",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 896",
+ "mov esi, 128",
+ "mov edx, 4",
+ "mov ecx, 4",
+ "mov r8, rbx",
+ "add r8, 38912",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1024",
+ "mov esi, 128",
+ "mov edx, 4",
+ "mov ecx, 4",
+ "mov r8, rbx",
+ "add r8, 39936",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1152",
+ "mov esi, 128",
+ "mov edx, 4",
+ "mov ecx, 4",
+ "mov r8, rbx",
+ "add r8, 40960",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 40960",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1280",
+ "mov esi, 128",
+ "mov edx, 4",
+ "mov ecx, 4",
+ "mov r8, rbx",
+ "add r8, 41984",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 41984",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1408",
+ "mov esi, 128",
+ "mov edx, 4",
+ "mov ecx, 4",
+ "mov r8, rbx",
+ "add r8, 43008",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 43008",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1536",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 44032",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 44032",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1952",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 45056",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 45056",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 2368",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 46080",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 2784",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 47104",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 47104",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 3200",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 48128",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 48128",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 3616",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 49152",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 49152",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbp",
+ "add rcx, 32",
+ "mov r8d, 32",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 32",
+ "mov rcx, r13",
+ "add rcx, 0",
+ "mov r8d, 32",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 64",
+ "mov rcx, r12",
+ "add rcx, 0",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 128",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbx",
+ "add rcx, 960",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx+896], rax",
+ "mov eax, 814",
+ "mov QWORD PTR [rbx+888], rax",
+ "23:",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 0",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 524288",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 21504",
+ "mov rsi, rbx",
+ "add rsi, 16384",
+ "mov ecx, 1024",
+ "24:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 24b",
+ "mov rdi, rbx",
+ "add rdi, 21504",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 1",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 524288",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov rsi, rbx",
+ "add rsi, 17408",
+ "mov ecx, 1024",
+ "25:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 25b",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 2",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 524288",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov rsi, rbx",
+ "add rsi, 18432",
+ "mov ecx, 1024",
+ "26:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 26b",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 3",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 524288",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 19456",
+ "mov ecx, 1024",
+ "27:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 27b",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 4",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 524288",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 20480",
+ "mov ecx, 1024",
+ "28:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 28b",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 50176",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 51200",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 52224",
+ "mov rdx, rbx",
+ "add rdx, 23552",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 53248",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 54272",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov rsi, rbx",
+ "add rsi, 55296",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov rsi, rbx",
+ "add rsi, 56320",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov rsi, rbx",
+ "add rsi, 57344",
+ "mov rdx, rbx",
+ "add rdx, 23552",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov rsi, rbx",
+ "add rsi, 58368",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov rsi, rbx",
+ "add rsi, 59392",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 60416",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 61440",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 62464",
+ "mov rdx, rbx",
+ "add rdx, 23552",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 63488",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 64512",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov rsi, rbx",
+ "add rsi, 65536",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov rsi, rbx",
+ "add rsi, 66560",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov rsi, rbx",
+ "add rsi, 67584",
+ "mov rdx, rbx",
+ "add rdx, 23552",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov rsi, rbx",
+ "add rsi, 68608",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov rsi, rbx",
+ "add rsi, 69632",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov rsi, rbx",
+ "add rsi, 70656",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov rsi, rbx",
+ "add rsi, 71680",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov rsi, rbx",
+ "add rsi, 72704",
+ "mov rdx, rbx",
+ "add rdx, 23552",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov rsi, rbx",
+ "add rsi, 73728",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov rsi, rbx",
+ "add rsi, 74752",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov rsi, rbx",
+ "add rsi, 75776",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov rsi, rbx",
+ "add rsi, 76800",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov rsi, rbx",
+ "add rsi, 77824",
+ "mov rdx, rbx",
+ "add rdx, 23552",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov rsi, rbx",
+ "add rsi, 78848",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov rsi, rbx",
+ "add rsi, 79872",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 2176",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 2304",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 2432",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 2560",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 2688",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, r12",
+ "add rcx, 0",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 64",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "mov r8d, 768",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 16",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbx",
+ "add rcx, 1040",
+ "mov r8d, 48",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov rdi, rbx",
+ "add rdi, 1040",
+ "mov esi, 48",
+ "mov edx, 49",
+ "mov rcx, rbx",
+ "add rcx, 5120",
+ "mov r8, rbx",
+ "add r8, 3072",
+ "call {vg_mldsa_sample_in_ball}",
+ "test eax, eax",
+ "jne 29f",
+ "mov r15d, 0",
+ "mov eax, 1",
+ "mov QWORD PTR [rbx+888], rax",
+ "jmp 210f",
+ "29:",
+ "mov rdi, rbx",
+ "add rdi, 5120",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov r15d, 1",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx+904], rax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 32768",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov esi, 524092",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 33792",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov esi, 524092",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 34816",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov esi, 524092",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 35840",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov esi, 524092",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 36864",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov esi, 524092",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 37888",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 261692",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 38912",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 261692",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 39936",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 261692",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 40960",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 261692",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 41984",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 261692",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 43008",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 261692",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 44032",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 261888",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov ecx, 1024",
+ "211:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 211b",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 10240",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 45056",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 261888",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 27648",
+ "mov ecx, 1024",
+ "212:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 212b",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 27648",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 27648",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 11264",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 46080",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 261888",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 28672",
+ "mov ecx, 1024",
+ "213:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 213b",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 28672",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 28672",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 12288",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 47104",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 261888",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov ecx, 1024",
+ "214:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 214b",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 13312",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 48128",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 261888",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 30720",
+ "mov ecx, 1024",
+ "215:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 215b",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 30720",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 30720",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 14336",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 49152",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 261888",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 31744",
+ "mov ecx, 1024",
+ "216:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 216b",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 31744",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 31744",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 15360",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov eax, DWORD PTR [rbx+904]",
+ "sub rax, 56",
+ "shr rax, 63",
+ "and r15d, eax",
+ "test r15d, r15d",
+ "jne 217f",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 5",
+ "mov QWORD PTR [rbx+896], rax",
+ "jmp 218f",
+ "217:",
+ "mov eax, 1",
+ "mov QWORD PTR [rbx+888], rax",
+ "218:",
+ "210:",
+ "mov rax, QWORD PTR [rbx+888]",
+ "sub rax, 1",
+ "mov QWORD PTR [rbx+888], rax",
+ "jne 23b",
+ "test r15d, r15d",
+ "jne 219f",
+ "jmp 220f",
+ "219:",
+ "mov rdi, r14",
+ "add rdi, 0",
+ "mov rsi, rbx",
+ "add rsi, 1040",
+ "mov ecx, 48",
+ "221:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 221b",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov esi, 524287",
+ "mov edx, 524288",
+ "mov rcx, r14",
+ "add rcx, 48",
+ "mov r8d, 640",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov esi, 524287",
+ "mov edx, 524288",
+ "mov rcx, r14",
+ "add rcx, 688",
+ "mov r8d, 640",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov esi, 524287",
+ "mov edx, 524288",
+ "mov rcx, r14",
+ "add rcx, 1328",
+ "mov r8d, 640",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov esi, 524287",
+ "mov edx, 524288",
+ "mov rcx, r14",
+ "add rcx, 1968",
+ "mov r8d, 640",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov esi, 524287",
+ "mov edx, 524288",
+ "mov rcx, r14",
+ "add rcx, 2608",
+ "mov r8d, 640",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 10240",
+ "mov esi, 1536",
+ "mov edx, 55",
+ "mov rcx, r14",
+ "add rcx, 3248",
+ "mov r8d, 61",
+ "call {vg_mldsa_hint_bit_pack}",
+ "220:",
+ "22:",
+ "mov eax, r15d",
+ "mov r15, QWORD PTR [rbx+880]",
+ "mov r14, QWORD PTR [rbx+872]",
+ "mov r13, QWORD PTR [rbx+864]",
+ "mov r12, QWORD PTR [rbx+856]",
+ "mov rbp, QWORD PTR [rbx+848]",
+ "mov rbx, QWORD PTR [rbx+840]",
+ "ret",
+ vg_mldsa_rej_ntt_poly = sym super::mldsa::vg_mldsa_rej_ntt_poly,
+ vg_mldsa_bit_unpack = sym super::mldsa::vg_mldsa_bit_unpack,
+ vg_mldsa_ntt_avx2 = sym super::mldsa::vg_mldsa_ntt_avx2,
+ vg_keccak_absorb = sym super::sha3::vg_keccak_absorb,
+ vg_keccak_pad = sym super::sha3::vg_keccak_pad,
+ vg_keccak_squeeze = sym super::sha3::vg_keccak_squeeze,
+ vg_mldsa_expand_mask_poly = sym super::mldsa::vg_mldsa_expand_mask_poly,
+ vg_mldsa_multiply_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_ntt_avx2,
+ vg_mldsa_multiply_add_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_add_ntt_avx2,
+ vg_mldsa_inv_ntt_avx2 = sym super::mldsa::vg_mldsa_inv_ntt_avx2,
+ vg_mldsa_high_bits = sym super::mldsa::vg_mldsa_high_bits,
+ vg_mldsa_simple_bit_pack = sym super::mldsa::vg_mldsa_simple_bit_pack,
+ vg_mldsa_sample_in_ball = sym super::mldsa::vg_mldsa_sample_in_ball,
+ vg_mldsa_add_avx2 = sym super::mldsa::vg_mldsa_add_avx2,
+ vg_mldsa_norm_lt = sym super::mldsa::vg_mldsa_norm_lt,
+ vg_mldsa_sub_avx2 = sym super::mldsa::vg_mldsa_sub_avx2,
+ vg_mldsa_low_bits = sym super::mldsa::vg_mldsa_low_bits,
+ vg_mldsa_make_hint = sym super::mldsa::vg_mldsa_make_hint,
+ vg_mldsa_bit_pack = sym super::mldsa::vg_mldsa_bit_pack,
+ vg_mldsa_hint_bit_pack = sym super::mldsa::vg_mldsa_hint_bit_pack,
+ )
+}
+
+/// The CPU features `vg_mldsa65_verify_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA65_VERIFY_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// ML-DSA-65 verification of a signature of a message representative, `ML-DSA.Verify_internal(pk, M′, σ)` (FIPS 204 Algorithm 8) with `μ` computed by the caller: with the public key `*pk`, the 64-byte message representative `μ = H(H(pk, 64) ‖ M′, 64)` at `mu` and the signature `*sig`, returns 1 if the signature is valid, and 0 if it is not or if a loop reaches its bound, which is at least the limit of FIPS 204 Appendix C, Table 3 (this happens with probability about 2^-256 or less).
+///
+/// Contract: `VG.Spec.MlDsa.verifyContract`. Not constant time: timing may depend on the public key, the message representative and the signature.
+///
+/// It calls the `vg_mldsa_*` primitives and the SHAKE256 sponge. The samplers' results are combined without a branch, so the only branches depend on the public key and the signature.
+///
+/// # Safety
+///
+/// * `pk` must be valid for reads of 1952 bytes.
+/// * `mu` must be valid for reads of 64 bytes.
+/// * `sig` must be valid for reads of 3309 bytes.
+/// * `scratch` must be valid for reads and writes of 103424 bytes.
+/// * `scratch` is working space: on return it holds intermediate values, which the caller must destroy (FIPS 204 §3.6.3).
+/// * `scratch` must not overlap `pk`, `mu` or `sig` (distinct Rust objects never do).
+/// * None of `pk`, `mu`, `sig` and `scratch` may overlap the return address on the stack or the 24 bytes of stack below it, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa65_verify_avx2(pk: *const [u8; 1952], mu: *const [u8; 64], sig: *const [u8; 3309], scratch: *mut [u64; 12928]) -> u32 {
+ core::arch::naked_asm!(
+ "mov QWORD PTR [rcx+840], rbx",
+ "mov QWORD PTR [rcx+848], rbp",
+ "mov QWORD PTR [rcx+856], r12",
+ "mov QWORD PTR [rcx+864], r13",
+ "mov QWORD PTR [rcx+872], r14",
+ "mov QWORD PTR [rcx+880], r15",
+ "mov rbx, rcx",
+ "mov rbp, rdi",
+ "mov r12, rsi",
+ "mov r13, rdx",
+ "mov r15d, 1",
+ "mov rdi, r13",
+ "add rdi, 3248",
+ "mov esi, 61",
+ "mov edx, 55",
+ "mov rcx, rbx",
+ "add rcx, 8192",
+ "mov r8d, 1536",
+ "call {vg_mldsa_hint_bit_unpack}",
+ "mov r15d, eax",
+ "test r15d, r15d",
+ "jne 20f",
+ "jmp 21f",
+ "20:",
+ "mov rdi, r13",
+ "add rdi, 48",
+ "mov esi, 640",
+ "mov edx, 524287",
+ "mov ecx, 524288",
+ "mov r8, rbx",
+ "add r8, 16384",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov esi, 524092",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, r13",
+ "add rdi, 688",
+ "mov esi, 640",
+ "mov edx, 524287",
+ "mov ecx, 524288",
+ "mov r8, rbx",
+ "add r8, 17408",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov esi, 524092",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, r13",
+ "add rdi, 1328",
+ "mov esi, 640",
+ "mov edx, 524287",
+ "mov ecx, 524288",
+ "mov r8, rbx",
+ "add r8, 18432",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov esi, 524092",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, r13",
+ "add rdi, 1968",
+ "mov esi, 640",
+ "mov edx, 524287",
+ "mov ecx, 524288",
+ "mov r8, rbx",
+ "add r8, 19456",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov esi, 524092",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, r13",
+ "add rdi, 2608",
+ "mov esi, 640",
+ "mov edx, 524287",
+ "mov ecx, 524288",
+ "mov r8, rbx",
+ "add r8, 20480",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov esi, 524092",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "test r15d, r15d",
+ "jne 22f",
+ "jmp 23f",
+ "22:",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbp",
+ "add rsi, 0",
+ "mov ecx, 32",
+ "24:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 24b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 28672",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov ecx, 256",
+ "25:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 25b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov ecx, 256",
+ "26:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 26b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 30720",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov ecx, 256",
+ "27:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 27b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 31744",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov ecx, 256",
+ "28:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 28b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 32768",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov ecx, 256",
+ "29:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 29b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 36864",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov ecx, 256",
+ "210:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 210b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 37888",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov ecx, 256",
+ "211:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 211b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 38912",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov ecx, 256",
+ "212:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 212b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 39936",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov ecx, 256",
+ "213:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 213b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 40960",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 40960",
+ "mov ecx, 256",
+ "214:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 214b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 45056",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 45056",
+ "mov ecx, 256",
+ "215:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 215b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 46080",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov ecx, 256",
+ "216:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 216b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 47104",
+ "mov ecx, 256",
+ "217:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 217b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 48128",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 48128",
+ "mov ecx, 256",
+ "218:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 218b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 49152",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 49152",
+ "mov ecx, 256",
+ "219:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 219b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 53248",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 53248",
+ "mov ecx, 256",
+ "220:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 220b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 54272",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 54272",
+ "mov ecx, 256",
+ "221:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 221b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 55296",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 55296",
+ "mov ecx, 256",
+ "222:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 222b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 56320",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 56320",
+ "mov ecx, 256",
+ "223:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 223b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 57344",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 57344",
+ "mov ecx, 256",
+ "224:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 224b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 61440",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 61440",
+ "mov ecx, 256",
+ "225:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 225b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 62464",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 62464",
+ "mov ecx, 256",
+ "226:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 226b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 63488",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 63488",
+ "mov ecx, 256",
+ "227:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 227b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 64512",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 64512",
+ "mov ecx, 256",
+ "228:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 228b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 65536",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 65536",
+ "mov ecx, 256",
+ "229:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 229b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 69632",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 69632",
+ "mov ecx, 256",
+ "230:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 230b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 70656",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 70656",
+ "mov ecx, 256",
+ "231:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 231b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 71680",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 71680",
+ "mov ecx, 256",
+ "232:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 232b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 72704",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 72704",
+ "mov ecx, 256",
+ "233:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 233b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 73728",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 73728",
+ "mov ecx, 256",
+ "234:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 234b",
+ "mov rdi, r13",
+ "add rdi, 0",
+ "mov esi, 48",
+ "mov edx, 49",
+ "mov rcx, rbx",
+ "add rcx, 23552",
+ "mov r8, rbx",
+ "add r8, 4096",
+ "call {vg_mldsa_sample_in_ball}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov ecx, 256",
+ "235:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 235b",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 28672",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 30720",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 31744",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 32768",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 32",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 1024",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 36864",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 37888",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 38912",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 39936",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 40960",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 352",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 1152",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 45056",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 46080",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 48128",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 49152",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 672",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 10240",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 1280",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 53248",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 54272",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 55296",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 56320",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 57344",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 992",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 11264",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 1408",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 61440",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 62464",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 63488",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 64512",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 65536",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1312",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 12288",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 1536",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 69632",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 70656",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 71680",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 72704",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 73728",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1632",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 13312",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 1664",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, r12",
+ "add rcx, 0",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 64",
+ "mov rcx, rbx",
+ "add rcx, 1024",
+ "mov r8d, 768",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 16",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "mov r8d, 48",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "mov rdi, r13",
+ "add rdi, 0",
+ "mov ecx, 48",
+ "mov edx, 0",
+ "236:",
+ "movzx eax, BYTE PTR [rsi]",
+ "movzx r8d, BYTE PTR [rdi]",
+ "xor rax, r8",
+ "or rdx, rax",
+ "add rsi, 1",
+ "add rdi, 1",
+ "sub rcx, 1",
+ "jne 236b",
+ "sub rdx, 1",
+ "sbb rax, rax",
+ "and r15d, eax",
+ "23:",
+ "21:",
+ "mov eax, r15d",
+ "mov r15, QWORD PTR [rbx+880]",
+ "mov r14, QWORD PTR [rbx+872]",
+ "mov r13, QWORD PTR [rbx+864]",
+ "mov r12, QWORD PTR [rbx+856]",
+ "mov rbp, QWORD PTR [rbx+848]",
+ "mov rbx, QWORD PTR [rbx+840]",
+ "ret",
+ vg_mldsa_hint_bit_unpack = sym super::mldsa::vg_mldsa_hint_bit_unpack,
+ vg_mldsa_bit_unpack = sym super::mldsa::vg_mldsa_bit_unpack,
+ vg_mldsa_norm_lt = sym super::mldsa::vg_mldsa_norm_lt,
+ vg_mldsa_rej_ntt_poly = sym super::mldsa::vg_mldsa_rej_ntt_poly,
+ vg_mldsa_sample_in_ball = sym super::mldsa::vg_mldsa_sample_in_ball,
+ vg_mldsa_ntt_avx2 = sym super::mldsa::vg_mldsa_ntt_avx2,
+ vg_mldsa_multiply_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_ntt_avx2,
+ vg_mldsa_multiply_add_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_add_ntt_avx2,
+ vg_mldsa_unpack_t1 = sym super::mldsa::vg_mldsa_unpack_t1,
+ vg_mldsa_sub_avx2 = sym super::mldsa::vg_mldsa_sub_avx2,
+ vg_mldsa_inv_ntt_avx2 = sym super::mldsa::vg_mldsa_inv_ntt_avx2,
+ vg_mldsa_use_hint = sym super::mldsa::vg_mldsa_use_hint,
+ vg_mldsa_simple_bit_pack = sym super::mldsa::vg_mldsa_simple_bit_pack,
+ vg_keccak_absorb = sym super::sha3::vg_keccak_absorb,
+ vg_keccak_pad = sym super::sha3::vg_keccak_pad,
+ vg_keccak_squeeze = sym super::sha3::vg_keccak_squeeze,
+ )
+}
+
/// ML-DSA-65 key generation from a seed, `ML-DSA.KeyGen_internal(ξ)` (FIPS 204 Algorithm 6): with the 32-byte seed `ξ` at `seed`, writes the public key to `*pk` and the private key to `*sk`. Returns 1 on success. Returns 0 if a loop reaches its bound, which is at least the limit of FIPS 204 Appendix C, Table 3 (this happens with probability about 2^-256 or less): the outputs are then unspecified, and the caller must destroy them and treat the operation as failed.
///
/// Contract: `VG.Spec.MlDsa.keyGenContract`. Constant time but for `ρ` and rejections: timing may depend on the pointers, on `ρ` (the first 32 bytes of the public key), and on which half-bytes of the SHAKE256 outputs `RejBoundedPoly` rejects (`rejBoundedLeak`, which is independent of the coefficients it samples), but not on anything else of the seed or the keys.
diff --git a/src/asm/x86_64/mldsa87.rs b/src/asm/x86_64/mldsa87.rs
index be3306d5c..79f684dd0 100644
--- a/src/asm/x86_64/mldsa87.rs
+++ b/src/asm/x86_64/mldsa87.rs
@@ -2,6 +2,7989 @@
//! Verified `mldsa87` functions for `x86_64`.
#![allow(dead_code)]
+/// The CPU features `vg_mldsa87_keygen_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA87_KEYGEN_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// ML-DSA-87 key generation from a seed, `ML-DSA.KeyGen_internal(ξ)` (FIPS 204 Algorithm 6): with the 32-byte seed `ξ` at `seed`, writes the public key to `*pk` and the private key to `*sk`. Returns 1 on success. Returns 0 if a loop reaches its bound, which is at least the limit of FIPS 204 Appendix C, Table 3 (this happens with probability about 2^-256 or less): the outputs are then unspecified, and the caller must destroy them and treat the operation as failed.
+///
+/// Contract: `VG.Spec.MlDsa.keyGenContract`. Constant time but for `ρ` and rejections: timing may depend on the pointers, on `ρ` (the first 32 bytes of the public key), and on which half-bytes of the SHAKE256 outputs `RejBoundedPoly` rejects (`rejBoundedLeak`, which is independent of the coefficients it samples), but not on anything else of the seed or the keys.
+///
+/// The function saves its caller's callee-saved registers in `scratch`; its calls use the 32 bytes of stack below its return address.
+///
+/// It samples every polynomial of `A` and of `s1` and `s2` whatever the samplers return, and zeroes the polynomial of a sampler that fails rather than branching on it: its timing does not depend on whether key generation fails.
+///
+/// # Safety
+///
+/// * `seed` must be valid for reads of 32 bytes.
+/// * `pk` must be valid for reads and writes of 2592 bytes.
+/// * `sk` must be valid for reads and writes of 4896 bytes.
+/// * `scratch` must be valid for reads and writes of 144384 bytes.
+/// * `seed` must be random bytes from an approved RBG (FIPS 204 §3.6.1), or a seed so generated before.
+/// * `scratch` is working space: on return it holds intermediate values, which the caller must destroy (FIPS 204 §3.6.3).
+/// * `pk`, `sk` and `scratch` must not overlap each other or `seed` (distinct Rust objects never do).
+/// * None of `seed`, `pk`, `sk` and `scratch` may overlap the return address on the stack or the 32 bytes of stack below it, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa87_keygen_avx2(seed: *const [u8; 32], pk: *mut [u8; 2592], sk: *mut [u8; 4896], scratch: *mut [u64; 18048]) -> u32 {
+ core::arch::naked_asm!(
+ "mov QWORD PTR [rcx+840], rbx",
+ "mov QWORD PTR [rcx+848], rbp",
+ "mov QWORD PTR [rcx+856], r12",
+ "mov QWORD PTR [rcx+864], r13",
+ "mov QWORD PTR [rcx+872], r14",
+ "mov QWORD PTR [rcx+880], r15",
+ "mov rbx, rcx",
+ "mov rbp, rdi",
+ "mov r12, rsi",
+ "mov r13, rdx",
+ "mov r15d, 1",
+ "mov eax, 8",
+ "mov BYTE PTR [rbx+896], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+897], al",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbp",
+ "add rcx, 0",
+ "mov r8d, 32",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 32",
+ "mov rcx, rbx",
+ "add rcx, 896",
+ "mov r8d, 2",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 34",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbx",
+ "add rcx, 1024",
+ "mov r8d, 128",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 1024",
+ "mov ecx, 32",
+ "20:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 20b",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov rsi, rbx",
+ "add rsi, 1056",
+ "mov ecx, 64",
+ "21:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 21b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1281], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 4096",
+ "mov ecx, 256",
+ "22:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 22b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 5120",
+ "mov ecx, 256",
+ "23:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 23b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov ecx, 256",
+ "24:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 24b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 7168",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov ecx, 256",
+ "25:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 25b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov ecx, 256",
+ "26:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 26b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 9216",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov ecx, 256",
+ "27:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 27b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 10240",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 10240",
+ "mov ecx, 256",
+ "28:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 28b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 11264",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 11264",
+ "mov ecx, 256",
+ "29:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 29b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 12288",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 12288",
+ "mov ecx, 256",
+ "210:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 210b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 13312",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 13312",
+ "mov ecx, 256",
+ "211:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 211b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 14336",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 14336",
+ "mov ecx, 256",
+ "212:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 212b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 15360",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 15360",
+ "mov ecx, 256",
+ "213:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 213b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 16384",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov ecx, 256",
+ "214:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 214b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 17408",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov ecx, 256",
+ "215:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 215b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 18432",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov ecx, 256",
+ "216:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 216b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 19456",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov ecx, 256",
+ "217:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 217b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 20480",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov ecx, 256",
+ "218:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 218b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 21504",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 21504",
+ "mov ecx, 256",
+ "219:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 219b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 22528",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov ecx, 256",
+ "220:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 220b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov ecx, 256",
+ "221:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 221b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov ecx, 256",
+ "222:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 222b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov ecx, 256",
+ "223:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 223b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov ecx, 256",
+ "224:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 224b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 27648",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov ecx, 256",
+ "225:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 225b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 28672",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov ecx, 256",
+ "226:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 226b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov ecx, 256",
+ "227:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 227b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 30720",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov ecx, 256",
+ "228:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 228b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 31744",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov ecx, 256",
+ "229:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 229b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 32768",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov ecx, 256",
+ "230:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 230b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 33792",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov ecx, 256",
+ "231:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 231b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 34816",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov ecx, 256",
+ "232:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 232b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 35840",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov ecx, 256",
+ "233:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 233b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 36864",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov ecx, 256",
+ "234:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 234b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 37888",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov ecx, 256",
+ "235:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 235b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 38912",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov ecx, 256",
+ "236:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 236b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 39936",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov ecx, 256",
+ "237:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 237b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 40960",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 40960",
+ "mov ecx, 256",
+ "238:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 238b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 41984",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 41984",
+ "mov ecx, 256",
+ "239:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 239b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 43008",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 43008",
+ "mov ecx, 256",
+ "240:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 240b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 44032",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 44032",
+ "mov ecx, 256",
+ "241:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 241b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 45056",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 45056",
+ "mov ecx, 256",
+ "242:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 242b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 46080",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov ecx, 256",
+ "243:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 243b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 47104",
+ "mov ecx, 256",
+ "244:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 244b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 48128",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 48128",
+ "mov ecx, 256",
+ "245:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 245b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 49152",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 49152",
+ "mov ecx, 256",
+ "246:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 246b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 50176",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 50176",
+ "mov ecx, 256",
+ "247:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 247b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 51200",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 51200",
+ "mov ecx, 256",
+ "248:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 248b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 52224",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 52224",
+ "mov ecx, 256",
+ "249:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 249b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 53248",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 53248",
+ "mov ecx, 256",
+ "250:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 250b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 54272",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 54272",
+ "mov ecx, 256",
+ "251:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 251b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 55296",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 55296",
+ "mov ecx, 256",
+ "252:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 252b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 56320",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 56320",
+ "mov ecx, 256",
+ "253:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 253b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 57344",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 57344",
+ "mov ecx, 256",
+ "254:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 254b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 58368",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 58368",
+ "mov ecx, 256",
+ "255:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 255b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 59392",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 59392",
+ "mov ecx, 256",
+ "256:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 256b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1184], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+1185], al",
+ "mov rdi, rbx",
+ "add rdi, 1152",
+ "mov rsi, rbx",
+ "add rsi, 60416",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 60416",
+ "mov ecx, 256",
+ "257:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 257b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 61440",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 61440",
+ "mov ecx, 256",
+ "258:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 258b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 62464",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 62464",
+ "mov ecx, 256",
+ "259:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 259b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 63488",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 63488",
+ "mov ecx, 256",
+ "260:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 260b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 64512",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 64512",
+ "mov ecx, 256",
+ "261:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 261b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 65536",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 65536",
+ "mov ecx, 256",
+ "262:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 262b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 66560",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 66560",
+ "mov ecx, 256",
+ "263:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 263b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 67584",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 67584",
+ "mov ecx, 256",
+ "264:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 264b",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 68608",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 68608",
+ "mov ecx, 256",
+ "265:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 265b",
+ "mov eax, 8",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 69632",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 69632",
+ "mov ecx, 256",
+ "266:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 266b",
+ "mov eax, 9",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 70656",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 70656",
+ "mov ecx, 256",
+ "267:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 267b",
+ "mov eax, 10",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 71680",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 71680",
+ "mov ecx, 256",
+ "268:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 268b",
+ "mov eax, 11",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 72704",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 72704",
+ "mov ecx, 256",
+ "269:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 269b",
+ "mov eax, 12",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 73728",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 73728",
+ "mov ecx, 256",
+ "270:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 270b",
+ "mov eax, 13",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 74752",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 74752",
+ "mov ecx, 256",
+ "271:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 271b",
+ "mov eax, 14",
+ "mov BYTE PTR [rbx+1280], al",
+ "mov rdi, rbx",
+ "add rdi, 1216",
+ "mov esi, 2",
+ "mov rdx, rbx",
+ "add rdx, 75776",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "call {vg_mldsa_rej_bounded_poly}",
+ "and r15d, eax",
+ "mov r8d, 0",
+ "sub r8d, eax",
+ "mov rdi, rbx",
+ "add rdi, 75776",
+ "mov ecx, 256",
+ "272:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, r8d",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 272b",
+ "mov rdi, r12",
+ "add rdi, 0",
+ "mov rsi, rbx",
+ "add rsi, 1024",
+ "mov ecx, 32",
+ "273:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 273b",
+ "mov rdi, r13",
+ "add rdi, 0",
+ "mov rsi, rbx",
+ "add rsi, 1024",
+ "mov ecx, 32",
+ "274:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 274b",
+ "mov rdi, r13",
+ "add rdi, 32",
+ "mov rsi, rbx",
+ "add rsi, 1120",
+ "mov ecx, 32",
+ "275:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 275b",
+ "mov rdi, rbx",
+ "add rdi, 61440",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 128",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 62464",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 224",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 63488",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 320",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 64512",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 416",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 65536",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 512",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 66560",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 608",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 67584",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 704",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 68608",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 800",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 69632",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 896",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 70656",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 992",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 71680",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 1088",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 72704",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 1184",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 73728",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 1280",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 74752",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 1376",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 75776",
+ "mov esi, 2",
+ "mov edx, 2",
+ "mov rcx, r13",
+ "add rcx, 1472",
+ "mov r8d, 96",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 61440",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 62464",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 63488",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 64512",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 65536",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 66560",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 67584",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "mov rdx, rbx",
+ "add rdx, 61440",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 62464",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "mov rdx, rbx",
+ "add rdx, 63488",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 7168",
+ "mov rdx, rbx",
+ "add rdx, 64512",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "mov rdx, rbx",
+ "add rdx, 65536",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 9216",
+ "mov rdx, rbx",
+ "add rdx, 66560",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 10240",
+ "mov rdx, rbx",
+ "add rdx, 67584",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 68608",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 77824",
+ "mov rdx, rbx",
+ "add rdx, 78848",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 77824",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 32",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 78848",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 1568",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 11264",
+ "mov rdx, rbx",
+ "add rdx, 61440",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 12288",
+ "mov rdx, rbx",
+ "add rdx, 62464",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 13312",
+ "mov rdx, rbx",
+ "add rdx, 63488",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 14336",
+ "mov rdx, rbx",
+ "add rdx, 64512",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 15360",
+ "mov rdx, rbx",
+ "add rdx, 65536",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 16384",
+ "mov rdx, rbx",
+ "add rdx, 66560",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 17408",
+ "mov rdx, rbx",
+ "add rdx, 67584",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 69632",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 77824",
+ "mov rdx, rbx",
+ "add rdx, 78848",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 77824",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 352",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 78848",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 1984",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 18432",
+ "mov rdx, rbx",
+ "add rdx, 61440",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 19456",
+ "mov rdx, rbx",
+ "add rdx, 62464",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 20480",
+ "mov rdx, rbx",
+ "add rdx, 63488",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 21504",
+ "mov rdx, rbx",
+ "add rdx, 64512",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 22528",
+ "mov rdx, rbx",
+ "add rdx, 65536",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 66560",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "mov rdx, rbx",
+ "add rdx, 67584",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 70656",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 77824",
+ "mov rdx, rbx",
+ "add rdx, 78848",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 77824",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 672",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 78848",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 2400",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "mov rdx, rbx",
+ "add rdx, 61440",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov rdx, rbx",
+ "add rdx, 62464",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 27648",
+ "mov rdx, rbx",
+ "add rdx, 63488",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 28672",
+ "mov rdx, rbx",
+ "add rdx, 64512",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov rdx, rbx",
+ "add rdx, 65536",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 30720",
+ "mov rdx, rbx",
+ "add rdx, 66560",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 31744",
+ "mov rdx, rbx",
+ "add rdx, 67584",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 71680",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 77824",
+ "mov rdx, rbx",
+ "add rdx, 78848",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 77824",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 992",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 78848",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 2816",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 32768",
+ "mov rdx, rbx",
+ "add rdx, 61440",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 33792",
+ "mov rdx, rbx",
+ "add rdx, 62464",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 34816",
+ "mov rdx, rbx",
+ "add rdx, 63488",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 35840",
+ "mov rdx, rbx",
+ "add rdx, 64512",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 36864",
+ "mov rdx, rbx",
+ "add rdx, 65536",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 37888",
+ "mov rdx, rbx",
+ "add rdx, 66560",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 38912",
+ "mov rdx, rbx",
+ "add rdx, 67584",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 72704",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 77824",
+ "mov rdx, rbx",
+ "add rdx, 78848",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 77824",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 1312",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 78848",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 3232",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 39936",
+ "mov rdx, rbx",
+ "add rdx, 61440",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 40960",
+ "mov rdx, rbx",
+ "add rdx, 62464",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 41984",
+ "mov rdx, rbx",
+ "add rdx, 63488",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 43008",
+ "mov rdx, rbx",
+ "add rdx, 64512",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 44032",
+ "mov rdx, rbx",
+ "add rdx, 65536",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 45056",
+ "mov rdx, rbx",
+ "add rdx, 66560",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 46080",
+ "mov rdx, rbx",
+ "add rdx, 67584",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 73728",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 77824",
+ "mov rdx, rbx",
+ "add rdx, 78848",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 77824",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 1632",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 78848",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 3648",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 61440",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 48128",
+ "mov rdx, rbx",
+ "add rdx, 62464",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 49152",
+ "mov rdx, rbx",
+ "add rdx, 63488",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 50176",
+ "mov rdx, rbx",
+ "add rdx, 64512",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 51200",
+ "mov rdx, rbx",
+ "add rdx, 65536",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 52224",
+ "mov rdx, rbx",
+ "add rdx, 66560",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 53248",
+ "mov rdx, rbx",
+ "add rdx, 67584",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 74752",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 77824",
+ "mov rdx, rbx",
+ "add rdx, 78848",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 77824",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 1952",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 78848",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 4064",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 54272",
+ "mov rdx, rbx",
+ "add rdx, 61440",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 55296",
+ "mov rdx, rbx",
+ "add rdx, 62464",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 56320",
+ "mov rdx, rbx",
+ "add rdx, 63488",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 57344",
+ "mov rdx, rbx",
+ "add rdx, 64512",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 58368",
+ "mov rdx, rbx",
+ "add rdx, 65536",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 59392",
+ "mov rdx, rbx",
+ "add rdx, 66560",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 60416",
+ "mov rdx, rbx",
+ "add rdx, 67584",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 75776",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 76800",
+ "mov rsi, rbx",
+ "add rsi, 77824",
+ "mov rdx, rbx",
+ "add rdx, 78848",
+ "call {vg_mldsa_power2round}",
+ "mov rdi, rbx",
+ "add rdi, 77824",
+ "mov esi, 1023",
+ "mov rdx, r12",
+ "add rdx, 2272",
+ "mov ecx, 320",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 78848",
+ "mov esi, 4095",
+ "mov edx, 4096",
+ "mov rcx, r13",
+ "add rcx, 4480",
+ "mov r8d, 416",
+ "call {vg_mldsa_bit_pack}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, r12",
+ "add rcx, 0",
+ "mov r8d, 2592",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 8",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, r13",
+ "add rcx, 64",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov eax, r15d",
+ "mov r15, QWORD PTR [rbx+880]",
+ "mov r14, QWORD PTR [rbx+872]",
+ "mov r13, QWORD PTR [rbx+864]",
+ "mov r12, QWORD PTR [rbx+856]",
+ "mov rbp, QWORD PTR [rbx+848]",
+ "mov rbx, QWORD PTR [rbx+840]",
+ "ret",
+ vg_keccak_absorb = sym super::sha3::vg_keccak_absorb,
+ vg_keccak_pad = sym super::sha3::vg_keccak_pad,
+ vg_keccak_squeeze = sym super::sha3::vg_keccak_squeeze,
+ vg_mldsa_rej_ntt_poly = sym super::mldsa::vg_mldsa_rej_ntt_poly,
+ vg_mldsa_rej_bounded_poly = sym super::mldsa::vg_mldsa_rej_bounded_poly,
+ vg_mldsa_bit_pack = sym super::mldsa::vg_mldsa_bit_pack,
+ vg_mldsa_ntt_avx2 = sym super::mldsa::vg_mldsa_ntt_avx2,
+ vg_mldsa_multiply_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_ntt_avx2,
+ vg_mldsa_multiply_add_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_add_ntt_avx2,
+ vg_mldsa_inv_ntt_avx2 = sym super::mldsa::vg_mldsa_inv_ntt_avx2,
+ vg_mldsa_add_avx2 = sym super::mldsa::vg_mldsa_add_avx2,
+ vg_mldsa_power2round = sym super::mldsa::vg_mldsa_power2round,
+ vg_mldsa_simple_bit_pack = sym super::mldsa::vg_mldsa_simple_bit_pack,
+ )
+}
+
+/// The CPU features `vg_mldsa87_sign_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA87_SIGN_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// ML-DSA-87 signing of a message representative, `ML-DSA.Sign_internal(sk, M′, rnd)` (FIPS 204 Algorithm 7) with `μ` computed by the caller: with the private key `*sk`, the 64-byte message representative `μ = H(tr ‖ M′, 64)` at `mu` (for the public key hash `tr`, bytes 64–127 of `*sk`) and the randomness `*rnd`, writes the signature to `*sig`. Returns 1 on success. Returns 0 if a loop reaches its bound, which is at least the limit of FIPS 204 Appendix C, Table 3 (this happens with probability about 2^-256 or less): the outputs are then unspecified, and the caller must destroy them and treat the operation as failed.
+///
+/// Contract: `VG.Spec.MlDsa.signContract`. Constant time but for `ρ` and the rejection sampling: timing may depend on the pointers, on `ρ` (the first 32 bytes of `*sk`), on the number of iterations of the signing loop and the commitment hash of each, and on the hint of the signature (`signLeak`), but not on anything else of the key, the message representative or the randomness.
+///
+/// The function saves its caller's callee-saved registers in `scratch`; its calls use the 24 bytes of stack below its return address.
+///
+/// The signing loop runs at most 814 iterations (FIPS 204 Appendix C). Each iteration computes every validity check and combines them without branching: the one branch on their result is the only place an iteration's outcome affects timing.
+///
+/// # Safety
+///
+/// * `sk` must be valid for reads of 4896 bytes.
+/// * `mu` must be valid for reads of 64 bytes.
+/// * `rnd` must be valid for reads of 32 bytes.
+/// * `sig` must be valid for reads and writes of 4627 bytes.
+/// * `scratch` must be valid for reads and writes of 144384 bytes.
+/// * `sk` must have been written by `vg_mldsa87_keygen`.
+/// * `rnd` must be fresh random bytes (FIPS 204 §3.6.1), or 32 zero bytes for deterministic signing.
+/// * `scratch` is working space: on return it holds intermediate values, which the caller must destroy (FIPS 204 §3.6.3).
+/// * `sig` and `scratch` must not overlap each other, `sk`, `mu` or `rnd` (distinct Rust objects never do).
+/// * None of `sk`, `mu`, `rnd`, `sig` and `scratch` may overlap the return address on the stack or the 24 bytes of stack below it, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa87_sign_avx2(sk: *const [u8; 4896], mu: *const [u8; 64], rnd: *const [u8; 32], sig: *mut [u8; 4627], scratch: *mut [u64; 18048]) -> u32 {
+ core::arch::naked_asm!(
+ "mov QWORD PTR [r8+840], rbx",
+ "mov QWORD PTR [r8+848], rbp",
+ "mov QWORD PTR [r8+856], r12",
+ "mov QWORD PTR [r8+864], r13",
+ "mov QWORD PTR [r8+872], r14",
+ "mov QWORD PTR [r8+880], r15",
+ "mov rbx, r8",
+ "mov rbp, rdi",
+ "mov r12, rsi",
+ "mov r13, rdx",
+ "mov r14, rcx",
+ "mov r15d, 1",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbp",
+ "add rsi, 0",
+ "mov ecx, 32",
+ "20:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 20b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 64512",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 65536",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 66560",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 67584",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 68608",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 69632",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 70656",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 71680",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 72704",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 73728",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 74752",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 75776",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 76800",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 77824",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 78848",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 79872",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 80896",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 81920",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 82944",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 83968",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 84992",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 86016",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 87040",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 88064",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 89088",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 90112",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 91136",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 92160",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 93184",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 94208",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 95232",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 96256",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 97280",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 98304",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 99328",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 100352",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 101376",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 102400",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 103424",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 104448",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 105472",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 106496",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 107520",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 108544",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 109568",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 110592",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 111616",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 112640",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 113664",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 114688",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 115712",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 116736",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 117760",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 118784",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 119808",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+944], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+945], al",
+ "mov rdi, rbx",
+ "add rdi, 912",
+ "mov rsi, rbx",
+ "add rsi, 120832",
+ "mov rdx, rbx",
+ "add rdx, 3072",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "test r15d, r15d",
+ "jne 21f",
+ "jmp 22f",
+ "21:",
+ "mov rdi, rbp",
+ "add rdi, 128",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 40960",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 40960",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 224",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 41984",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 41984",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 320",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 43008",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 43008",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 416",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 44032",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 44032",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 512",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 45056",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 45056",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 608",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 46080",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 704",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 47104",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 47104",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 800",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 48128",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 48128",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 896",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 49152",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 49152",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 992",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 50176",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 50176",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1088",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 51200",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 51200",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1184",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 52224",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 52224",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1280",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 53248",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 53248",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1376",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 54272",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 54272",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1472",
+ "mov esi, 96",
+ "mov edx, 2",
+ "mov ecx, 2",
+ "mov r8, rbx",
+ "add r8, 55296",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 55296",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1568",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 56320",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 56320",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1984",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 57344",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 57344",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 2400",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 58368",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 58368",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 2816",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 59392",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 59392",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 3232",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 60416",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 60416",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 3648",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 61440",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 61440",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 4064",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 62464",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 62464",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 4480",
+ "mov esi, 416",
+ "mov edx, 4095",
+ "mov ecx, 4096",
+ "mov r8, rbx",
+ "add r8, 63488",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 63488",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbp",
+ "add rcx, 32",
+ "mov r8d, 32",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 32",
+ "mov rcx, r13",
+ "add rcx, 0",
+ "mov r8d, 32",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 64",
+ "mov rcx, r12",
+ "add rcx, 0",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 128",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbx",
+ "add rcx, 960",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx+896], rax",
+ "mov eax, 814",
+ "mov QWORD PTR [rbx+888], rax",
+ "23:",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 0",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 524288",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 18432",
+ "mov ecx, 1024",
+ "24:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 24b",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 1",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 524288",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 19456",
+ "mov ecx, 1024",
+ "25:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 25b",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 2",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 524288",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov rsi, rbx",
+ "add rsi, 20480",
+ "mov ecx, 1024",
+ "26:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 26b",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 3",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 524288",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 21504",
+ "mov ecx, 1024",
+ "27:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 27b",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 4",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 524288",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov rsi, rbx",
+ "add rsi, 22528",
+ "mov ecx, 1024",
+ "28:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 28b",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 5",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 524288",
+ "mov rdx, rbx",
+ "add rdx, 23552",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov ecx, 1024",
+ "29:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 29b",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 6",
+ "mov BYTE PTR [rbx+1024], al",
+ "shr rax, 8",
+ "mov BYTE PTR [rbx+1025], al",
+ "mov rdi, rbx",
+ "add rdi, 960",
+ "mov esi, 524288",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "mov rcx, rbx",
+ "add rcx, 3072",
+ "call {vg_mldsa_expand_mask_poly}",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "mov ecx, 1024",
+ "210:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 210b",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov rsi, rbx",
+ "add rsi, 64512",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov rsi, rbx",
+ "add rsi, 65536",
+ "mov rdx, rbx",
+ "add rdx, 26624",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov rsi, rbx",
+ "add rsi, 66560",
+ "mov rdx, rbx",
+ "add rdx, 27648",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov rsi, rbx",
+ "add rsi, 67584",
+ "mov rdx, rbx",
+ "add rdx, 28672",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov rsi, rbx",
+ "add rsi, 68608",
+ "mov rdx, rbx",
+ "add rdx, 29696",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov rsi, rbx",
+ "add rsi, 69632",
+ "mov rdx, rbx",
+ "add rdx, 30720",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov rsi, rbx",
+ "add rsi, 70656",
+ "mov rdx, rbx",
+ "add rdx, 31744",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov rsi, rbx",
+ "add rsi, 71680",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov rsi, rbx",
+ "add rsi, 72704",
+ "mov rdx, rbx",
+ "add rdx, 26624",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov rsi, rbx",
+ "add rsi, 73728",
+ "mov rdx, rbx",
+ "add rdx, 27648",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov rsi, rbx",
+ "add rsi, 74752",
+ "mov rdx, rbx",
+ "add rdx, 28672",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov rsi, rbx",
+ "add rsi, 75776",
+ "mov rdx, rbx",
+ "add rdx, 29696",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov rsi, rbx",
+ "add rsi, 76800",
+ "mov rdx, rbx",
+ "add rdx, 30720",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov rsi, rbx",
+ "add rsi, 77824",
+ "mov rdx, rbx",
+ "add rdx, 31744",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov rsi, rbx",
+ "add rsi, 78848",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov rsi, rbx",
+ "add rsi, 79872",
+ "mov rdx, rbx",
+ "add rdx, 26624",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov rsi, rbx",
+ "add rsi, 80896",
+ "mov rdx, rbx",
+ "add rdx, 27648",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov rsi, rbx",
+ "add rsi, 81920",
+ "mov rdx, rbx",
+ "add rdx, 28672",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov rsi, rbx",
+ "add rsi, 82944",
+ "mov rdx, rbx",
+ "add rdx, 29696",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov rsi, rbx",
+ "add rsi, 83968",
+ "mov rdx, rbx",
+ "add rdx, 30720",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov rsi, rbx",
+ "add rsi, 84992",
+ "mov rdx, rbx",
+ "add rdx, 31744",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov rsi, rbx",
+ "add rsi, 86016",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov rsi, rbx",
+ "add rsi, 87040",
+ "mov rdx, rbx",
+ "add rdx, 26624",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov rsi, rbx",
+ "add rsi, 88064",
+ "mov rdx, rbx",
+ "add rdx, 27648",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov rsi, rbx",
+ "add rsi, 89088",
+ "mov rdx, rbx",
+ "add rdx, 28672",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov rsi, rbx",
+ "add rsi, 90112",
+ "mov rdx, rbx",
+ "add rdx, 29696",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov rsi, rbx",
+ "add rsi, 91136",
+ "mov rdx, rbx",
+ "add rdx, 30720",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov rsi, rbx",
+ "add rsi, 92160",
+ "mov rdx, rbx",
+ "add rdx, 31744",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov rsi, rbx",
+ "add rsi, 93184",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov rsi, rbx",
+ "add rsi, 94208",
+ "mov rdx, rbx",
+ "add rdx, 26624",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov rsi, rbx",
+ "add rsi, 95232",
+ "mov rdx, rbx",
+ "add rdx, 27648",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov rsi, rbx",
+ "add rsi, 96256",
+ "mov rdx, rbx",
+ "add rdx, 28672",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov rsi, rbx",
+ "add rsi, 97280",
+ "mov rdx, rbx",
+ "add rdx, 29696",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov rsi, rbx",
+ "add rsi, 98304",
+ "mov rdx, rbx",
+ "add rdx, 30720",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov rsi, rbx",
+ "add rsi, 99328",
+ "mov rdx, rbx",
+ "add rdx, 31744",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov rsi, rbx",
+ "add rsi, 100352",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov rsi, rbx",
+ "add rsi, 101376",
+ "mov rdx, rbx",
+ "add rdx, 26624",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov rsi, rbx",
+ "add rsi, 102400",
+ "mov rdx, rbx",
+ "add rdx, 27648",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov rsi, rbx",
+ "add rsi, 103424",
+ "mov rdx, rbx",
+ "add rdx, 28672",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov rsi, rbx",
+ "add rsi, 104448",
+ "mov rdx, rbx",
+ "add rdx, 29696",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov rsi, rbx",
+ "add rsi, 105472",
+ "mov rdx, rbx",
+ "add rdx, 30720",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov rsi, rbx",
+ "add rsi, 106496",
+ "mov rdx, rbx",
+ "add rdx, 31744",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov rsi, rbx",
+ "add rsi, 107520",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov rsi, rbx",
+ "add rsi, 108544",
+ "mov rdx, rbx",
+ "add rdx, 26624",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov rsi, rbx",
+ "add rsi, 109568",
+ "mov rdx, rbx",
+ "add rdx, 27648",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov rsi, rbx",
+ "add rsi, 110592",
+ "mov rdx, rbx",
+ "add rdx, 28672",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov rsi, rbx",
+ "add rsi, 111616",
+ "mov rdx, rbx",
+ "add rdx, 29696",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov rsi, rbx",
+ "add rsi, 112640",
+ "mov rdx, rbx",
+ "add rdx, 30720",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov rsi, rbx",
+ "add rsi, 113664",
+ "mov rdx, rbx",
+ "add rdx, 31744",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov rsi, rbx",
+ "add rsi, 114688",
+ "mov rdx, rbx",
+ "add rdx, 25600",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov rsi, rbx",
+ "add rsi, 115712",
+ "mov rdx, rbx",
+ "add rdx, 26624",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov rsi, rbx",
+ "add rsi, 116736",
+ "mov rdx, rbx",
+ "add rdx, 27648",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov rsi, rbx",
+ "add rsi, 117760",
+ "mov rdx, rbx",
+ "add rdx, 28672",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov rsi, rbx",
+ "add rsi, 118784",
+ "mov rdx, rbx",
+ "add rdx, 29696",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov rsi, rbx",
+ "add rsi, 119808",
+ "mov rdx, rbx",
+ "add rdx, 30720",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov rsi, rbx",
+ "add rsi, 120832",
+ "mov rdx, rbx",
+ "add rdx, 31744",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 2048",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 2176",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 2304",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 2432",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 2560",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 2688",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 2816",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 6144",
+ "call {vg_mldsa_high_bits}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 2944",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, r12",
+ "add rcx, 0",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 64",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "mov r8d, 1024",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbx",
+ "add rcx, 1040",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov rdi, rbx",
+ "add rdi, 1040",
+ "mov esi, 64",
+ "mov edx, 60",
+ "mov rcx, rbx",
+ "add rcx, 5120",
+ "mov r8, rbx",
+ "add r8, 3072",
+ "call {vg_mldsa_sample_in_ball}",
+ "test eax, eax",
+ "jne 211f",
+ "mov r15d, 0",
+ "mov eax, 1",
+ "mov QWORD PTR [rbx+888], rax",
+ "jmp 212f",
+ "211:",
+ "mov rdi, rbx",
+ "add rdi, 5120",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov r15d, 1",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx+904], rax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 40960",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov esi, 524168",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 41984",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov esi, 524168",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 43008",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov esi, 524168",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 44032",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 21504",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 21504",
+ "mov esi, 524168",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 45056",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov esi, 524168",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 46080",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov esi, 524168",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 47104",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov esi, 524168",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 48128",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 261768",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 49152",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 261768",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 50176",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 261768",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 51200",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 261768",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 52224",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 261768",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 53248",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 261768",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 54272",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 261768",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 55296",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 6144",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov rsi, rbx",
+ "add rsi, 6144",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov esi, 261888",
+ "mov rdx, rbx",
+ "add rdx, 7168",
+ "call {vg_mldsa_low_bits}",
+ "mov rdi, rbx",
+ "add rdi, 7168",
+ "mov esi, 261768",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 56320",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 261888",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 32768",
+ "mov ecx, 1024",
+ "213:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 213b",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 32768",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 32768",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 10240",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 57344",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 261888",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 33792",
+ "mov ecx, 1024",
+ "214:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 214b",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 33792",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 33792",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 11264",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 58368",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 261888",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 34816",
+ "mov ecx, 1024",
+ "215:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 215b",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 34816",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 34816",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 12288",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 59392",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 261888",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 35840",
+ "mov ecx, 1024",
+ "216:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 216b",
+ "mov rdi, rbx",
+ "add rdi, 35840",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 35840",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 35840",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 13312",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 60416",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 261888",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 36864",
+ "mov ecx, 1024",
+ "217:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 217b",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 36864",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 36864",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 14336",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 61440",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 261888",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 37888",
+ "mov ecx, 1024",
+ "218:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 218b",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 37888",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 37888",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 15360",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 62464",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 261888",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 38912",
+ "mov ecx, 1024",
+ "219:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 219b",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 38912",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 38912",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 16384",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 5120",
+ "mov rdx, rbx",
+ "add rdx, 63488",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 3072",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov esi, 261888",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 39936",
+ "mov ecx, 1024",
+ "220:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 220b",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov rsi, rbx",
+ "add rsi, 8192",
+ "call {vg_mldsa_add_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 39936",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 39936",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 17408",
+ "call {vg_mldsa_make_hint}",
+ "mov ecx, DWORD PTR [rbx+904]",
+ "add ecx, eax",
+ "mov QWORD PTR [rbx+904], rcx",
+ "mov eax, DWORD PTR [rbx+904]",
+ "sub rax, 76",
+ "shr rax, 63",
+ "and r15d, eax",
+ "test r15d, r15d",
+ "jne 221f",
+ "mov rax, QWORD PTR [rbx+896]",
+ "add rax, 7",
+ "mov QWORD PTR [rbx+896], rax",
+ "jmp 222f",
+ "221:",
+ "mov eax, 1",
+ "mov QWORD PTR [rbx+888], rax",
+ "222:",
+ "212:",
+ "mov rax, QWORD PTR [rbx+888]",
+ "sub rax, 1",
+ "mov QWORD PTR [rbx+888], rax",
+ "jne 23b",
+ "test r15d, r15d",
+ "jne 223f",
+ "jmp 224f",
+ "223:",
+ "mov rdi, r14",
+ "add rdi, 0",
+ "mov rsi, rbx",
+ "add rsi, 1040",
+ "mov ecx, 64",
+ "225:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 225b",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov esi, 524287",
+ "mov edx, 524288",
+ "mov rcx, r14",
+ "add rcx, 64",
+ "mov r8d, 640",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov esi, 524287",
+ "mov edx, 524288",
+ "mov rcx, r14",
+ "add rcx, 704",
+ "mov r8d, 640",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov esi, 524287",
+ "mov edx, 524288",
+ "mov rcx, r14",
+ "add rcx, 1344",
+ "mov r8d, 640",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 21504",
+ "mov esi, 524287",
+ "mov edx, 524288",
+ "mov rcx, r14",
+ "add rcx, 1984",
+ "mov r8d, 640",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov esi, 524287",
+ "mov edx, 524288",
+ "mov rcx, r14",
+ "add rcx, 2624",
+ "mov r8d, 640",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov esi, 524287",
+ "mov edx, 524288",
+ "mov rcx, r14",
+ "add rcx, 3264",
+ "mov r8d, 640",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov esi, 524287",
+ "mov edx, 524288",
+ "mov rcx, r14",
+ "add rcx, 3904",
+ "mov r8d, 640",
+ "call {vg_mldsa_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 10240",
+ "mov esi, 2048",
+ "mov edx, 75",
+ "mov rcx, r14",
+ "add rcx, 4544",
+ "mov r8d, 83",
+ "call {vg_mldsa_hint_bit_pack}",
+ "224:",
+ "22:",
+ "mov eax, r15d",
+ "mov r15, QWORD PTR [rbx+880]",
+ "mov r14, QWORD PTR [rbx+872]",
+ "mov r13, QWORD PTR [rbx+864]",
+ "mov r12, QWORD PTR [rbx+856]",
+ "mov rbp, QWORD PTR [rbx+848]",
+ "mov rbx, QWORD PTR [rbx+840]",
+ "ret",
+ vg_mldsa_rej_ntt_poly = sym super::mldsa::vg_mldsa_rej_ntt_poly,
+ vg_mldsa_bit_unpack = sym super::mldsa::vg_mldsa_bit_unpack,
+ vg_mldsa_ntt_avx2 = sym super::mldsa::vg_mldsa_ntt_avx2,
+ vg_keccak_absorb = sym super::sha3::vg_keccak_absorb,
+ vg_keccak_pad = sym super::sha3::vg_keccak_pad,
+ vg_keccak_squeeze = sym super::sha3::vg_keccak_squeeze,
+ vg_mldsa_expand_mask_poly = sym super::mldsa::vg_mldsa_expand_mask_poly,
+ vg_mldsa_multiply_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_ntt_avx2,
+ vg_mldsa_multiply_add_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_add_ntt_avx2,
+ vg_mldsa_inv_ntt_avx2 = sym super::mldsa::vg_mldsa_inv_ntt_avx2,
+ vg_mldsa_high_bits = sym super::mldsa::vg_mldsa_high_bits,
+ vg_mldsa_simple_bit_pack = sym super::mldsa::vg_mldsa_simple_bit_pack,
+ vg_mldsa_sample_in_ball = sym super::mldsa::vg_mldsa_sample_in_ball,
+ vg_mldsa_add_avx2 = sym super::mldsa::vg_mldsa_add_avx2,
+ vg_mldsa_norm_lt = sym super::mldsa::vg_mldsa_norm_lt,
+ vg_mldsa_sub_avx2 = sym super::mldsa::vg_mldsa_sub_avx2,
+ vg_mldsa_low_bits = sym super::mldsa::vg_mldsa_low_bits,
+ vg_mldsa_make_hint = sym super::mldsa::vg_mldsa_make_hint,
+ vg_mldsa_bit_pack = sym super::mldsa::vg_mldsa_bit_pack,
+ vg_mldsa_hint_bit_pack = sym super::mldsa::vg_mldsa_hint_bit_pack,
+ )
+}
+
+/// The CPU features `vg_mldsa87_verify_avx2` requires (`Artifact.features`).
+pub(crate) const VG_MLDSA87_VERIFY_AVX2_FEATURES: &[&str] = &["avx", "avx2"];
+
+/// ML-DSA-87 verification of a signature of a message representative, `ML-DSA.Verify_internal(pk, M′, σ)` (FIPS 204 Algorithm 8) with `μ` computed by the caller: with the public key `*pk`, the 64-byte message representative `μ = H(H(pk, 64) ‖ M′, 64)` at `mu` and the signature `*sig`, returns 1 if the signature is valid, and 0 if it is not or if a loop reaches its bound, which is at least the limit of FIPS 204 Appendix C, Table 3 (this happens with probability about 2^-256 or less).
+///
+/// Contract: `VG.Spec.MlDsa.verifyContract`. Not constant time: timing may depend on the public key, the message representative and the signature.
+///
+/// It calls the `vg_mldsa_*` primitives and the SHAKE256 sponge. The samplers' results are combined without a branch, so the only branches depend on the public key and the signature.
+///
+/// # Safety
+///
+/// * `pk` must be valid for reads of 2592 bytes.
+/// * `mu` must be valid for reads of 64 bytes.
+/// * `sig` must be valid for reads of 4627 bytes.
+/// * `scratch` must be valid for reads and writes of 144384 bytes.
+/// * `scratch` is working space: on return it holds intermediate values, which the caller must destroy (FIPS 204 §3.6.3).
+/// * `scratch` must not overlap `pk`, `mu` or `sig` (distinct Rust objects never do).
+/// * None of `pk`, `mu`, `sig` and `scratch` may overlap the return address on the stack or the 24 bytes of stack below it, or wrap around the end of the address space (no Rust object does).
+/// * The CPU must support the `avx` and `avx2` target features.
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_mldsa87_verify_avx2(pk: *const [u8; 2592], mu: *const [u8; 64], sig: *const [u8; 4627], scratch: *mut [u64; 18048]) -> u32 {
+ core::arch::naked_asm!(
+ "mov QWORD PTR [rcx+840], rbx",
+ "mov QWORD PTR [rcx+848], rbp",
+ "mov QWORD PTR [rcx+856], r12",
+ "mov QWORD PTR [rcx+864], r13",
+ "mov QWORD PTR [rcx+872], r14",
+ "mov QWORD PTR [rcx+880], r15",
+ "mov rbx, rcx",
+ "mov rbp, rdi",
+ "mov r12, rsi",
+ "mov r13, rdx",
+ "mov r15d, 1",
+ "mov rdi, r13",
+ "add rdi, 4544",
+ "mov esi, 83",
+ "mov edx, 75",
+ "mov rcx, rbx",
+ "add rcx, 8192",
+ "mov r8d, 2048",
+ "call {vg_mldsa_hint_bit_unpack}",
+ "mov r15d, eax",
+ "test r15d, r15d",
+ "jne 20f",
+ "jmp 21f",
+ "20:",
+ "mov rdi, r13",
+ "add rdi, 64",
+ "mov esi, 640",
+ "mov edx, 524287",
+ "mov ecx, 524288",
+ "mov r8, rbx",
+ "add r8, 16384",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov esi, 524168",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, r13",
+ "add rdi, 704",
+ "mov esi, 640",
+ "mov edx, 524287",
+ "mov ecx, 524288",
+ "mov r8, rbx",
+ "add r8, 17408",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov esi, 524168",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, r13",
+ "add rdi, 1344",
+ "mov esi, 640",
+ "mov edx, 524287",
+ "mov ecx, 524288",
+ "mov r8, rbx",
+ "add r8, 18432",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov esi, 524168",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, r13",
+ "add rdi, 1984",
+ "mov esi, 640",
+ "mov edx, 524287",
+ "mov ecx, 524288",
+ "mov r8, rbx",
+ "add r8, 19456",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov esi, 524168",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, r13",
+ "add rdi, 2624",
+ "mov esi, 640",
+ "mov edx, 524287",
+ "mov ecx, 524288",
+ "mov r8, rbx",
+ "add r8, 20480",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov esi, 524168",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, r13",
+ "add rdi, 3264",
+ "mov esi, 640",
+ "mov edx, 524287",
+ "mov ecx, 524288",
+ "mov r8, rbx",
+ "add r8, 21504",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 21504",
+ "mov esi, 524168",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "mov rdi, r13",
+ "add rdi, 3904",
+ "mov esi, 640",
+ "mov edx, 524287",
+ "mov ecx, 524288",
+ "mov r8, rbx",
+ "add r8, 22528",
+ "call {vg_mldsa_bit_unpack}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov esi, 524168",
+ "call {vg_mldsa_norm_lt}",
+ "and r15d, eax",
+ "test r15d, r15d",
+ "jne 22f",
+ "jmp 23f",
+ "22:",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbp",
+ "add rsi, 0",
+ "mov ecx, 32",
+ "24:",
+ "movzx eax, BYTE PTR [rsi]",
+ "mov BYTE PTR [rdi], al",
+ "add rdi, 1",
+ "add rsi, 1",
+ "sub rcx, 1",
+ "jne 24b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 28672",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 28672",
+ "mov ecx, 256",
+ "25:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 25b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 29696",
+ "mov ecx, 256",
+ "26:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 26b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 30720",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 30720",
+ "mov ecx, 256",
+ "27:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 27b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 31744",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 31744",
+ "mov ecx, 256",
+ "28:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 28b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 32768",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 32768",
+ "mov ecx, 256",
+ "29:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 29b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 33792",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 33792",
+ "mov ecx, 256",
+ "210:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 210b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 34816",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 34816",
+ "mov ecx, 256",
+ "211:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 211b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 36864",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 36864",
+ "mov ecx, 256",
+ "212:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 212b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 37888",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 37888",
+ "mov ecx, 256",
+ "213:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 213b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 38912",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 38912",
+ "mov ecx, 256",
+ "214:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 214b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 39936",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 39936",
+ "mov ecx, 256",
+ "215:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 215b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 40960",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 40960",
+ "mov ecx, 256",
+ "216:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 216b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 41984",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 41984",
+ "mov ecx, 256",
+ "217:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 217b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 43008",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 43008",
+ "mov ecx, 256",
+ "218:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 218b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 45056",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 45056",
+ "mov ecx, 256",
+ "219:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 219b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 46080",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 46080",
+ "mov ecx, 256",
+ "220:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 220b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 47104",
+ "mov ecx, 256",
+ "221:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 221b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 48128",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 48128",
+ "mov ecx, 256",
+ "222:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 222b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 49152",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 49152",
+ "mov ecx, 256",
+ "223:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 223b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 50176",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 50176",
+ "mov ecx, 256",
+ "224:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 224b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 51200",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 51200",
+ "mov ecx, 256",
+ "225:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 225b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 53248",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 53248",
+ "mov ecx, 256",
+ "226:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 226b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 54272",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 54272",
+ "mov ecx, 256",
+ "227:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 227b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 55296",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 55296",
+ "mov ecx, 256",
+ "228:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 228b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 56320",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 56320",
+ "mov ecx, 256",
+ "229:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 229b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 57344",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 57344",
+ "mov ecx, 256",
+ "230:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 230b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 58368",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 58368",
+ "mov ecx, 256",
+ "231:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 231b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 59392",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 59392",
+ "mov ecx, 256",
+ "232:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 232b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 61440",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 61440",
+ "mov ecx, 256",
+ "233:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 233b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 62464",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 62464",
+ "mov ecx, 256",
+ "234:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 234b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 63488",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 63488",
+ "mov ecx, 256",
+ "235:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 235b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 64512",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 64512",
+ "mov ecx, 256",
+ "236:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 236b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 65536",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 65536",
+ "mov ecx, 256",
+ "237:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 237b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 66560",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 66560",
+ "mov ecx, 256",
+ "238:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 238b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 67584",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 67584",
+ "mov ecx, 256",
+ "239:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 239b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 69632",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 69632",
+ "mov ecx, 256",
+ "240:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 240b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 70656",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 70656",
+ "mov ecx, 256",
+ "241:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 241b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 71680",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 71680",
+ "mov ecx, 256",
+ "242:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 242b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 72704",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 72704",
+ "mov ecx, 256",
+ "243:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 243b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 73728",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 73728",
+ "mov ecx, 256",
+ "244:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 244b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 74752",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 74752",
+ "mov ecx, 256",
+ "245:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 245b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 75776",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 75776",
+ "mov ecx, 256",
+ "246:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 246b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 77824",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 77824",
+ "mov ecx, 256",
+ "247:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 247b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 78848",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 78848",
+ "mov ecx, 256",
+ "248:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 248b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 79872",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 79872",
+ "mov ecx, 256",
+ "249:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 249b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 80896",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 80896",
+ "mov ecx, 256",
+ "250:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 250b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 81920",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 81920",
+ "mov ecx, 256",
+ "251:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 251b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 82944",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 82944",
+ "mov ecx, 256",
+ "252:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 252b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 83968",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 83968",
+ "mov ecx, 256",
+ "253:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 253b",
+ "mov eax, 0",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 86016",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 86016",
+ "mov ecx, 256",
+ "254:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 254b",
+ "mov eax, 1",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 87040",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 87040",
+ "mov ecx, 256",
+ "255:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 255b",
+ "mov eax, 2",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 88064",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 88064",
+ "mov ecx, 256",
+ "256:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 256b",
+ "mov eax, 3",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 89088",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 89088",
+ "mov ecx, 256",
+ "257:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 257b",
+ "mov eax, 4",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 90112",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 90112",
+ "mov ecx, 256",
+ "258:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 258b",
+ "mov eax, 5",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 91136",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 91136",
+ "mov ecx, 256",
+ "259:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 259b",
+ "mov eax, 6",
+ "mov BYTE PTR [rbx+928], al",
+ "mov eax, 7",
+ "mov BYTE PTR [rbx+929], al",
+ "mov rdi, rbx",
+ "add rdi, 896",
+ "mov rsi, rbx",
+ "add rsi, 92160",
+ "mov rdx, rbx",
+ "add rdx, 4096",
+ "call {vg_mldsa_rej_ntt_poly}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 92160",
+ "mov ecx, 256",
+ "260:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 260b",
+ "mov rdi, r13",
+ "add rdi, 0",
+ "mov esi, 64",
+ "mov edx, 60",
+ "mov rcx, rbx",
+ "add rcx, 23552",
+ "mov r8, rbx",
+ "add r8, 4096",
+ "call {vg_mldsa_sample_in_ball}",
+ "and r15d, eax",
+ "mov edx, 0",
+ "sub edx, eax",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov ecx, 256",
+ "261:",
+ "mov eax, DWORD PTR [rdi]",
+ "and eax, edx",
+ "mov DWORD PTR [rdi], eax",
+ "add rdi, 4",
+ "sub rcx, 1",
+ "jne 261b",
+ "mov rdi, rbx",
+ "add rdi, 16384",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 17408",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 18432",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 19456",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 20480",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 21504",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 22528",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 23552",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 28672",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 29696",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 30720",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 31744",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 32768",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 33792",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 34816",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 32",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 8192",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 1024",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 36864",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 37888",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 38912",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 39936",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 40960",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 41984",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 43008",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 352",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 9216",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 1152",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 45056",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 46080",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 47104",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 48128",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 49152",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 50176",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 51200",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 672",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 10240",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 1280",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 53248",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 54272",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 55296",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 56320",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 57344",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 58368",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 59392",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 992",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 11264",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 1408",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 61440",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 62464",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 63488",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 64512",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 65536",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 66560",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 67584",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1312",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 12288",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 1536",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 69632",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 70656",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 71680",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 72704",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 73728",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 74752",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 75776",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1632",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 13312",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 1664",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 77824",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 78848",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 79872",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 80896",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 81920",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 82944",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 83968",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 1952",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 14336",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 1792",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 86016",
+ "mov rdx, rbx",
+ "add rdx, 16384",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 87040",
+ "mov rdx, rbx",
+ "add rdx, 17408",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 88064",
+ "mov rdx, rbx",
+ "add rdx, 18432",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 89088",
+ "mov rdx, rbx",
+ "add rdx, 19456",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 90112",
+ "mov rdx, rbx",
+ "add rdx, 20480",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 91136",
+ "mov rdx, rbx",
+ "add rdx, 21504",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 92160",
+ "mov rdx, rbx",
+ "add rdx, 22528",
+ "call {vg_mldsa_multiply_add_ntt_avx2}",
+ "mov rdi, rbp",
+ "add rdi, 2272",
+ "mov rsi, rbx",
+ "add rsi, 24576",
+ "call {vg_mldsa_unpack_t1}",
+ "mov rdi, rbx",
+ "add rdi, 24576",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 25600",
+ "mov rsi, rbx",
+ "add rsi, 23552",
+ "mov rdx, rbx",
+ "add rdx, 24576",
+ "call {vg_mldsa_multiply_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 25600",
+ "call {vg_mldsa_sub_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 26624",
+ "mov rsi, rbx",
+ "add rsi, 4096",
+ "call {vg_mldsa_inv_ntt_avx2}",
+ "mov rdi, rbx",
+ "add rdi, 15360",
+ "mov rsi, rbx",
+ "add rsi, 26624",
+ "mov edx, 261888",
+ "mov rcx, rbx",
+ "add rcx, 27648",
+ "call {vg_mldsa_use_hint}",
+ "mov rdi, rbx",
+ "add rdi, 27648",
+ "mov esi, 15",
+ "mov rdx, rbx",
+ "add rdx, 1920",
+ "mov ecx, 128",
+ "call {vg_mldsa_simple_bit_pack}",
+ "mov eax, 0",
+ "mov QWORD PTR [rbx], rax",
+ "mov QWORD PTR [rbx+8], rax",
+ "mov QWORD PTR [rbx+16], rax",
+ "mov QWORD PTR [rbx+24], rax",
+ "mov QWORD PTR [rbx+32], rax",
+ "mov QWORD PTR [rbx+40], rax",
+ "mov QWORD PTR [rbx+48], rax",
+ "mov QWORD PTR [rbx+56], rax",
+ "mov QWORD PTR [rbx+64], rax",
+ "mov QWORD PTR [rbx+72], rax",
+ "mov QWORD PTR [rbx+80], rax",
+ "mov QWORD PTR [rbx+88], rax",
+ "mov QWORD PTR [rbx+96], rax",
+ "mov QWORD PTR [rbx+104], rax",
+ "mov QWORD PTR [rbx+112], rax",
+ "mov QWORD PTR [rbx+120], rax",
+ "mov QWORD PTR [rbx+128], rax",
+ "mov QWORD PTR [rbx+136], rax",
+ "mov QWORD PTR [rbx+144], rax",
+ "mov QWORD PTR [rbx+152], rax",
+ "mov QWORD PTR [rbx+160], rax",
+ "mov QWORD PTR [rbx+168], rax",
+ "mov QWORD PTR [rbx+176], rax",
+ "mov QWORD PTR [rbx+184], rax",
+ "mov QWORD PTR [rbx+192], rax",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, r12",
+ "add rcx, 0",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 64",
+ "mov rcx, rbx",
+ "add rcx, 1024",
+ "mov r8d, 1024",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_absorb}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov ecx, 31",
+ "mov r8, rbx",
+ "add r8, 200",
+ "call {vg_keccak_pad}",
+ "mov rdi, rbx",
+ "add rdi, 0",
+ "mov esi, 136",
+ "mov edx, 0",
+ "mov rcx, rbx",
+ "add rcx, 2048",
+ "mov r8d, 64",
+ "mov r9, rbx",
+ "add r9, 200",
+ "call {vg_keccak_squeeze}",
+ "mov rsi, rbx",
+ "add rsi, 2048",
+ "mov rdi, r13",
+ "add rdi, 0",
+ "mov ecx, 64",
+ "mov edx, 0",
+ "262:",
+ "movzx eax, BYTE PTR [rsi]",
+ "movzx r8d, BYTE PTR [rdi]",
+ "xor rax, r8",
+ "or rdx, rax",
+ "add rsi, 1",
+ "add rdi, 1",
+ "sub rcx, 1",
+ "jne 262b",
+ "sub rdx, 1",
+ "sbb rax, rax",
+ "and r15d, eax",
+ "23:",
+ "21:",
+ "mov eax, r15d",
+ "mov r15, QWORD PTR [rbx+880]",
+ "mov r14, QWORD PTR [rbx+872]",
+ "mov r13, QWORD PTR [rbx+864]",
+ "mov r12, QWORD PTR [rbx+856]",
+ "mov rbp, QWORD PTR [rbx+848]",
+ "mov rbx, QWORD PTR [rbx+840]",
+ "ret",
+ vg_mldsa_hint_bit_unpack = sym super::mldsa::vg_mldsa_hint_bit_unpack,
+ vg_mldsa_bit_unpack = sym super::mldsa::vg_mldsa_bit_unpack,
+ vg_mldsa_norm_lt = sym super::mldsa::vg_mldsa_norm_lt,
+ vg_mldsa_rej_ntt_poly = sym super::mldsa::vg_mldsa_rej_ntt_poly,
+ vg_mldsa_sample_in_ball = sym super::mldsa::vg_mldsa_sample_in_ball,
+ vg_mldsa_ntt_avx2 = sym super::mldsa::vg_mldsa_ntt_avx2,
+ vg_mldsa_multiply_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_ntt_avx2,
+ vg_mldsa_multiply_add_ntt_avx2 = sym super::mldsa::vg_mldsa_multiply_add_ntt_avx2,
+ vg_mldsa_unpack_t1 = sym super::mldsa::vg_mldsa_unpack_t1,
+ vg_mldsa_sub_avx2 = sym super::mldsa::vg_mldsa_sub_avx2,
+ vg_mldsa_inv_ntt_avx2 = sym super::mldsa::vg_mldsa_inv_ntt_avx2,
+ vg_mldsa_use_hint = sym super::mldsa::vg_mldsa_use_hint,
+ vg_mldsa_simple_bit_pack = sym super::mldsa::vg_mldsa_simple_bit_pack,
+ vg_keccak_absorb = sym super::sha3::vg_keccak_absorb,
+ vg_keccak_pad = sym super::sha3::vg_keccak_pad,
+ vg_keccak_squeeze = sym super::sha3::vg_keccak_squeeze,
+ )
+}
+
/// ML-DSA-87 key generation from a seed, `ML-DSA.KeyGen_internal(ξ)` (FIPS 204 Algorithm 6): with the 32-byte seed `ξ` at `seed`, writes the public key to `*pk` and the private key to `*sk`. Returns 1 on success. Returns 0 if a loop reaches its bound, which is at least the limit of FIPS 204 Appendix C, Table 3 (this happens with probability about 2^-256 or less): the outputs are then unspecified, and the caller must destroy them and treat the operation as failed.
///
/// Contract: `VG.Spec.MlDsa.keyGenContract`. Constant time but for `ρ` and rejections: timing may depend on the pointers, on `ρ` (the first 32 bytes of the public key), and on which half-bytes of the SHAKE256 outputs `RejBoundedPoly` rejects (`rejBoundedLeak`, which is independent of the coefficients it samples), but not on anything else of the seed or the keys.
diff --git a/src/mldsa44.rs b/src/mldsa44.rs
index 782c59c4b..04777dad9 100644
--- a/src/mldsa44.rs
+++ b/src/mldsa44.rs
@@ -38,6 +38,9 @@ crate::mldsa_common::ml_dsa! {
keygen_sha3: (crate::arch::mldsa44::vg_mldsa44_keygen_sha3, crate::arch::mldsa44::VG_MLDSA44_KEYGEN_SHA3_FEATURES),
sign_sha3: (crate::arch::mldsa44::vg_mldsa44_sign_sha3, crate::arch::mldsa44::VG_MLDSA44_SIGN_SHA3_FEATURES),
verify_sha3: (crate::arch::mldsa44::vg_mldsa44_verify_sha3, crate::arch::mldsa44::VG_MLDSA44_VERIFY_SHA3_FEATURES),
+ keygen_avx2: (crate::arch::mldsa44::vg_mldsa44_keygen_avx2, crate::arch::mldsa44::VG_MLDSA44_KEYGEN_AVX2_FEATURES),
+ sign_avx2: (crate::arch::mldsa44::vg_mldsa44_sign_avx2, crate::arch::mldsa44::VG_MLDSA44_SIGN_AVX2_FEATURES),
+ verify_avx2: (crate::arch::mldsa44::vg_mldsa44_verify_avx2, crate::arch::mldsa44::VG_MLDSA44_VERIFY_AVX2_FEATURES),
pk: 1312,
sk: 2560,
sig: 2420,
diff --git a/src/mldsa65.rs b/src/mldsa65.rs
index a67072013..79dff1485 100644
--- a/src/mldsa65.rs
+++ b/src/mldsa65.rs
@@ -38,6 +38,9 @@ crate::mldsa_common::ml_dsa! {
keygen_sha3: (crate::arch::mldsa65::vg_mldsa65_keygen_sha3, crate::arch::mldsa65::VG_MLDSA65_KEYGEN_SHA3_FEATURES),
sign_sha3: (crate::arch::mldsa65::vg_mldsa65_sign_sha3, crate::arch::mldsa65::VG_MLDSA65_SIGN_SHA3_FEATURES),
verify_sha3: (crate::arch::mldsa65::vg_mldsa65_verify_sha3, crate::arch::mldsa65::VG_MLDSA65_VERIFY_SHA3_FEATURES),
+ keygen_avx2: (crate::arch::mldsa65::vg_mldsa65_keygen_avx2, crate::arch::mldsa65::VG_MLDSA65_KEYGEN_AVX2_FEATURES),
+ sign_avx2: (crate::arch::mldsa65::vg_mldsa65_sign_avx2, crate::arch::mldsa65::VG_MLDSA65_SIGN_AVX2_FEATURES),
+ verify_avx2: (crate::arch::mldsa65::vg_mldsa65_verify_avx2, crate::arch::mldsa65::VG_MLDSA65_VERIFY_AVX2_FEATURES),
pk: 1952,
sk: 4032,
sig: 3309,
diff --git a/src/mldsa87.rs b/src/mldsa87.rs
index 7b672b3e4..ce1e72136 100644
--- a/src/mldsa87.rs
+++ b/src/mldsa87.rs
@@ -38,6 +38,9 @@ crate::mldsa_common::ml_dsa! {
keygen_sha3: (crate::arch::mldsa87::vg_mldsa87_keygen_sha3, crate::arch::mldsa87::VG_MLDSA87_KEYGEN_SHA3_FEATURES),
sign_sha3: (crate::arch::mldsa87::vg_mldsa87_sign_sha3, crate::arch::mldsa87::VG_MLDSA87_SIGN_SHA3_FEATURES),
verify_sha3: (crate::arch::mldsa87::vg_mldsa87_verify_sha3, crate::arch::mldsa87::VG_MLDSA87_VERIFY_SHA3_FEATURES),
+ keygen_avx2: (crate::arch::mldsa87::vg_mldsa87_keygen_avx2, crate::arch::mldsa87::VG_MLDSA87_KEYGEN_AVX2_FEATURES),
+ sign_avx2: (crate::arch::mldsa87::vg_mldsa87_sign_avx2, crate::arch::mldsa87::VG_MLDSA87_SIGN_AVX2_FEATURES),
+ verify_avx2: (crate::arch::mldsa87::vg_mldsa87_verify_avx2, crate::arch::mldsa87::VG_MLDSA87_VERIFY_AVX2_FEATURES),
pk: 2592,
sk: 4896,
sig: 4627,
diff --git a/src/mldsa_common.rs b/src/mldsa_common.rs
index 2979826b0..448792854 100644
--- a/src/mldsa_common.rs
+++ b/src/mldsa_common.rs
@@ -25,6 +25,45 @@ pub(crate) fn message_rep(tr: &[u8; 64], msg: &[u8], ctx: &[u8]) -> Option<[u8;
Some(mu)
}
+/// The implementations of ML-DSA's verified functions: their instances for
+/// the polynomial arithmetic and Keccak they call (`Generic/MlDsaArith/` and
+/// the Keccak backend, `crate::hashes::sha3::Backend`).
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub(crate) enum Backend {
+ /// The target's baseline ISA (on x86-64, SSE2 polynomial arithmetic),
+ /// with scalar Keccak.
+ Scalar,
+ /// AArch64 with the SHA-3 extension, for Keccak.
+ #[cfg(all(target_arch = "aarch64", feature = "cpu-features-env"))]
+ Sha3,
+ /// x86-64 with AVX2, for the polynomial arithmetic.
+ #[cfg(target_arch = "x86_64")]
+ Avx2,
+}
+
+impl Backend {
+ /// The implementation for the Keccak backend `keccak`, on a CPU with the
+ /// features `f`, of functions whose AVX2 instances need `avx2`.
+ #[cfg_attr(not(target_arch = "x86_64"), allow(unused_variables))]
+ pub(crate) fn select(
+ keccak: crate::hashes::sha3::Backend,
+ f: crate::cpu::Features,
+ avx2: &[&[&str]],
+ ) -> Backend {
+ match keccak {
+ crate::hashes::sha3::Backend::Scalar => {
+ #[cfg(target_arch = "x86_64")]
+ if f.contains(crate::cpu::Features::all(avx2)) {
+ return Backend::Avx2;
+ }
+ Backend::Scalar
+ }
+ #[cfg(all(target_arch = "aarch64", feature = "cpu-features-env"))]
+ crate::hashes::sha3::Backend::Sha3 => Backend::Sha3,
+ }
+ }
+}
+
/// Defines the API of one ML-DSA parameter set: its `Error`, `SigningKey`
/// and `VerifyingKey`, over its verified `keygen`, `sign` and `verify`
/// functions (which take `μ`) and its sizes.
@@ -39,6 +78,9 @@ macro_rules! ml_dsa {
keygen_sha3: ($keygen_sha3:path, $keygen_sha3_features:path),
sign_sha3: ($sign_sha3:path, $sign_sha3_features:path),
verify_sha3: ($verify_sha3:path, $verify_sha3_features:path),
+ keygen_avx2: ($keygen_avx2:path, $keygen_avx2_features:path),
+ sign_avx2: ($sign_avx2:path, $sign_avx2_features:path),
+ verify_avx2: ($verify_avx2:path, $verify_avx2_features:path),
pk: $pk:literal,
sk: $sk:literal,
sig: $sig:literal,
@@ -46,10 +88,12 @@ macro_rules! ml_dsa {
) => {
use $crate::mldsa_common::message_rep;
use $crate::zeroize::zeroize;
- use $crate::hashes::sha3::Backend;
+ use $crate::mldsa_common::Backend;
- /// Follow the shared Keccak backend only when all generated callers'
- /// feature requirements are met. The draft's default stays scalar.
+ /// The implementation to call: the Keccak backend, followed only
+ /// when all generated callers' feature requirements are met (the
+ /// draft's default stays scalar), and AVX2 for the polynomial
+ /// arithmetic on x86-64 when the CPU has what its callers need.
fn backend() -> Backend {
#[cfg(all(target_arch = "aarch64", feature = "cpu-features-env"))]
if !$crate::cpu::detected().contains($crate::cpu::Features::all(&[
@@ -59,7 +103,11 @@ macro_rules! ml_dsa {
])) {
return Backend::Scalar;
}
- Backend::detected()
+ #[cfg(target_arch = "x86_64")]
+ const AVX2: &[&[&str]] = &[$keygen_avx2_features, $sign_avx2_features, $verify_avx2_features];
+ #[cfg(not(target_arch = "x86_64"))]
+ const AVX2: &[&[&str]] = &[];
+ Backend::select($crate::hashes::sha3::Backend::detected(), $crate::cpu::detected(), AVX2)
}
/// Why an operation failed.
@@ -140,6 +188,8 @@ macro_rules! ml_dsa {
Backend::Scalar => $verify(&self.bytes, mu, sig, &mut scratch),
#[cfg(all(target_arch = "aarch64", feature = "cpu-features-env"))]
Backend::Sha3 => $verify_sha3(&self.bytes, mu, sig, &mut scratch),
+ #[cfg(target_arch = "x86_64")]
+ Backend::Avx2 => $verify_avx2(&self.bytes, mu, sig, &mut scratch),
}
};
if r == 1 { Ok(()) } else { Err(Error::InvalidSignature) }
@@ -196,6 +246,8 @@ macro_rules! ml_dsa {
Backend::Scalar => $keygen(seed, &mut key.vk.bytes, &mut key.sk, &mut scratch),
#[cfg(all(target_arch = "aarch64", feature = "cpu-features-env"))]
Backend::Sha3 => $keygen_sha3(seed, &mut key.vk.bytes, &mut key.sk, &mut scratch),
+ #[cfg(target_arch = "x86_64")]
+ Backend::Avx2 => $keygen_avx2(seed, &mut key.vk.bytes, &mut key.sk, &mut scratch),
}
};
zeroize(&mut scratch);
@@ -274,6 +326,8 @@ macro_rules! ml_dsa {
Backend::Scalar => $sign(&self.sk, mu, rnd, &mut sig, &mut scratch),
#[cfg(all(target_arch = "aarch64", feature = "cpu-features-env"))]
Backend::Sha3 => $sign_sha3(&self.sk, mu, rnd, &mut sig, &mut scratch),
+ #[cfg(target_arch = "x86_64")]
+ Backend::Avx2 => $sign_avx2(&self.sk, mu, rnd, &mut sig, &mut scratch),
}
};
zeroize(&mut scratch);