kernel_3d_16 and xof functions
diff --git a/asm/asm.py b/asm/asm.py
index 75c7012..014c420 100755
--- a/asm/asm.py
+++ b/asm/asm.py
@@ -1,6 +1,11 @@
 #! /usr/bin/env python3
 
 # Generate asm!
+#
+# TODOs:
+# - vzeroupper
+# - CET
+# - prefetches
 
 from dataclasses import dataclass, replace
 
@@ -11,6 +16,16 @@
 SSE2 = "sse2"
 LINUX = "linux"
 
+MESSAGE_SCHEDULE = [
+    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
+    [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8],
+    [3, 4, 10, 12, 13, 2, 7, 14, 6, 5, 9, 0, 11, 15, 8, 1],
+    [10, 7, 12, 9, 14, 3, 13, 15, 4, 0, 11, 2, 5, 8, 1, 6],
+    [12, 13, 9, 11, 15, 10, 14, 8, 7, 2, 5, 3, 0, 1, 6, 4],
+    [9, 14, 11, 5, 8, 12, 15, 1, 13, 3, 0, 10, 2, 6, 4, 7],
+    [11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13],
+]
+
 
 @dataclass
 class Target:
@@ -47,9 +62,9 @@
     if target.extension == AVX512:
         if degree == 1:
             output.append(f"vpaddd xmm{dest}, xmm{dest}, xmm{src}")
-        elif degree == 2:
+        elif degree in (2, 8):
             output.append(f"vpaddd ymm{dest}, ymm{dest}, ymm{src}")
-        elif degree == 4:
+        elif degree in (4, 16):
             output.append(f"vpaddd zmm{dest}, zmm{dest}, zmm{src}")
         else:
             raise NotImplementedError
@@ -68,9 +83,9 @@
     if target.extension == AVX512:
         if degree == 1:
             output.append(f"vpxord xmm{dest}, xmm{dest}, xmm{src}")
-        elif degree == 2:
+        elif degree in (2, 8):
             output.append(f"vpxord ymm{dest}, ymm{dest}, ymm{src}")
-        elif degree == 4:
+        elif degree in (4, 16):
             output.append(f"vpxord zmm{dest}, zmm{dest}, zmm{src}")
         else:
             raise NotImplementedError
@@ -90,9 +105,9 @@
     if target.extension == AVX512:
         if degree == 1:
             output.append(f"vprord xmm{reg}, xmm{reg}, {bits}")
-        elif degree == 2:
+        elif degree in (2, 8):
             output.append(f"vprord ymm{reg}, ymm{reg}, {bits}")
-        elif degree == 4:
+        elif degree in (4, 16):
             output.append(f"vprord zmm{reg}, zmm{reg}, {bits}")
         else:
             raise NotImplementedError
@@ -138,7 +153,7 @@
         raise NotImplementedError
 
 
-# See the comments above kernel2d().
+# See the comments above kernel_2d().
 def diagonalize_state_rows(target, output, degree):
     if target.extension == AVX512:
         if degree == 1:
@@ -169,7 +184,7 @@
         raise NotImplementedError
 
 
-# See the comments above kernel2d().
+# See the comments above kernel_2d().
 def undiagonalize_state_rows(target, output, degree):
     if target.extension == AVX512:
         if degree == 1:
@@ -200,7 +215,7 @@
         raise NotImplementedError
 
 
-# See the comments above kernel2d().
+# See the comments above kernel_2d().
 def permute_message_rows(target, output, degree):
     if target.extension == AVX512:
         if degree == 1:
@@ -309,8 +324,8 @@
         raise NotImplementedError
 
 
-def kernel2d_name(target, degree):
-    return f"blake3_{target.extension}_kernel2d_{degree}"
+def kernel_2d_name(target, degree):
+    return f"blake3_{target.extension}_kernel_2d_{degree}"
 
 
 # The two-dimensional kernel packs one or more *rows* of the state into a
@@ -353,22 +368,29 @@
 #     ymm5:  a1,  a3,  a5,  a7,  b1,  b3,  b5,  b7
 #     ymm6: a14,  a8, a10, a12, b14,  b8, b10, b12
 #     ymm7: a15,  a9, a11, a13, b15,  b9, b11, b13
-def kernel2d(target, output, degree):
-    label = kernel2d_name(target, degree)
+def kernel_2d(target, output, degree):
+    label = kernel_2d_name(target, degree)
     output.append(f"{label}:")
     # vpshufb indexes
-    if target.extension == SSE41:
+    if target.extension == SSE2:
+        assert degree == 1
+    elif target.extension == SSE41:
+        assert degree == 1
         output.append(f"movaps xmm14, xmmword ptr [ROT8+rip]")
         output.append(f"movaps xmm15, xmmword ptr [ROT16+rip]")
-    if target.extension == AVX2:
+    elif target.extension == AVX2:
+        assert degree == 2
         output.append(f"vbroadcasti128 ymm14, xmmword ptr [ROT16+rip]")
         output.append(f"vbroadcasti128 ymm15, xmmword ptr [ROT8+rip]")
-    if target.extension == AVX512:
+    elif target.extension == AVX512:
+        assert degree in (1, 2, 4)
         if degree == 4:
             output.append(f"mov {target.scratch32(0)}, 43690")
             output.append(f"kmovw k3, {target.scratch32(0)}")
             output.append(f"mov {target.scratch32(0)}, 34952")
             output.append(f"kmovw k4, {target.scratch32(0)}")
+    else:
+        raise NotImplementedError
     for round_number in range(7):
         if round_number > 0:
             # Un-diagonalize and permute before each round except the first.
@@ -482,12 +504,12 @@
     output.append(f".global {label}")
     output.append(f"{label}:")
     compress_setup(target, output)
-    output.append(f"call {kernel2d_name(target, 1)}")
+    output.append(f"call {kernel_2d_name(target, 1)}")
     compress_finish(target, output)
     output.append(target.ret())
 
 
-def xof_setup2d(target, output, degree):
+def xof_setup_2d(target, output, degree):
     if target.extension == AVX512:
         if degree == 1:
             # state words
@@ -641,7 +663,7 @@
         raise NotImplementedError
 
 
-def xof_stream_finish2d(target, output, degree):
+def xof_stream_finish_2d(target, output, degree):
     if target.extension == AVX512:
         if degree == 1:
             output.append(f"vpxor xmm2, xmm2, [{target.arg64(0)}]")
@@ -706,7 +728,7 @@
         raise NotImplementedError
 
 
-def xof_xor_finish2d(target, output, degree):
+def xof_xor_finish_2d(target, output, degree):
     if target.extension == AVX512:
         if degree == 1:
             output.append(f"vpxor xmm2, xmm2, [{target.arg64(0)}]")
@@ -842,28 +864,558 @@
         raise NotImplementedError
 
 
+def g_function_3d(target, output, degree, columns, msg_words1, msg_words2):
+    if target.extension == SSE41:
+        assert degree == 4
+    elif target.extension == AVX2:
+        assert degree == 8
+    elif target.extension == AVX512:
+        assert degree in (8, 16)
+    else:
+        raise NotImplementedError
+    for (column, m1) in zip(columns, msg_words1):
+        add_row(target, output, degree, dest=column[0], src=m1)
+    for column in columns:
+        add_row(target, output, degree, dest=column[0], src=column[1])
+    for column in columns:
+        xor_row(target, output, degree, dest=column[3], src=column[0])
+    for column in columns:
+        bitrotate_row(target, output, degree, reg=column[3], bits=16)
+    for column in columns:
+        add_row(target, output, degree, dest=column[2], src=column[3])
+    for column in columns:
+        xor_row(target, output, degree, dest=column[1], src=column[2])
+    for column in columns:
+        bitrotate_row(target, output, degree, reg=column[1], bits=12)
+    for (column, m2) in zip(columns, msg_words2):
+        add_row(target, output, degree, dest=column[0], src=m2)
+    for column in columns:
+        add_row(target, output, degree, dest=column[0], src=column[1])
+    for column in columns:
+        xor_row(target, output, degree, dest=column[3], src=column[0])
+    for column in columns:
+        bitrotate_row(target, output, degree, reg=column[3], bits=8)
+    for column in columns:
+        add_row(target, output, degree, dest=column[2], src=column[3])
+    for column in columns:
+        xor_row(target, output, degree, dest=column[1], src=column[2])
+    for column in columns:
+        bitrotate_row(target, output, degree, reg=column[1], bits=7)
+
+
+def kernel_3d_name(target, degree):
+    return f"blake3_{target.extension}_kernel_3d_{degree}"
+
+
+def kernel_3d(target, output, degree):
+    label = kernel_3d_name(target, degree)
+    output.append(f"{label}:")
+    if target.extension == SSE41:
+        assert degree == 4
+    elif target.extension == AVX2:
+        assert degree == 8
+    elif target.extension == AVX512:
+        assert degree in (8, 16)
+    else:
+        raise NotImplementedError
+    for round_number in range(7):
+        straight_columns = [
+            [0, 4, 8, 12],
+            [1, 5, 9, 13],
+            [2, 6, 10, 14],
+            [3, 7, 11, 15],
+        ]
+        msg_words1 = [16 + MESSAGE_SCHEDULE[round_number][i] for i in [0, 2, 4, 6]]
+        msg_words2 = [16 + MESSAGE_SCHEDULE[round_number][i] for i in [1, 3, 5, 7]]
+        g_function_3d(target, output, degree, straight_columns, msg_words1, msg_words2)
+        diagonal_columns = [
+            [0, 5, 10, 15],
+            [1, 6, 11, 12],
+            [2, 7, 8, 13],
+            [3, 4, 9, 14],
+        ]
+        msg_words1 = [16 + MESSAGE_SCHEDULE[round_number][i] for i in [8, 10, 12, 14]]
+        msg_words2 = [16 + MESSAGE_SCHEDULE[round_number][i] for i in [9, 11, 13, 15]]
+        g_function_3d(target, output, degree, diagonal_columns, msg_words1, msg_words2)
+    # Xor the last two rows into the first two, but don't do the feed forward
+    # here. That's only done in the XOF case.
+    for dest in range(8):
+        xor_row(target, output, degree, dest=dest, src=dest + 8)
+    output.append(target.ret())
+
+
+def xof_setup_3d(target, output, degree):
+    if target.extension == AVX512:
+        if degree == 16:
+            # Load vpermi2d indexes into the counter registers.
+            output.append(f"vmovdqa32 zmm12, zmmword ptr [rip + EVEN_INDEXES]")
+            output.append(f"vmovdqa32 zmm13, zmmword ptr [rip + ODD_INDEXES]")
+            # Load the state words.
+            for i in range(8):
+                output.append(
+                    f"vpbroadcastd zmm{i}, dword ptr [{target.arg64(0)}+{4*i}]"
+                )
+            # Load the message words.
+            for i in range(16):
+                output.append(
+                    f"vpbroadcastd zmm{i+16}, dword ptr [{target.arg64(1)}+{4*i}]"
+                )
+            # Load the 64-bit counter increments into a temporary register.
+            output.append(f"vmovdqa64 zmm8, zmmword ptr [INCREMENT_3D+rip]")
+            # Broadcast the counter and add it to the increments. This gives
+            # the first 8 counter values.
+            output.append(f"vpbroadcastq zmm9, {target.arg64(2)}")
+            output.append(f"vpaddq zmm9, zmm9, zmm8")
+            # Increment the counter and repeat that for the last 8 counter values.
+            output.append(f"add {target.arg64(2)}, 8")
+            output.append(f"vpbroadcastq zmm10, {target.arg64(2)}")
+            output.append(f"vpaddq zmm10, zmm10, zmm8")
+            # Extract the lower and upper halves of the counter words, using
+            # the permutation tables loaded above.
+            output.append(f"vpermi2d zmm12, zmm9, zmm10")
+            output.append(f"vpermi2d zmm13, zmm9, zmm10")
+            # Load the block length.
+            output.append(f"vpbroadcastd zmm14, {target.arg32(3)}")
+            # Load the domain flags.
+            output.append(f"vpbroadcastd zmm15, {target.arg32(4)}")
+            # Load the IV constants.
+            for i in range(4):
+                output.append(f"vpbroadcastd zmm{i+8}, dword ptr [BLAKE3_IV+rip+{4*i}]")
+        else:
+            raise NotImplementedError
+    else:
+        raise NotImplementedError
+
+
+def xof_stream_finish_3d(target, output, degree):
+    if target.extension == AVX512:
+        if degree == 16:
+            # Re-broadcast the input CV and feed it forward into the second half of the state.
+            output.append(f"vpbroadcastd zmm16, dword ptr [{target.arg64(0)} + 0 * 4]")
+            output.append(f"vpxord zmm8, zmm8, zmm16")
+            output.append(f"vpbroadcastd zmm17, dword ptr [{target.arg64(0)} + 1 * 4]")
+            output.append(f"vpxord zmm9, zmm9, zmm17")
+            output.append(f"vpbroadcastd zmm18, dword ptr [{target.arg64(0)} + 2 * 4]")
+            output.append(f"vpxord zmm10, zmm10, zmm18")
+            output.append(f"vpbroadcastd zmm19, dword ptr [{target.arg64(0)} + 3 * 4]")
+            output.append(f"vpxord zmm11, zmm11, zmm19")
+            output.append(f"vpbroadcastd zmm20, dword ptr [{target.arg64(0)} + 4 * 4]")
+            output.append(f"vpxord zmm12, zmm12, zmm20")
+            output.append(f"vpbroadcastd zmm21, dword ptr [{target.arg64(0)} + 5 * 4]")
+            output.append(f"vpxord zmm13, zmm13, zmm21")
+            output.append(f"vpbroadcastd zmm22, dword ptr [{target.arg64(0)} + 6 * 4]")
+            output.append(f"vpxord zmm14, zmm14, zmm22")
+            output.append(f"vpbroadcastd zmm23, dword ptr [{target.arg64(0)} + 7 * 4]")
+            output.append(f"vpxord zmm15, zmm15, zmm23")
+            # zmm0-zmm15 now contain the final extended state vectors, transposed. We need to un-transpose
+            # them before we write them out. As with blake3_avx512_blocks_16, we prefer to avoid expensive
+            # operations across 128-bit lanes, so we do a couple of interleaving passes and then write out
+            # 128 bits at a time.
+            #
+            # First, interleave 32-bit words. Use zmm16-zmm31 to hold the intermediate results. This
+            # takes the input vectors like:
+            #
+            # a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0
+            #
+            # And produces vectors like:
+            #
+            # a0, a1, b0, b1, e0, e1, g0, g1, i0, i1, k0, k1, m0, m1, o0, o1
+            #
+            # Then interleave 64-bit words back into zmm0-zmm15, producing vectors like:
+            #
+            # a0, a1, a2, a3, e0, e1, e2, e3, i0, i1, i2, i3, m0, m1, m2, m3
+            #
+            # Finally, write out each 128-bit group, unaligned.
+            output.append(f"vpunpckldq zmm16, zmm0, zmm1")
+            output.append(f"vpunpckhdq zmm17, zmm0, zmm1")
+            output.append(f"vpunpckldq zmm18, zmm2, zmm3")
+            output.append(f"vpunpckhdq zmm19, zmm2, zmm3")
+            output.append(f"vpunpcklqdq zmm0, zmm16, zmm18")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 0 * 16], xmm0")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 16 * 16], zmm0, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 32 * 16], zmm0, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 48 * 16], zmm0, 3"
+            )
+            output.append(f"vpunpckhqdq zmm1, zmm16, zmm18")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 4 * 16], xmm1")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 20 * 16], zmm1, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 36 * 16], zmm1, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 52 * 16], zmm1, 3"
+            )
+            output.append(f"vpunpcklqdq zmm2, zmm17, zmm19")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 8 * 16], xmm2")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 24 * 16], zmm2, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 40 * 16], zmm2, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 56 * 16], zmm2, 3"
+            )
+            output.append(f"vpunpckhqdq zmm3, zmm17, zmm19")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 12 * 16], xmm3")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 28 * 16], zmm3, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 44 * 16], zmm3, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 60 * 16], zmm3, 3"
+            )
+            output.append(f"vpunpckldq zmm20, zmm4, zmm5")
+            output.append(f"vpunpckhdq zmm21, zmm4, zmm5")
+            output.append(f"vpunpckldq zmm22, zmm6, zmm7")
+            output.append(f"vpunpckhdq zmm23, zmm6, zmm7")
+            output.append(f"vpunpcklqdq zmm4, zmm20, zmm22")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 1 * 16], xmm4")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 17 * 16], zmm4, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 33 * 16], zmm4, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 49 * 16], zmm4, 3"
+            )
+            output.append(f"vpunpckhqdq zmm5, zmm20, zmm22")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 5 * 16], xmm5")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 21 * 16], zmm5, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 37 * 16], zmm5, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 53 * 16], zmm5, 3"
+            )
+            output.append(f"vpunpcklqdq zmm6, zmm21, zmm23")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 9 * 16], xmm6")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 25 * 16], zmm6, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 41 * 16], zmm6, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 57 * 16], zmm6, 3"
+            )
+            output.append(f"vpunpckhqdq zmm7, zmm21, zmm23")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 13 * 16], xmm7")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 29 * 16], zmm7, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 45 * 16], zmm7, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 61 * 16], zmm7, 3"
+            )
+            output.append(f"vpunpckldq zmm24, zmm8, zmm9")
+            output.append(f"vpunpckhdq zmm25, zmm8, zmm9")
+            output.append(f"vpunpckldq zmm26, zmm10, zmm11")
+            output.append(f"vpunpckhdq zmm27, zmm10, zmm11")
+            output.append(f"vpunpcklqdq zmm8, zmm24, zmm26")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 2 * 16], xmm8")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 18 * 16], zmm8, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 34 * 16], zmm8, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 50 * 16], zmm8, 3"
+            )
+            output.append(f"vpunpckhqdq zmm9, zmm24, zmm26")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 6 * 16], xmm9")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 22 * 16], zmm9, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 38 * 16], zmm9, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 54 * 16], zmm9, 3"
+            )
+            output.append(f"vpunpcklqdq zmm10, zmm25, zmm27")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 10 * 16], xmm10")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 26 * 16], zmm10, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 42 * 16], zmm10, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 58 * 16], zmm10, 3"
+            )
+            output.append(f"vpunpckhqdq zmm11, zmm25, zmm27")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 14 * 16], xmm11")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 30 * 16], zmm11, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 46 * 16], zmm11, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 62 * 16], zmm11, 3"
+            )
+            output.append(f"vpunpckldq zmm28, zmm12, zmm13")
+            output.append(f"vpunpckhdq zmm29, zmm12, zmm13")
+            output.append(f"vpunpckldq zmm30, zmm14, zmm15")
+            output.append(f"vpunpckhdq zmm31, zmm14, zmm15")
+            output.append(f"vpunpcklqdq zmm12, zmm28, zmm30")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 3 * 16], xmm12")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 19 * 16], zmm12, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 35 * 16], zmm12, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 51 * 16], zmm12, 3"
+            )
+            output.append(f"vpunpckhqdq zmm13, zmm28, zmm30")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 7 * 16], xmm13")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 23 * 16], zmm13, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 39 * 16], zmm13, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 55 * 16], zmm13, 3"
+            )
+            output.append(f"vpunpcklqdq zmm14, zmm29, zmm31")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 11 * 16], xmm14")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 27 * 16], zmm14, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 43 * 16], zmm14, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 59 * 16], zmm14, 3"
+            )
+            output.append(f"vpunpckhqdq zmm15, zmm29, zmm31")
+            output.append(f"vmovdqu32 xmmword ptr [{target.arg64(5)} + 15 * 16], xmm15")
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 31 * 16], zmm15, 1"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 47 * 16], zmm15, 2"
+            )
+            output.append(
+                f"vextracti32x4 xmmword ptr [{target.arg64(5)} + 63 * 16], zmm15, 3"
+            )
+        else:
+            raise NotImplementedError
+    else:
+        raise NotImplementedError
+
+
+def xof_xor_finish_3d(target, output, degree):
+    if target.extension == AVX512:
+        if degree == 16:
+            # Re-broadcast the input CV and feed it forward into the second half of the state.
+            output.append(f"vpbroadcastd zmm16, dword ptr [{target.arg64(0)} + 0 * 4]")
+            output.append(f"vpxord zmm8, zmm8, zmm16")
+            output.append(f"vpbroadcastd zmm17, dword ptr [{target.arg64(0)} + 1 * 4]")
+            output.append(f"vpxord zmm9, zmm9, zmm17")
+            output.append(f"vpbroadcastd zmm18, dword ptr [{target.arg64(0)} + 2 * 4]")
+            output.append(f"vpxord zmm10, zmm10, zmm18")
+            output.append(f"vpbroadcastd zmm19, dword ptr [{target.arg64(0)} + 3 * 4]")
+            output.append(f"vpxord zmm11, zmm11, zmm19")
+            output.append(f"vpbroadcastd zmm20, dword ptr [{target.arg64(0)} + 4 * 4]")
+            output.append(f"vpxord zmm12, zmm12, zmm20")
+            output.append(f"vpbroadcastd zmm21, dword ptr [{target.arg64(0)} + 5 * 4]")
+            output.append(f"vpxord zmm13, zmm13, zmm21")
+            output.append(f"vpbroadcastd zmm22, dword ptr [{target.arg64(0)} + 6 * 4]")
+            output.append(f"vpxord zmm14, zmm14, zmm22")
+            output.append(f"vpbroadcastd zmm23, dword ptr [{target.arg64(0)} + 7 * 4]")
+            output.append(f"vpxord zmm15, zmm15, zmm23")
+            # zmm0-zmm15 now contain the final extended state vectors, transposed. We need to un-transpose
+            # them before we write them out. Unlike blake3_avx512_xof_stream_16, we do a complete
+            # un-transpose here, to make the xor step easier.
+            #
+            # First interleave 32-bit words. This takes vectors like:
+            #
+            # a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0
+            #
+            # And produces vectors like:
+            #
+            # a0, a1, b0, b1, e0, e1, g0, g1, i0, i1, k0, k1, m0, m1, o0, o1
+            output.append(f"vpunpckldq zmm16, zmm0, zmm1")
+            output.append(f"vpunpckhdq zmm17, zmm0, zmm1")
+            output.append(f"vpunpckldq zmm18, zmm2, zmm3")
+            output.append(f"vpunpckhdq zmm19, zmm2, zmm3")
+            output.append(f"vpunpckldq zmm20, zmm4, zmm5")
+            output.append(f"vpunpckhdq zmm21, zmm4, zmm5")
+            output.append(f"vpunpckldq zmm22, zmm6, zmm7")
+            output.append(f"vpunpckhdq zmm23, zmm6, zmm7")
+            output.append(f"vpunpckldq zmm24, zmm8, zmm9")
+            output.append(f"vpunpckhdq zmm25, zmm8, zmm9")
+            output.append(f"vpunpckldq zmm26, zmm10, zmm11")
+            output.append(f"vpunpckhdq zmm27, zmm10, zmm11")
+            output.append(f"vpunpckldq zmm28, zmm12, zmm13")
+            output.append(f"vpunpckhdq zmm29, zmm12, zmm13")
+            output.append(f"vpunpckldq zmm30, zmm14, zmm15")
+            output.append(f"vpunpckhdq zmm31, zmm14, zmm15")
+            # Then interleave 64-bit words, producing vectors like:
+            #
+            # a0, a1, a2, a3, e0, e1, e2, e3, i0, i1, i2, i3, m0, m1, m2, m3
+            output.append(f"vpunpcklqdq zmm0, zmm16, zmm18")
+            output.append(f"vpunpckhqdq zmm1, zmm16, zmm18")
+            output.append(f"vpunpcklqdq zmm2, zmm17, zmm19")
+            output.append(f"vpunpckhqdq zmm3, zmm17, zmm19")
+            output.append(f"vpunpcklqdq zmm4, zmm20, zmm22")
+            output.append(f"vpunpckhqdq zmm5, zmm20, zmm22")
+            output.append(f"vpunpcklqdq zmm6, zmm21, zmm23")
+            output.append(f"vpunpckhqdq zmm7, zmm21, zmm23")
+            output.append(f"vpunpcklqdq zmm8, zmm24, zmm26")
+            output.append(f"vpunpckhqdq zmm9, zmm24, zmm26")
+            output.append(f"vpunpcklqdq zmm10, zmm25, zmm27")
+            output.append(f"vpunpckhqdq zmm11, zmm25, zmm27")
+            output.append(f"vpunpcklqdq zmm12, zmm28, zmm30")
+            output.append(f"vpunpckhqdq zmm13, zmm28, zmm30")
+            output.append(f"vpunpcklqdq zmm14, zmm29, zmm31")
+            output.append(f"vpunpckhqdq zmm15, zmm29, zmm31")
+            # Then interleave 128-bit lanes, producing vectors like:
+            #
+            # a0, a1, a2, a3, i0, i1, i2, i3, a4, a5, a6, a7, i4, i5, i6, i7
+            output.append(
+                "vshufi32x4 zmm16, zmm0, zmm4, 0x88"
+            )  # lo lanes: 0x88 = 0b10001000 = (0, 2, 0, 2)
+            output.append(f"vshufi32x4 zmm17, zmm1, zmm5, 0x88")
+            output.append(f"vshufi32x4 zmm18, zmm2, zmm6, 0x88")
+            output.append(f"vshufi32x4 zmm19, zmm3, zmm7, 0x88")
+            output.append(
+                "vshufi32x4 zmm20, zmm0, zmm4, 0xdd"
+            )  # hi lanes: 0xdd = 0b11011101 = (1, 3, 1, 3)
+            output.append(f"vshufi32x4 zmm21, zmm1, zmm5, 0xdd")
+            output.append(f"vshufi32x4 zmm22, zmm2, zmm6, 0xdd")
+            output.append(f"vshufi32x4 zmm23, zmm3, zmm7, 0xdd")
+            output.append(f"vshufi32x4 zmm24, zmm8, zmm12, 0x88")  # lo lanes
+            output.append(f"vshufi32x4 zmm25, zmm9, zmm13, 0x88")
+            output.append(f"vshufi32x4 zmm26, zmm10, zmm14, 0x88")
+            output.append(f"vshufi32x4 zmm27, zmm11, zmm15, 0x88")
+            output.append(f"vshufi32x4 zmm28, zmm8, zmm12, 0xdd")  # hi lanes
+            output.append(f"vshufi32x4 zmm29, zmm9, zmm13, 0xdd")
+            output.append(f"vshufi32x4 zmm30, zmm10, zmm14, 0xdd")
+            output.append(f"vshufi32x4 zmm31, zmm11, zmm15, 0xdd")
+            # Finally interleave 128-bit lanes again (the same permutation as the previous pass, but
+            # different inputs), producing vectors like:
+            #
+            # a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15
+            output.append(f"vshufi32x4 zmm0, zmm16, zmm24, 0x88")  # lo lanes
+            output.append(f"vshufi32x4 zmm1, zmm17, zmm25, 0x88")
+            output.append(f"vshufi32x4 zmm2, zmm18, zmm26, 0x88")
+            output.append(f"vshufi32x4 zmm3, zmm19, zmm27, 0x88")
+            output.append(f"vshufi32x4 zmm4, zmm20, zmm28, 0x88")
+            output.append(f"vshufi32x4 zmm5, zmm21, zmm29, 0x88")
+            output.append(f"vshufi32x4 zmm6, zmm22, zmm30, 0x88")
+            output.append(f"vshufi32x4 zmm7, zmm23, zmm31, 0x88")
+            output.append(f"vshufi32x4 zmm8, zmm16, zmm24, 0xdd")  # hi lanes
+            output.append(f"vshufi32x4 zmm9, zmm17, zmm25, 0xdd")
+            output.append(f"vshufi32x4 zmm10, zmm18, zmm26, 0xdd")
+            output.append(f"vshufi32x4 zmm11, zmm19, zmm27, 0xdd")
+            output.append(f"vshufi32x4 zmm12, zmm20, zmm28, 0xdd")
+            output.append(f"vshufi32x4 zmm13, zmm21, zmm29, 0xdd")
+            output.append(f"vshufi32x4 zmm14, zmm22, zmm30, 0xdd")
+            output.append(f"vshufi32x4 zmm15, zmm23, zmm31, 0xdd")
+            # zmm0-zmm15 now contain the fully un-transposed state words. Load each 64 block on input
+            # (unaligned), perform the xor, and write out the result (again unaligned).
+            output.append(f"vmovdqu32 zmm16, zmmword ptr [{target.arg64(5)} + 0 * 64]")
+            output.append(f"vpxord zmm0, zmm0, zmm16")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 0 * 64], zmm0")
+            output.append(f"vmovdqu32 zmm17, zmmword ptr [{target.arg64(5)} + 1 * 64]")
+            output.append(f"vpxord zmm1, zmm1, zmm17")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 1 * 64], zmm1")
+            output.append(f"vmovdqu32 zmm18, zmmword ptr [{target.arg64(5)} + 2 * 64]")
+            output.append(f"vpxord zmm2, zmm2, zmm18")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 2 * 64], zmm2")
+            output.append(f"vmovdqu32 zmm19, zmmword ptr [{target.arg64(5)} + 3 * 64]")
+            output.append(f"vpxord zmm3, zmm3, zmm19")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 3 * 64], zmm3")
+            output.append(f"vmovdqu32 zmm20, zmmword ptr [{target.arg64(5)} + 4 * 64]")
+            output.append(f"vpxord zmm4, zmm4, zmm20")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 4 * 64], zmm4")
+            output.append(f"vmovdqu32 zmm21, zmmword ptr [{target.arg64(5)} + 5 * 64]")
+            output.append(f"vpxord zmm5, zmm5, zmm21")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 5 * 64], zmm5")
+            output.append(f"vmovdqu32 zmm22, zmmword ptr [{target.arg64(5)} + 6 * 64]")
+            output.append(f"vpxord zmm6, zmm6, zmm22")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 6 * 64], zmm6")
+            output.append(f"vmovdqu32 zmm23, zmmword ptr [{target.arg64(5)} + 7 * 64]")
+            output.append(f"vpxord zmm7, zmm7, zmm23")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 7 * 64], zmm7")
+            output.append(f"vmovdqu32 zmm24, zmmword ptr [{target.arg64(5)} + 8 * 64]")
+            output.append(f"vpxord zmm8, zmm8, zmm24")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 8 * 64], zmm8")
+            output.append(f"vmovdqu32 zmm25, zmmword ptr [{target.arg64(5)} + 9 * 64]")
+            output.append(f"vpxord zmm9, zmm9, zmm25")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 9 * 64], zmm9")
+            output.append(f"vmovdqu32 zmm26, zmmword ptr [{target.arg64(5)} + 10 * 64]")
+            output.append(f"vpxord zmm10, zmm10, zmm26")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 10 * 64], zmm10")
+            output.append(f"vmovdqu32 zmm27, zmmword ptr [{target.arg64(5)} + 11 * 64]")
+            output.append(f"vpxord zmm11, zmm11, zmm27")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 11 * 64], zmm11")
+            output.append(f"vmovdqu32 zmm28, zmmword ptr [{target.arg64(5)} + 12 * 64]")
+            output.append(f"vpxord zmm12, zmm12, zmm28")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 12 * 64], zmm12")
+            output.append(f"vmovdqu32 zmm29, zmmword ptr [{target.arg64(5)} + 13 * 64]")
+            output.append(f"vpxord zmm13, zmm13, zmm29")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 13 * 64], zmm13")
+            output.append(f"vmovdqu32 zmm30, zmmword ptr [{target.arg64(5)} + 14 * 64]")
+            output.append(f"vpxord zmm14, zmm14, zmm30")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 14 * 64], zmm14")
+            output.append(f"vmovdqu32 zmm31, zmmword ptr [{target.arg64(5)} + 15 * 64]")
+            output.append(f"vpxord zmm15, zmm15, zmm31")
+            output.append(f"vmovdqu32 zmmword ptr [{target.arg64(5)} + 15 * 64], zmm15")
+        else:
+            raise NotImplementedError
+    else:
+        raise NotImplementedError
+
+
 def xof_fn(target, output, degree, xor):
     variant = "xor" if xor else "stream"
-    finish_fn_2d = xof_xor_finish2d if xor else xof_stream_finish2d
+    finish_fn_2d = xof_xor_finish_2d if xor else xof_stream_finish_2d
+    finish_fn_3d = xof_xor_finish_3d if xor else xof_stream_finish_3d
     label = f"blake3_{target.extension}_xof_{variant}_{degree}"
     output.append(f".global {label}")
     output.append(f"{label}:")
     if target.extension == AVX512:
         if degree in (1, 2, 4):
-            xof_setup2d(target, output, degree)
-            output.append(f"call {kernel2d_name(target, degree)}")
+            xof_setup_2d(target, output, degree)
+            output.append(f"call {kernel_2d_name(target, degree)}")
             finish_fn_2d(target, output, degree)
+        elif degree in (8, 16):
+            xof_setup_3d(target, output, degree)
+            output.append(f"call {kernel_3d_name(target, degree)}")
+            finish_fn_3d(target, output, degree)
         else:
             raise NotImplementedError
     elif target.extension == AVX2:
         assert degree == 2
-        xof_setup2d(target, output, degree)
-        output.append(f"call {kernel2d_name(target, degree)}")
+        xof_setup_2d(target, output, degree)
+        output.append(f"call {kernel_2d_name(target, degree)}")
         finish_fn_2d(target, output, degree)
     elif target.extension in (SSE41, SSE2):
         assert degree == 1
-        xof_setup2d(target, output, degree)
-        output.append(f"call {kernel2d_name(target, degree)}")
+        xof_setup_2d(target, output, degree)
+        output.append(f"call {kernel_2d_name(target, degree)}")
         finish_fn_2d(target, output, degree)
     else:
         raise NotImplementedError
@@ -877,7 +1429,7 @@
 
 def emit_sse2(target, output):
     target = replace(target, extension=SSE2)
-    kernel2d(target, output, 1)
+    kernel_2d(target, output, 1)
     compress(target, output)
     xof_fn(target, output, 1, xor=False)
     xof_fn(target, output, 1, xor=True)
@@ -894,7 +1446,7 @@
 
 def emit_sse41(target, output):
     target = replace(target, extension=SSE41)
-    kernel2d(target, output, 1)
+    kernel_2d(target, output, 1)
     compress(target, output)
     xof_fn(target, output, 1, xor=False)
     xof_fn(target, output, 1, xor=True)
@@ -902,24 +1454,35 @@
 
 def emit_avx2(target, output):
     target = replace(target, extension=AVX2)
-    kernel2d(target, output, 2)
+    kernel_2d(target, output, 2)
     xof_fn(target, output, 2, xor=False)
     xof_fn(target, output, 2, xor=True)
 
 
 def emit_avx512(target, output):
     target = replace(target, extension=AVX512)
-    kernel2d(target, output, 1)
-    kernel2d(target, output, 2)
-    kernel2d(target, output, 4)
+
+    # degree 1
+    kernel_2d(target, output, 1)
     compress(target, output)
     xof_fn(target, output, 1, xor=False)
     xof_fn(target, output, 1, xor=True)
+
+    # degree 2
+    kernel_2d(target, output, 2)
     xof_fn(target, output, 2, xor=False)
     xof_fn(target, output, 2, xor=True)
+
+    # degree 4
+    kernel_2d(target, output, 4)
     xof_fn(target, output, 4, xor=False)
     xof_fn(target, output, 4, xor=True)
 
+    # degree 16
+    kernel_3d(target, output, 16)
+    xof_fn(target, output, 16, xor=False)
+    xof_fn(target, output, 16, xor=True)
+
 
 def emit_footer(target, output):
     output.append(".balign 16")
@@ -942,6 +1505,14 @@
     output.append(".balign 64")
     output.append("INCREMENT_2D:")
     output.append(".quad  0, 0, 1, 0, 2, 0, 3, 0")
+    output.append("INCREMENT_3D:")
+    output.append(".quad  0, 1, 2, 3, 4, 5, 6, 7")
+
+    output.append(".balign 64")
+    output.append("EVEN_INDEXES:")
+    output.append(".long 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30")
+    output.append("ODD_INDEXES:")
+    output.append(".long 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31")
 
 
 def format(output):
diff --git a/asm/out.S b/asm/out.S
index 9d5f77f..2c802e5 100644
--- a/asm/out.S
+++ b/asm/out.S
@@ -1,5 +1,5 @@
 # This file is generated by asm.py. Don't edit this file directly.
-blake3_sse2_kernel2d_1:
+blake3_sse2_kernel_2d_1:
         paddd xmm0, xmm4
         paddd xmm0, xmm1
         pxor xmm3, xmm0
@@ -531,7 +531,7 @@
         pshufd  xmm6, xmm6, 0x93
         shufps  xmm8, xmm7, 221
         pshufd  xmm7, xmm8, 0x93
-        call blake3_sse2_kernel2d_1
+        call blake3_sse2_kernel_2d_1
         movups xmmword ptr [rdi], xmm0
         movups xmmword ptr [rdi+0x10], xmm1
         ret
@@ -559,7 +559,7 @@
         pshufd  xmm6, xmm6, 0x93
         shufps  xmm8, xmm7, 221
         pshufd  xmm7, xmm8, 0x93
-        call blake3_sse2_kernel2d_1
+        call blake3_sse2_kernel_2d_1
         movdqu xmm4, xmmword ptr [rdi]
         movdqu xmm5, xmmword ptr [rdi+0x10]
         pxor xmm2, xmm4
@@ -593,7 +593,7 @@
         pshufd  xmm6, xmm6, 0x93
         shufps  xmm8, xmm7, 221
         pshufd  xmm7, xmm8, 0x93
-        call blake3_sse2_kernel2d_1
+        call blake3_sse2_kernel_2d_1
         movdqu xmm4, xmmword ptr [rdi]
         movdqu xmm5, xmmword ptr [rdi+0x10]
         pxor xmm2, xmm4
@@ -620,7 +620,7 @@
 .long 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000
 PBLENDW_0xC0_MASK:
 .long 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF
-blake3_sse41_kernel2d_1:
+blake3_sse41_kernel_2d_1:
         movaps xmm14, xmmword ptr [ROT8+rip]
         movaps xmm15, xmmword ptr [ROT16+rip]
         paddd xmm0, xmm4
@@ -1068,7 +1068,7 @@
         pshufd  xmm6, xmm6, 0x93
         shufps  xmm8, xmm7, 221
         pshufd  xmm7, xmm8, 0x93
-        call blake3_sse41_kernel2d_1
+        call blake3_sse41_kernel_2d_1
         movups xmmword ptr [rdi], xmm0
         movups xmmword ptr [rdi+0x10], xmm1
         ret
@@ -1096,7 +1096,7 @@
         pshufd  xmm6, xmm6, 0x93
         shufps  xmm8, xmm7, 221
         pshufd  xmm7, xmm8, 0x93
-        call blake3_sse41_kernel2d_1
+        call blake3_sse41_kernel_2d_1
         movdqu xmm4, xmmword ptr [rdi]
         movdqu xmm5, xmmword ptr [rdi+0x10]
         pxor xmm2, xmm4
@@ -1130,7 +1130,7 @@
         pshufd  xmm6, xmm6, 0x93
         shufps  xmm8, xmm7, 221
         pshufd  xmm7, xmm8, 0x93
-        call blake3_sse41_kernel2d_1
+        call blake3_sse41_kernel_2d_1
         movdqu xmm4, xmmword ptr [rdi]
         movdqu xmm5, xmmword ptr [rdi+0x10]
         pxor xmm2, xmm4
@@ -1148,7 +1148,7 @@
         movups xmmword ptr [r9+0x20], xmm2
         movups xmmword ptr [r9+0x30], xmm3
         ret
-blake3_avx2_kernel2d_2:
+blake3_avx2_kernel_2d_2:
         vbroadcasti128 ymm14, xmmword ptr [ROT16+rip]
         vbroadcasti128 ymm15, xmmword ptr [ROT8+rip]
         vpaddd ymm0, ymm0, ymm4
@@ -1549,7 +1549,7 @@
         vshufps ymm7, ymm8, ymm9, 221
         vpshufd ymm6, ymm6, 0x93
         vpshufd ymm7, ymm7, 0x93
-        call blake3_avx2_kernel2d_2
+        call blake3_avx2_kernel_2d_2
         vbroadcasti128 ymm4, xmmword ptr [rdi]
         vpxor ymm2, ymm2, ymm4
         vbroadcasti128 ymm5, xmmword ptr [rdi + 16]
@@ -1586,7 +1586,7 @@
         vshufps ymm7, ymm8, ymm9, 221
         vpshufd ymm6, ymm6, 0x93
         vpshufd ymm7, ymm7, 0x93
-        call blake3_avx2_kernel2d_2
+        call blake3_avx2_kernel_2d_2
         vbroadcasti128 ymm4, xmmword ptr [rdi]
         vpxor ymm2, ymm2, ymm4
         vbroadcasti128 ymm5, xmmword ptr [rdi + 16]
@@ -1604,7 +1604,7 @@
         vmovdqu ymmword ptr [r9 + 2 * 32], ymm6
         vmovdqu ymmword ptr [r9 + 3 * 32], ymm7
         ret
-blake3_avx512_kernel2d_1:
+blake3_avx512_kernel_2d_1:
         vpaddd xmm0, xmm0, xmm4
         vpaddd xmm0, xmm0, xmm1
         vpxord xmm3, xmm3, xmm0
@@ -1924,7 +1924,94 @@
         vpxord xmm0, xmm0, xmm2
         vpxord xmm1, xmm1, xmm3
         ret
-blake3_avx512_kernel2d_2:
+.global blake3_avx512_compress
+blake3_avx512_compress:
+        vmovdqu xmm0, xmmword ptr [rdi]
+        vmovdqu xmm1, xmmword ptr [rdi+0x10]
+        shl r8, 32
+        mov ecx, ecx
+        or rcx, r8
+        vmovq xmm3, rdx
+        vmovq xmm4, rcx
+        vpunpcklqdq xmm3, xmm3, xmm4
+        vmovaps xmm2, xmmword ptr [BLAKE3_IV+rip]
+        vmovups xmm8, xmmword ptr [rsi]
+        vmovups xmm9, xmmword ptr [rsi+0x10]
+        vshufps xmm4, xmm8, xmm9, 136
+        vshufps xmm5, xmm8, xmm9, 221
+        vmovups xmm8, xmmword ptr [rsi+0x20]
+        vmovups xmm9, xmmword ptr [rsi+0x30]
+        vshufps xmm6, xmm8, xmm9, 136
+        vshufps xmm7, xmm8, xmm9, 221
+        vpshufd xmm6, xmm6, 0x93
+        vpshufd xmm7, xmm7, 0x93
+        call blake3_avx512_kernel_2d_1
+        vmovdqu xmmword ptr [rdi], xmm0
+        vmovdqu xmmword ptr [rdi+0x10], xmm1
+        ret
+.global blake3_avx512_xof_stream_1
+blake3_avx512_xof_stream_1:
+        vmovdqu xmm0, xmmword ptr [rdi]
+        vmovdqu xmm1, xmmword ptr [rdi+0x10]
+        shl r8, 32
+        mov ecx, ecx
+        or rcx, r8
+        vmovq xmm3, rdx
+        vmovq xmm4, rcx
+        vpunpcklqdq xmm3, xmm3, xmm4
+        vmovaps xmm2, xmmword ptr [BLAKE3_IV+rip]
+        vmovups xmm8, xmmword ptr [rsi]
+        vmovups xmm9, xmmword ptr [rsi+0x10]
+        vshufps xmm4, xmm8, xmm9, 136
+        vshufps xmm5, xmm8, xmm9, 221
+        vmovups xmm8, xmmword ptr [rsi+0x20]
+        vmovups xmm9, xmmword ptr [rsi+0x30]
+        vshufps xmm6, xmm8, xmm9, 136
+        vshufps xmm7, xmm8, xmm9, 221
+        vpshufd xmm6, xmm6, 0x93
+        vpshufd xmm7, xmm7, 0x93
+        call blake3_avx512_kernel_2d_1
+        vpxor xmm2, xmm2, [rdi]
+        vpxor xmm3, xmm3, [rdi+0x10]
+        vmovdqu xmmword ptr [r9], xmm0
+        vmovdqu xmmword ptr [r9+0x10], xmm1
+        vmovdqu xmmword ptr [r9+0x20], xmm2
+        vmovdqu xmmword ptr [r9+0x30], xmm3
+        ret
+.global blake3_avx512_xof_xor_1
+blake3_avx512_xof_xor_1:
+        vmovdqu xmm0, xmmword ptr [rdi]
+        vmovdqu xmm1, xmmword ptr [rdi+0x10]
+        shl r8, 32
+        mov ecx, ecx
+        or rcx, r8
+        vmovq xmm3, rdx
+        vmovq xmm4, rcx
+        vpunpcklqdq xmm3, xmm3, xmm4
+        vmovaps xmm2, xmmword ptr [BLAKE3_IV+rip]
+        vmovups xmm8, xmmword ptr [rsi]
+        vmovups xmm9, xmmword ptr [rsi+0x10]
+        vshufps xmm4, xmm8, xmm9, 136
+        vshufps xmm5, xmm8, xmm9, 221
+        vmovups xmm8, xmmword ptr [rsi+0x20]
+        vmovups xmm9, xmmword ptr [rsi+0x30]
+        vshufps xmm6, xmm8, xmm9, 136
+        vshufps xmm7, xmm8, xmm9, 221
+        vpshufd xmm6, xmm6, 0x93
+        vpshufd xmm7, xmm7, 0x93
+        call blake3_avx512_kernel_2d_1
+        vpxor xmm2, xmm2, [rdi]
+        vpxor xmm3, xmm3, [rdi+0x10]
+        vpxor xmm0, xmm0, [r9]
+        vpxor xmm1, xmm1, [r9+0x10]
+        vpxor xmm2, xmm2, [r9+0x20]
+        vpxor xmm3, xmm3, [r9+0x30]
+        vmovdqu xmmword ptr [r9], xmm0
+        vmovdqu xmmword ptr [r9+0x10], xmm1
+        vmovdqu xmmword ptr [r9+0x20], xmm2
+        vmovdqu xmmword ptr [r9+0x30], xmm3
+        ret
+blake3_avx512_kernel_2d_2:
         vpaddd ymm0, ymm0, ymm4
         vpaddd ymm0, ymm0, ymm1
         vpxord ymm3, ymm3, ymm0
@@ -2244,7 +2331,85 @@
         vpxord ymm0, ymm0, ymm2
         vpxord ymm1, ymm1, ymm3
         ret
-blake3_avx512_kernel2d_4:
+.global blake3_avx512_xof_stream_2
+blake3_avx512_xof_stream_2:
+        vbroadcasti128 ymm0, xmmword ptr [rdi]
+        vbroadcasti128 ymm1, xmmword ptr [rdi+0x10]
+        vmovdqa ymm4, ymmword ptr [INCREMENT_2D+rip]
+        vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV+rip]
+        vpbroadcastq ymm5, rdx
+        vpaddq ymm6, ymm4, ymm5
+        shl r8, 32
+        mov ecx, ecx
+        or rcx, r8
+        vpbroadcastq ymm7, rcx
+        vpblendd ymm3, ymm6, ymm7, 0xCC
+        vbroadcasti128 ymm8, xmmword ptr [rsi]
+        vbroadcasti128 ymm9, xmmword ptr [rsi+0x10]
+        vshufps ymm4, ymm8, ymm9, 136
+        vshufps ymm5, ymm8, ymm9, 221
+        vbroadcasti128 ymm8, xmmword ptr [rsi+0x20]
+        vbroadcasti128 ymm9, xmmword ptr [rsi+0x30]
+        vshufps ymm6, ymm8, ymm9, 136
+        vshufps ymm7, ymm8, ymm9, 221
+        vpshufd ymm6, ymm6, 0x93
+        vpshufd ymm7, ymm7, 0x93
+        call blake3_avx512_kernel_2d_2
+        vbroadcasti128 ymm4, xmmword ptr [rdi]
+        vpxor ymm2, ymm2, ymm4
+        vbroadcasti128 ymm5, xmmword ptr [rdi + 16]
+        vpxor ymm3, ymm3, ymm5
+        vmovdqu xmmword ptr [r9 + 0 * 16], xmm0
+        vmovdqu xmmword ptr [r9 + 1 * 16], xmm1
+        vmovdqu xmmword ptr [r9 + 2 * 16], xmm2
+        vmovdqu xmmword ptr [r9 + 3 * 16], xmm3
+        vextracti128 xmmword ptr [r9+4*16], ymm0, 1
+        vextracti128 xmmword ptr [r9+5*16], ymm1, 1
+        vextracti128 xmmword ptr [r9+6*16], ymm2, 1
+        vextracti128 xmmword ptr [r9+7*16], ymm3, 1
+        ret
+.global blake3_avx512_xof_xor_2
+blake3_avx512_xof_xor_2:
+        vbroadcasti128 ymm0, xmmword ptr [rdi]
+        vbroadcasti128 ymm1, xmmword ptr [rdi+0x10]
+        vmovdqa ymm4, ymmword ptr [INCREMENT_2D+rip]
+        vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV+rip]
+        vpbroadcastq ymm5, rdx
+        vpaddq ymm6, ymm4, ymm5
+        shl r8, 32
+        mov ecx, ecx
+        or rcx, r8
+        vpbroadcastq ymm7, rcx
+        vpblendd ymm3, ymm6, ymm7, 0xCC
+        vbroadcasti128 ymm8, xmmword ptr [rsi]
+        vbroadcasti128 ymm9, xmmword ptr [rsi+0x10]
+        vshufps ymm4, ymm8, ymm9, 136
+        vshufps ymm5, ymm8, ymm9, 221
+        vbroadcasti128 ymm8, xmmword ptr [rsi+0x20]
+        vbroadcasti128 ymm9, xmmword ptr [rsi+0x30]
+        vshufps ymm6, ymm8, ymm9, 136
+        vshufps ymm7, ymm8, ymm9, 221
+        vpshufd ymm6, ymm6, 0x93
+        vpshufd ymm7, ymm7, 0x93
+        call blake3_avx512_kernel_2d_2
+        vbroadcasti128 ymm4, xmmword ptr [rdi]
+        vpxor ymm2, ymm2, ymm4
+        vbroadcasti128 ymm5, xmmword ptr [rdi + 16]
+        vpxor ymm3, ymm3, ymm5
+        vperm2f128 ymm4, ymm0, ymm1, 32
+        vperm2f128 ymm5, ymm2, ymm3, 32
+        vperm2f128 ymm6, ymm0, ymm1, 49
+        vperm2f128 ymm7, ymm2, ymm3, 49
+        vpxor ymm4, ymm4, ymmword ptr [r9 + 0 * 32]
+        vpxor ymm5, ymm5, ymmword ptr [r9 + 1 * 32]
+        vpxor ymm6, ymm6, ymmword ptr [r9 + 2 * 32]
+        vpxor ymm7, ymm7, ymmword ptr [r9 + 3 * 32]
+        vmovdqu ymmword ptr [r9 + 0 * 32], ymm4
+        vmovdqu ymmword ptr [r9 + 1 * 32], ymm5
+        vmovdqu ymmword ptr [r9 + 2 * 32], ymm6
+        vmovdqu ymmword ptr [r9 + 3 * 32], ymm7
+        ret
+blake3_avx512_kernel_2d_4:
         mov eax, 43690
         kmovw k3, eax
         mov eax, 34952
@@ -2568,171 +2733,6 @@
         vpxord zmm0, zmm0, zmm2
         vpxord zmm1, zmm1, zmm3
         ret
-.global blake3_avx512_compress
-blake3_avx512_compress:
-        vmovdqu xmm0, xmmword ptr [rdi]
-        vmovdqu xmm1, xmmword ptr [rdi+0x10]
-        shl r8, 32
-        mov ecx, ecx
-        or rcx, r8
-        vmovq xmm3, rdx
-        vmovq xmm4, rcx
-        vpunpcklqdq xmm3, xmm3, xmm4
-        vmovaps xmm2, xmmword ptr [BLAKE3_IV+rip]
-        vmovups xmm8, xmmword ptr [rsi]
-        vmovups xmm9, xmmword ptr [rsi+0x10]
-        vshufps xmm4, xmm8, xmm9, 136
-        vshufps xmm5, xmm8, xmm9, 221
-        vmovups xmm8, xmmword ptr [rsi+0x20]
-        vmovups xmm9, xmmword ptr [rsi+0x30]
-        vshufps xmm6, xmm8, xmm9, 136
-        vshufps xmm7, xmm8, xmm9, 221
-        vpshufd xmm6, xmm6, 0x93
-        vpshufd xmm7, xmm7, 0x93
-        call blake3_avx512_kernel2d_1
-        vmovdqu xmmword ptr [rdi], xmm0
-        vmovdqu xmmword ptr [rdi+0x10], xmm1
-        ret
-.global blake3_avx512_xof_stream_1
-blake3_avx512_xof_stream_1:
-        vmovdqu xmm0, xmmword ptr [rdi]
-        vmovdqu xmm1, xmmword ptr [rdi+0x10]
-        shl r8, 32
-        mov ecx, ecx
-        or rcx, r8
-        vmovq xmm3, rdx
-        vmovq xmm4, rcx
-        vpunpcklqdq xmm3, xmm3, xmm4
-        vmovaps xmm2, xmmword ptr [BLAKE3_IV+rip]
-        vmovups xmm8, xmmword ptr [rsi]
-        vmovups xmm9, xmmword ptr [rsi+0x10]
-        vshufps xmm4, xmm8, xmm9, 136
-        vshufps xmm5, xmm8, xmm9, 221
-        vmovups xmm8, xmmword ptr [rsi+0x20]
-        vmovups xmm9, xmmword ptr [rsi+0x30]
-        vshufps xmm6, xmm8, xmm9, 136
-        vshufps xmm7, xmm8, xmm9, 221
-        vpshufd xmm6, xmm6, 0x93
-        vpshufd xmm7, xmm7, 0x93
-        call blake3_avx512_kernel2d_1
-        vpxor xmm2, xmm2, [rdi]
-        vpxor xmm3, xmm3, [rdi+0x10]
-        vmovdqu xmmword ptr [r9], xmm0
-        vmovdqu xmmword ptr [r9+0x10], xmm1
-        vmovdqu xmmword ptr [r9+0x20], xmm2
-        vmovdqu xmmword ptr [r9+0x30], xmm3
-        ret
-.global blake3_avx512_xof_xor_1
-blake3_avx512_xof_xor_1:
-        vmovdqu xmm0, xmmword ptr [rdi]
-        vmovdqu xmm1, xmmword ptr [rdi+0x10]
-        shl r8, 32
-        mov ecx, ecx
-        or rcx, r8
-        vmovq xmm3, rdx
-        vmovq xmm4, rcx
-        vpunpcklqdq xmm3, xmm3, xmm4
-        vmovaps xmm2, xmmword ptr [BLAKE3_IV+rip]
-        vmovups xmm8, xmmword ptr [rsi]
-        vmovups xmm9, xmmword ptr [rsi+0x10]
-        vshufps xmm4, xmm8, xmm9, 136
-        vshufps xmm5, xmm8, xmm9, 221
-        vmovups xmm8, xmmword ptr [rsi+0x20]
-        vmovups xmm9, xmmword ptr [rsi+0x30]
-        vshufps xmm6, xmm8, xmm9, 136
-        vshufps xmm7, xmm8, xmm9, 221
-        vpshufd xmm6, xmm6, 0x93
-        vpshufd xmm7, xmm7, 0x93
-        call blake3_avx512_kernel2d_1
-        vpxor xmm2, xmm2, [rdi]
-        vpxor xmm3, xmm3, [rdi+0x10]
-        vpxor xmm0, xmm0, [r9]
-        vpxor xmm1, xmm1, [r9+0x10]
-        vpxor xmm2, xmm2, [r9+0x20]
-        vpxor xmm3, xmm3, [r9+0x30]
-        vmovdqu xmmword ptr [r9], xmm0
-        vmovdqu xmmword ptr [r9+0x10], xmm1
-        vmovdqu xmmword ptr [r9+0x20], xmm2
-        vmovdqu xmmword ptr [r9+0x30], xmm3
-        ret
-.global blake3_avx512_xof_stream_2
-blake3_avx512_xof_stream_2:
-        vbroadcasti128 ymm0, xmmword ptr [rdi]
-        vbroadcasti128 ymm1, xmmword ptr [rdi+0x10]
-        vmovdqa ymm4, ymmword ptr [INCREMENT_2D+rip]
-        vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV+rip]
-        vpbroadcastq ymm5, rdx
-        vpaddq ymm6, ymm4, ymm5
-        shl r8, 32
-        mov ecx, ecx
-        or rcx, r8
-        vpbroadcastq ymm7, rcx
-        vpblendd ymm3, ymm6, ymm7, 0xCC
-        vbroadcasti128 ymm8, xmmword ptr [rsi]
-        vbroadcasti128 ymm9, xmmword ptr [rsi+0x10]
-        vshufps ymm4, ymm8, ymm9, 136
-        vshufps ymm5, ymm8, ymm9, 221
-        vbroadcasti128 ymm8, xmmword ptr [rsi+0x20]
-        vbroadcasti128 ymm9, xmmword ptr [rsi+0x30]
-        vshufps ymm6, ymm8, ymm9, 136
-        vshufps ymm7, ymm8, ymm9, 221
-        vpshufd ymm6, ymm6, 0x93
-        vpshufd ymm7, ymm7, 0x93
-        call blake3_avx512_kernel2d_2
-        vbroadcasti128 ymm4, xmmword ptr [rdi]
-        vpxor ymm2, ymm2, ymm4
-        vbroadcasti128 ymm5, xmmword ptr [rdi + 16]
-        vpxor ymm3, ymm3, ymm5
-        vmovdqu xmmword ptr [r9 + 0 * 16], xmm0
-        vmovdqu xmmword ptr [r9 + 1 * 16], xmm1
-        vmovdqu xmmword ptr [r9 + 2 * 16], xmm2
-        vmovdqu xmmword ptr [r9 + 3 * 16], xmm3
-        vextracti128 xmmword ptr [r9+4*16], ymm0, 1
-        vextracti128 xmmword ptr [r9+5*16], ymm1, 1
-        vextracti128 xmmword ptr [r9+6*16], ymm2, 1
-        vextracti128 xmmword ptr [r9+7*16], ymm3, 1
-        ret
-.global blake3_avx512_xof_xor_2
-blake3_avx512_xof_xor_2:
-        vbroadcasti128 ymm0, xmmword ptr [rdi]
-        vbroadcasti128 ymm1, xmmword ptr [rdi+0x10]
-        vmovdqa ymm4, ymmword ptr [INCREMENT_2D+rip]
-        vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV+rip]
-        vpbroadcastq ymm5, rdx
-        vpaddq ymm6, ymm4, ymm5
-        shl r8, 32
-        mov ecx, ecx
-        or rcx, r8
-        vpbroadcastq ymm7, rcx
-        vpblendd ymm3, ymm6, ymm7, 0xCC
-        vbroadcasti128 ymm8, xmmword ptr [rsi]
-        vbroadcasti128 ymm9, xmmword ptr [rsi+0x10]
-        vshufps ymm4, ymm8, ymm9, 136
-        vshufps ymm5, ymm8, ymm9, 221
-        vbroadcasti128 ymm8, xmmword ptr [rsi+0x20]
-        vbroadcasti128 ymm9, xmmword ptr [rsi+0x30]
-        vshufps ymm6, ymm8, ymm9, 136
-        vshufps ymm7, ymm8, ymm9, 221
-        vpshufd ymm6, ymm6, 0x93
-        vpshufd ymm7, ymm7, 0x93
-        call blake3_avx512_kernel2d_2
-        vbroadcasti128 ymm4, xmmword ptr [rdi]
-        vpxor ymm2, ymm2, ymm4
-        vbroadcasti128 ymm5, xmmword ptr [rdi + 16]
-        vpxor ymm3, ymm3, ymm5
-        vperm2f128 ymm4, ymm0, ymm1, 32
-        vperm2f128 ymm5, ymm2, ymm3, 32
-        vperm2f128 ymm6, ymm0, ymm1, 49
-        vperm2f128 ymm7, ymm2, ymm3, 49
-        vpxor ymm4, ymm4, ymmword ptr [r9 + 0 * 32]
-        vpxor ymm5, ymm5, ymmword ptr [r9 + 1 * 32]
-        vpxor ymm6, ymm6, ymmword ptr [r9 + 2 * 32]
-        vpxor ymm7, ymm7, ymmword ptr [r9 + 3 * 32]
-        vmovdqu ymmword ptr [r9 + 0 * 32], ymm4
-        vmovdqu ymmword ptr [r9 + 1 * 32], ymm5
-        vmovdqu ymmword ptr [r9 + 2 * 32], ymm6
-        vmovdqu ymmword ptr [r9 + 3 * 32], ymm7
-        ret
 .global blake3_avx512_xof_stream_4
 blake3_avx512_xof_stream_4:
         vbroadcasti32x4 zmm0, xmmword ptr [rdi]
@@ -2758,7 +2758,7 @@
         vshufps zmm7, zmm8, zmm9, 221
         vpshufd zmm6, zmm6, 0x93
         vpshufd zmm7, zmm7, 0x93
-        call blake3_avx512_kernel2d_4
+        call blake3_avx512_kernel_2d_4
         vbroadcasti32x4 zmm4, xmmword ptr [rdi]
         vpxord zmm2, zmm2, zmm4
         vbroadcasti32x4 zmm5, xmmword ptr [rdi + 16]
@@ -2805,7 +2805,7 @@
         vshufps zmm7, zmm8, zmm9, 221
         vpshufd zmm6, zmm6, 0x93
         vpshufd zmm7, zmm7, 0x93
-        call blake3_avx512_kernel2d_4
+        call blake3_avx512_kernel_2d_4
         vbroadcasti32x4 zmm4, xmmword ptr [rdi]
         vpxord zmm2, zmm2, zmm4
         vbroadcasti32x4 zmm5, xmmword ptr [rdi + 16]
@@ -2827,6 +2827,1128 @@
         vmovdqu32 zmmword ptr [r9 + 2*64], zmm2
         vmovdqu32 zmmword ptr [r9 + 3*64], zmm3
         ret
+blake3_avx512_kernel_3d_16:
+        vpaddd zmm0, zmm0, zmm16
+        vpaddd zmm1, zmm1, zmm18
+        vpaddd zmm2, zmm2, zmm20
+        vpaddd zmm3, zmm3, zmm22
+        vpaddd zmm0, zmm0, zmm4
+        vpaddd zmm1, zmm1, zmm5
+        vpaddd zmm2, zmm2, zmm6
+        vpaddd zmm3, zmm3, zmm7
+        vpxord zmm12, zmm12, zmm0
+        vpxord zmm13, zmm13, zmm1
+        vpxord zmm14, zmm14, zmm2
+        vpxord zmm15, zmm15, zmm3
+        vprord zmm12, zmm12, 16
+        vprord zmm13, zmm13, 16
+        vprord zmm14, zmm14, 16
+        vprord zmm15, zmm15, 16
+        vpaddd zmm8, zmm8, zmm12
+        vpaddd zmm9, zmm9, zmm13
+        vpaddd zmm10, zmm10, zmm14
+        vpaddd zmm11, zmm11, zmm15
+        vpxord zmm4, zmm4, zmm8
+        vpxord zmm5, zmm5, zmm9
+        vpxord zmm6, zmm6, zmm10
+        vpxord zmm7, zmm7, zmm11
+        vprord zmm4, zmm4, 12
+        vprord zmm5, zmm5, 12
+        vprord zmm6, zmm6, 12
+        vprord zmm7, zmm7, 12
+        vpaddd zmm0, zmm0, zmm17
+        vpaddd zmm1, zmm1, zmm19
+        vpaddd zmm2, zmm2, zmm21
+        vpaddd zmm3, zmm3, zmm23
+        vpaddd zmm0, zmm0, zmm4
+        vpaddd zmm1, zmm1, zmm5
+        vpaddd zmm2, zmm2, zmm6
+        vpaddd zmm3, zmm3, zmm7
+        vpxord zmm12, zmm12, zmm0
+        vpxord zmm13, zmm13, zmm1
+        vpxord zmm14, zmm14, zmm2
+        vpxord zmm15, zmm15, zmm3
+        vprord zmm12, zmm12, 8
+        vprord zmm13, zmm13, 8
+        vprord zmm14, zmm14, 8
+        vprord zmm15, zmm15, 8
+        vpaddd zmm8, zmm8, zmm12
+        vpaddd zmm9, zmm9, zmm13
+        vpaddd zmm10, zmm10, zmm14
+        vpaddd zmm11, zmm11, zmm15
+        vpxord zmm4, zmm4, zmm8
+        vpxord zmm5, zmm5, zmm9
+        vpxord zmm6, zmm6, zmm10
+        vpxord zmm7, zmm7, zmm11
+        vprord zmm4, zmm4, 7
+        vprord zmm5, zmm5, 7
+        vprord zmm6, zmm6, 7
+        vprord zmm7, zmm7, 7
+        vpaddd zmm0, zmm0, zmm24
+        vpaddd zmm1, zmm1, zmm26
+        vpaddd zmm2, zmm2, zmm28
+        vpaddd zmm3, zmm3, zmm30
+        vpaddd zmm0, zmm0, zmm5
+        vpaddd zmm1, zmm1, zmm6
+        vpaddd zmm2, zmm2, zmm7
+        vpaddd zmm3, zmm3, zmm4
+        vpxord zmm15, zmm15, zmm0
+        vpxord zmm12, zmm12, zmm1
+        vpxord zmm13, zmm13, zmm2
+        vpxord zmm14, zmm14, zmm3
+        vprord zmm15, zmm15, 16
+        vprord zmm12, zmm12, 16
+        vprord zmm13, zmm13, 16
+        vprord zmm14, zmm14, 16
+        vpaddd zmm10, zmm10, zmm15
+        vpaddd zmm11, zmm11, zmm12
+        vpaddd zmm8, zmm8, zmm13
+        vpaddd zmm9, zmm9, zmm14
+        vpxord zmm5, zmm5, zmm10
+        vpxord zmm6, zmm6, zmm11
+        vpxord zmm7, zmm7, zmm8
+        vpxord zmm4, zmm4, zmm9
+        vprord zmm5, zmm5, 12
+        vprord zmm6, zmm6, 12
+        vprord zmm7, zmm7, 12
+        vprord zmm4, zmm4, 12
+        vpaddd zmm0, zmm0, zmm25
+        vpaddd zmm1, zmm1, zmm27
+        vpaddd zmm2, zmm2, zmm29
+        vpaddd zmm3, zmm3, zmm31
+        vpaddd zmm0, zmm0, zmm5
+        vpaddd zmm1, zmm1, zmm6
+        vpaddd zmm2, zmm2, zmm7
+        vpaddd zmm3, zmm3, zmm4
+        vpxord zmm15, zmm15, zmm0
+        vpxord zmm12, zmm12, zmm1
+        vpxord zmm13, zmm13, zmm2
+        vpxord zmm14, zmm14, zmm3
+        vprord zmm15, zmm15, 8
+        vprord zmm12, zmm12, 8
+        vprord zmm13, zmm13, 8
+        vprord zmm14, zmm14, 8
+        vpaddd zmm10, zmm10, zmm15
+        vpaddd zmm11, zmm11, zmm12
+        vpaddd zmm8, zmm8, zmm13
+        vpaddd zmm9, zmm9, zmm14
+        vpxord zmm5, zmm5, zmm10
+        vpxord zmm6, zmm6, zmm11
+        vpxord zmm7, zmm7, zmm8
+        vpxord zmm4, zmm4, zmm9
+        vprord zmm5, zmm5, 7
+        vprord zmm6, zmm6, 7
+        vprord zmm7, zmm7, 7
+        vprord zmm4, zmm4, 7
+        vpaddd zmm0, zmm0, zmm18
+        vpaddd zmm1, zmm1, zmm19
+        vpaddd zmm2, zmm2, zmm23
+        vpaddd zmm3, zmm3, zmm20
+        vpaddd zmm0, zmm0, zmm4
+        vpaddd zmm1, zmm1, zmm5
+        vpaddd zmm2, zmm2, zmm6
+        vpaddd zmm3, zmm3, zmm7
+        vpxord zmm12, zmm12, zmm0
+        vpxord zmm13, zmm13, zmm1
+        vpxord zmm14, zmm14, zmm2
+        vpxord zmm15, zmm15, zmm3
+        vprord zmm12, zmm12, 16
+        vprord zmm13, zmm13, 16
+        vprord zmm14, zmm14, 16
+        vprord zmm15, zmm15, 16
+        vpaddd zmm8, zmm8, zmm12
+        vpaddd zmm9, zmm9, zmm13
+        vpaddd zmm10, zmm10, zmm14
+        vpaddd zmm11, zmm11, zmm15
+        vpxord zmm4, zmm4, zmm8
+        vpxord zmm5, zmm5, zmm9
+        vpxord zmm6, zmm6, zmm10
+        vpxord zmm7, zmm7, zmm11
+        vprord zmm4, zmm4, 12
+        vprord zmm5, zmm5, 12
+        vprord zmm6, zmm6, 12
+        vprord zmm7, zmm7, 12
+        vpaddd zmm0, zmm0, zmm22
+        vpaddd zmm1, zmm1, zmm26
+        vpaddd zmm2, zmm2, zmm16
+        vpaddd zmm3, zmm3, zmm29
+        vpaddd zmm0, zmm0, zmm4
+        vpaddd zmm1, zmm1, zmm5
+        vpaddd zmm2, zmm2, zmm6
+        vpaddd zmm3, zmm3, zmm7
+        vpxord zmm12, zmm12, zmm0
+        vpxord zmm13, zmm13, zmm1
+        vpxord zmm14, zmm14, zmm2
+        vpxord zmm15, zmm15, zmm3
+        vprord zmm12, zmm12, 8
+        vprord zmm13, zmm13, 8
+        vprord zmm14, zmm14, 8
+        vprord zmm15, zmm15, 8
+        vpaddd zmm8, zmm8, zmm12
+        vpaddd zmm9, zmm9, zmm13
+        vpaddd zmm10, zmm10, zmm14
+        vpaddd zmm11, zmm11, zmm15
+        vpxord zmm4, zmm4, zmm8
+        vpxord zmm5, zmm5, zmm9
+        vpxord zmm6, zmm6, zmm10
+        vpxord zmm7, zmm7, zmm11
+        vprord zmm4, zmm4, 7
+        vprord zmm5, zmm5, 7
+        vprord zmm6, zmm6, 7
+        vprord zmm7, zmm7, 7
+        vpaddd zmm0, zmm0, zmm17
+        vpaddd zmm1, zmm1, zmm28
+        vpaddd zmm2, zmm2, zmm25
+        vpaddd zmm3, zmm3, zmm31
+        vpaddd zmm0, zmm0, zmm5
+        vpaddd zmm1, zmm1, zmm6
+        vpaddd zmm2, zmm2, zmm7
+        vpaddd zmm3, zmm3, zmm4
+        vpxord zmm15, zmm15, zmm0
+        vpxord zmm12, zmm12, zmm1
+        vpxord zmm13, zmm13, zmm2
+        vpxord zmm14, zmm14, zmm3
+        vprord zmm15, zmm15, 16
+        vprord zmm12, zmm12, 16
+        vprord zmm13, zmm13, 16
+        vprord zmm14, zmm14, 16
+        vpaddd zmm10, zmm10, zmm15
+        vpaddd zmm11, zmm11, zmm12
+        vpaddd zmm8, zmm8, zmm13
+        vpaddd zmm9, zmm9, zmm14
+        vpxord zmm5, zmm5, zmm10
+        vpxord zmm6, zmm6, zmm11
+        vpxord zmm7, zmm7, zmm8
+        vpxord zmm4, zmm4, zmm9
+        vprord zmm5, zmm5, 12
+        vprord zmm6, zmm6, 12
+        vprord zmm7, zmm7, 12
+        vprord zmm4, zmm4, 12
+        vpaddd zmm0, zmm0, zmm27
+        vpaddd zmm1, zmm1, zmm21
+        vpaddd zmm2, zmm2, zmm30
+        vpaddd zmm3, zmm3, zmm24
+        vpaddd zmm0, zmm0, zmm5
+        vpaddd zmm1, zmm1, zmm6
+        vpaddd zmm2, zmm2, zmm7
+        vpaddd zmm3, zmm3, zmm4
+        vpxord zmm15, zmm15, zmm0
+        vpxord zmm12, zmm12, zmm1
+        vpxord zmm13, zmm13, zmm2
+        vpxord zmm14, zmm14, zmm3
+        vprord zmm15, zmm15, 8
+        vprord zmm12, zmm12, 8
+        vprord zmm13, zmm13, 8
+        vprord zmm14, zmm14, 8
+        vpaddd zmm10, zmm10, zmm15
+        vpaddd zmm11, zmm11, zmm12
+        vpaddd zmm8, zmm8, zmm13
+        vpaddd zmm9, zmm9, zmm14
+        vpxord zmm5, zmm5, zmm10
+        vpxord zmm6, zmm6, zmm11
+        vpxord zmm7, zmm7, zmm8
+        vpxord zmm4, zmm4, zmm9
+        vprord zmm5, zmm5, 7
+        vprord zmm6, zmm6, 7
+        vprord zmm7, zmm7, 7
+        vprord zmm4, zmm4, 7
+        vpaddd zmm0, zmm0, zmm19
+        vpaddd zmm1, zmm1, zmm26
+        vpaddd zmm2, zmm2, zmm29
+        vpaddd zmm3, zmm3, zmm23
+        vpaddd zmm0, zmm0, zmm4
+        vpaddd zmm1, zmm1, zmm5
+        vpaddd zmm2, zmm2, zmm6
+        vpaddd zmm3, zmm3, zmm7
+        vpxord zmm12, zmm12, zmm0
+        vpxord zmm13, zmm13, zmm1
+        vpxord zmm14, zmm14, zmm2
+        vpxord zmm15, zmm15, zmm3
+        vprord zmm12, zmm12, 16
+        vprord zmm13, zmm13, 16
+        vprord zmm14, zmm14, 16
+        vprord zmm15, zmm15, 16
+        vpaddd zmm8, zmm8, zmm12
+        vpaddd zmm9, zmm9, zmm13
+        vpaddd zmm10, zmm10, zmm14
+        vpaddd zmm11, zmm11, zmm15
+        vpxord zmm4, zmm4, zmm8
+        vpxord zmm5, zmm5, zmm9
+        vpxord zmm6, zmm6, zmm10
+        vpxord zmm7, zmm7, zmm11
+        vprord zmm4, zmm4, 12
+        vprord zmm5, zmm5, 12
+        vprord zmm6, zmm6, 12
+        vprord zmm7, zmm7, 12
+        vpaddd zmm0, zmm0, zmm20
+        vpaddd zmm1, zmm1, zmm28
+        vpaddd zmm2, zmm2, zmm18
+        vpaddd zmm3, zmm3, zmm30
+        vpaddd zmm0, zmm0, zmm4
+        vpaddd zmm1, zmm1, zmm5
+        vpaddd zmm2, zmm2, zmm6
+        vpaddd zmm3, zmm3, zmm7
+        vpxord zmm12, zmm12, zmm0
+        vpxord zmm13, zmm13, zmm1
+        vpxord zmm14, zmm14, zmm2
+        vpxord zmm15, zmm15, zmm3
+        vprord zmm12, zmm12, 8
+        vprord zmm13, zmm13, 8
+        vprord zmm14, zmm14, 8
+        vprord zmm15, zmm15, 8
+        vpaddd zmm8, zmm8, zmm12
+        vpaddd zmm9, zmm9, zmm13
+        vpaddd zmm10, zmm10, zmm14
+        vpaddd zmm11, zmm11, zmm15
+        vpxord zmm4, zmm4, zmm8
+        vpxord zmm5, zmm5, zmm9
+        vpxord zmm6, zmm6, zmm10
+        vpxord zmm7, zmm7, zmm11
+        vprord zmm4, zmm4, 7
+        vprord zmm5, zmm5, 7
+        vprord zmm6, zmm6, 7
+        vprord zmm7, zmm7, 7
+        vpaddd zmm0, zmm0, zmm22
+        vpaddd zmm1, zmm1, zmm25
+        vpaddd zmm2, zmm2, zmm27
+        vpaddd zmm3, zmm3, zmm24
+        vpaddd zmm0, zmm0, zmm5
+        vpaddd zmm1, zmm1, zmm6
+        vpaddd zmm2, zmm2, zmm7
+        vpaddd zmm3, zmm3, zmm4
+        vpxord zmm15, zmm15, zmm0
+        vpxord zmm12, zmm12, zmm1
+        vpxord zmm13, zmm13, zmm2
+        vpxord zmm14, zmm14, zmm3
+        vprord zmm15, zmm15, 16
+        vprord zmm12, zmm12, 16
+        vprord zmm13, zmm13, 16
+        vprord zmm14, zmm14, 16
+        vpaddd zmm10, zmm10, zmm15
+        vpaddd zmm11, zmm11, zmm12
+        vpaddd zmm8, zmm8, zmm13
+        vpaddd zmm9, zmm9, zmm14
+        vpxord zmm5, zmm5, zmm10
+        vpxord zmm6, zmm6, zmm11
+        vpxord zmm7, zmm7, zmm8
+        vpxord zmm4, zmm4, zmm9
+        vprord zmm5, zmm5, 12
+        vprord zmm6, zmm6, 12
+        vprord zmm7, zmm7, 12
+        vprord zmm4, zmm4, 12
+        vpaddd zmm0, zmm0, zmm21
+        vpaddd zmm1, zmm1, zmm16
+        vpaddd zmm2, zmm2, zmm31
+        vpaddd zmm3, zmm3, zmm17
+        vpaddd zmm0, zmm0, zmm5
+        vpaddd zmm1, zmm1, zmm6
+        vpaddd zmm2, zmm2, zmm7
+        vpaddd zmm3, zmm3, zmm4
+        vpxord zmm15, zmm15, zmm0
+        vpxord zmm12, zmm12, zmm1
+        vpxord zmm13, zmm13, zmm2
+        vpxord zmm14, zmm14, zmm3
+        vprord zmm15, zmm15, 8
+        vprord zmm12, zmm12, 8
+        vprord zmm13, zmm13, 8
+        vprord zmm14, zmm14, 8
+        vpaddd zmm10, zmm10, zmm15
+        vpaddd zmm11, zmm11, zmm12
+        vpaddd zmm8, zmm8, zmm13
+        vpaddd zmm9, zmm9, zmm14
+        vpxord zmm5, zmm5, zmm10
+        vpxord zmm6, zmm6, zmm11
+        vpxord zmm7, zmm7, zmm8
+        vpxord zmm4, zmm4, zmm9
+        vprord zmm5, zmm5, 7
+        vprord zmm6, zmm6, 7
+        vprord zmm7, zmm7, 7
+        vprord zmm4, zmm4, 7
+        vpaddd zmm0, zmm0, zmm26
+        vpaddd zmm1, zmm1, zmm28
+        vpaddd zmm2, zmm2, zmm30
+        vpaddd zmm3, zmm3, zmm29
+        vpaddd zmm0, zmm0, zmm4
+        vpaddd zmm1, zmm1, zmm5
+        vpaddd zmm2, zmm2, zmm6
+        vpaddd zmm3, zmm3, zmm7
+        vpxord zmm12, zmm12, zmm0
+        vpxord zmm13, zmm13, zmm1
+        vpxord zmm14, zmm14, zmm2
+        vpxord zmm15, zmm15, zmm3
+        vprord zmm12, zmm12, 16
+        vprord zmm13, zmm13, 16
+        vprord zmm14, zmm14, 16
+        vprord zmm15, zmm15, 16
+        vpaddd zmm8, zmm8, zmm12
+        vpaddd zmm9, zmm9, zmm13
+        vpaddd zmm10, zmm10, zmm14
+        vpaddd zmm11, zmm11, zmm15
+        vpxord zmm4, zmm4, zmm8
+        vpxord zmm5, zmm5, zmm9
+        vpxord zmm6, zmm6, zmm10
+        vpxord zmm7, zmm7, zmm11
+        vprord zmm4, zmm4, 12
+        vprord zmm5, zmm5, 12
+        vprord zmm6, zmm6, 12
+        vprord zmm7, zmm7, 12
+        vpaddd zmm0, zmm0, zmm23
+        vpaddd zmm1, zmm1, zmm25
+        vpaddd zmm2, zmm2, zmm19
+        vpaddd zmm3, zmm3, zmm31
+        vpaddd zmm0, zmm0, zmm4
+        vpaddd zmm1, zmm1, zmm5
+        vpaddd zmm2, zmm2, zmm6
+        vpaddd zmm3, zmm3, zmm7
+        vpxord zmm12, zmm12, zmm0
+        vpxord zmm13, zmm13, zmm1
+        vpxord zmm14, zmm14, zmm2
+        vpxord zmm15, zmm15, zmm3
+        vprord zmm12, zmm12, 8
+        vprord zmm13, zmm13, 8
+        vprord zmm14, zmm14, 8
+        vprord zmm15, zmm15, 8
+        vpaddd zmm8, zmm8, zmm12
+        vpaddd zmm9, zmm9, zmm13
+        vpaddd zmm10, zmm10, zmm14
+        vpaddd zmm11, zmm11, zmm15
+        vpxord zmm4, zmm4, zmm8
+        vpxord zmm5, zmm5, zmm9
+        vpxord zmm6, zmm6, zmm10
+        vpxord zmm7, zmm7, zmm11
+        vprord zmm4, zmm4, 7
+        vprord zmm5, zmm5, 7
+        vprord zmm6, zmm6, 7
+        vprord zmm7, zmm7, 7
+        vpaddd zmm0, zmm0, zmm20
+        vpaddd zmm1, zmm1, zmm27
+        vpaddd zmm2, zmm2, zmm21
+        vpaddd zmm3, zmm3, zmm17
+        vpaddd zmm0, zmm0, zmm5
+        vpaddd zmm1, zmm1, zmm6
+        vpaddd zmm2, zmm2, zmm7
+        vpaddd zmm3, zmm3, zmm4
+        vpxord zmm15, zmm15, zmm0
+        vpxord zmm12, zmm12, zmm1
+        vpxord zmm13, zmm13, zmm2
+        vpxord zmm14, zmm14, zmm3
+        vprord zmm15, zmm15, 16
+        vprord zmm12, zmm12, 16
+        vprord zmm13, zmm13, 16
+        vprord zmm14, zmm14, 16
+        vpaddd zmm10, zmm10, zmm15
+        vpaddd zmm11, zmm11, zmm12
+        vpaddd zmm8, zmm8, zmm13
+        vpaddd zmm9, zmm9, zmm14
+        vpxord zmm5, zmm5, zmm10
+        vpxord zmm6, zmm6, zmm11
+        vpxord zmm7, zmm7, zmm8
+        vpxord zmm4, zmm4, zmm9
+        vprord zmm5, zmm5, 12
+        vprord zmm6, zmm6, 12
+        vprord zmm7, zmm7, 12
+        vprord zmm4, zmm4, 12
+        vpaddd zmm0, zmm0, zmm16
+        vpaddd zmm1, zmm1, zmm18
+        vpaddd zmm2, zmm2, zmm24
+        vpaddd zmm3, zmm3, zmm22
+        vpaddd zmm0, zmm0, zmm5
+        vpaddd zmm1, zmm1, zmm6
+        vpaddd zmm2, zmm2, zmm7
+        vpaddd zmm3, zmm3, zmm4
+        vpxord zmm15, zmm15, zmm0
+        vpxord zmm12, zmm12, zmm1
+        vpxord zmm13, zmm13, zmm2
+        vpxord zmm14, zmm14, zmm3
+        vprord zmm15, zmm15, 8
+        vprord zmm12, zmm12, 8
+        vprord zmm13, zmm13, 8
+        vprord zmm14, zmm14, 8
+        vpaddd zmm10, zmm10, zmm15
+        vpaddd zmm11, zmm11, zmm12
+        vpaddd zmm8, zmm8, zmm13
+        vpaddd zmm9, zmm9, zmm14
+        vpxord zmm5, zmm5, zmm10
+        vpxord zmm6, zmm6, zmm11
+        vpxord zmm7, zmm7, zmm8
+        vpxord zmm4, zmm4, zmm9
+        vprord zmm5, zmm5, 7
+        vprord zmm6, zmm6, 7
+        vprord zmm7, zmm7, 7
+        vprord zmm4, zmm4, 7
+        vpaddd zmm0, zmm0, zmm28
+        vpaddd zmm1, zmm1, zmm25
+        vpaddd zmm2, zmm2, zmm31
+        vpaddd zmm3, zmm3, zmm30
+        vpaddd zmm0, zmm0, zmm4
+        vpaddd zmm1, zmm1, zmm5
+        vpaddd zmm2, zmm2, zmm6
+        vpaddd zmm3, zmm3, zmm7
+        vpxord zmm12, zmm12, zmm0
+        vpxord zmm13, zmm13, zmm1
+        vpxord zmm14, zmm14, zmm2
+        vpxord zmm15, zmm15, zmm3
+        vprord zmm12, zmm12, 16
+        vprord zmm13, zmm13, 16
+        vprord zmm14, zmm14, 16
+        vprord zmm15, zmm15, 16
+        vpaddd zmm8, zmm8, zmm12
+        vpaddd zmm9, zmm9, zmm13
+        vpaddd zmm10, zmm10, zmm14
+        vpaddd zmm11, zmm11, zmm15
+        vpxord zmm4, zmm4, zmm8
+        vpxord zmm5, zmm5, zmm9
+        vpxord zmm6, zmm6, zmm10
+        vpxord zmm7, zmm7, zmm11
+        vprord zmm4, zmm4, 12
+        vprord zmm5, zmm5, 12
+        vprord zmm6, zmm6, 12
+        vprord zmm7, zmm7, 12
+        vpaddd zmm0, zmm0, zmm29
+        vpaddd zmm1, zmm1, zmm27
+        vpaddd zmm2, zmm2, zmm26
+        vpaddd zmm3, zmm3, zmm24
+        vpaddd zmm0, zmm0, zmm4
+        vpaddd zmm1, zmm1, zmm5
+        vpaddd zmm2, zmm2, zmm6
+        vpaddd zmm3, zmm3, zmm7
+        vpxord zmm12, zmm12, zmm0
+        vpxord zmm13, zmm13, zmm1
+        vpxord zmm14, zmm14, zmm2
+        vpxord zmm15, zmm15, zmm3
+        vprord zmm12, zmm12, 8
+        vprord zmm13, zmm13, 8
+        vprord zmm14, zmm14, 8
+        vprord zmm15, zmm15, 8
+        vpaddd zmm8, zmm8, zmm12
+        vpaddd zmm9, zmm9, zmm13
+        vpaddd zmm10, zmm10, zmm14
+        vpaddd zmm11, zmm11, zmm15
+        vpxord zmm4, zmm4, zmm8
+        vpxord zmm5, zmm5, zmm9
+        vpxord zmm6, zmm6, zmm10
+        vpxord zmm7, zmm7, zmm11
+        vprord zmm4, zmm4, 7
+        vprord zmm5, zmm5, 7
+        vprord zmm6, zmm6, 7
+        vprord zmm7, zmm7, 7
+        vpaddd zmm0, zmm0, zmm23
+        vpaddd zmm1, zmm1, zmm21
+        vpaddd zmm2, zmm2, zmm16
+        vpaddd zmm3, zmm3, zmm22
+        vpaddd zmm0, zmm0, zmm5
+        vpaddd zmm1, zmm1, zmm6
+        vpaddd zmm2, zmm2, zmm7
+        vpaddd zmm3, zmm3, zmm4
+        vpxord zmm15, zmm15, zmm0
+        vpxord zmm12, zmm12, zmm1
+        vpxord zmm13, zmm13, zmm2
+        vpxord zmm14, zmm14, zmm3
+        vprord zmm15, zmm15, 16
+        vprord zmm12, zmm12, 16
+        vprord zmm13, zmm13, 16
+        vprord zmm14, zmm14, 16
+        vpaddd zmm10, zmm10, zmm15
+        vpaddd zmm11, zmm11, zmm12
+        vpaddd zmm8, zmm8, zmm13
+        vpaddd zmm9, zmm9, zmm14
+        vpxord zmm5, zmm5, zmm10
+        vpxord zmm6, zmm6, zmm11
+        vpxord zmm7, zmm7, zmm8
+        vpxord zmm4, zmm4, zmm9
+        vprord zmm5, zmm5, 12
+        vprord zmm6, zmm6, 12
+        vprord zmm7, zmm7, 12
+        vprord zmm4, zmm4, 12
+        vpaddd zmm0, zmm0, zmm18
+        vpaddd zmm1, zmm1, zmm19
+        vpaddd zmm2, zmm2, zmm17
+        vpaddd zmm3, zmm3, zmm20
+        vpaddd zmm0, zmm0, zmm5
+        vpaddd zmm1, zmm1, zmm6
+        vpaddd zmm2, zmm2, zmm7
+        vpaddd zmm3, zmm3, zmm4
+        vpxord zmm15, zmm15, zmm0
+        vpxord zmm12, zmm12, zmm1
+        vpxord zmm13, zmm13, zmm2
+        vpxord zmm14, zmm14, zmm3
+        vprord zmm15, zmm15, 8
+        vprord zmm12, zmm12, 8
+        vprord zmm13, zmm13, 8
+        vprord zmm14, zmm14, 8
+        vpaddd zmm10, zmm10, zmm15
+        vpaddd zmm11, zmm11, zmm12
+        vpaddd zmm8, zmm8, zmm13
+        vpaddd zmm9, zmm9, zmm14
+        vpxord zmm5, zmm5, zmm10
+        vpxord zmm6, zmm6, zmm11
+        vpxord zmm7, zmm7, zmm8
+        vpxord zmm4, zmm4, zmm9
+        vprord zmm5, zmm5, 7
+        vprord zmm6, zmm6, 7
+        vprord zmm7, zmm7, 7
+        vprord zmm4, zmm4, 7
+        vpaddd zmm0, zmm0, zmm25
+        vpaddd zmm1, zmm1, zmm27
+        vpaddd zmm2, zmm2, zmm24
+        vpaddd zmm3, zmm3, zmm31
+        vpaddd zmm0, zmm0, zmm4
+        vpaddd zmm1, zmm1, zmm5
+        vpaddd zmm2, zmm2, zmm6
+        vpaddd zmm3, zmm3, zmm7
+        vpxord zmm12, zmm12, zmm0
+        vpxord zmm13, zmm13, zmm1
+        vpxord zmm14, zmm14, zmm2
+        vpxord zmm15, zmm15, zmm3
+        vprord zmm12, zmm12, 16
+        vprord zmm13, zmm13, 16
+        vprord zmm14, zmm14, 16
+        vprord zmm15, zmm15, 16
+        vpaddd zmm8, zmm8, zmm12
+        vpaddd zmm9, zmm9, zmm13
+        vpaddd zmm10, zmm10, zmm14
+        vpaddd zmm11, zmm11, zmm15
+        vpxord zmm4, zmm4, zmm8
+        vpxord zmm5, zmm5, zmm9
+        vpxord zmm6, zmm6, zmm10
+        vpxord zmm7, zmm7, zmm11
+        vprord zmm4, zmm4, 12
+        vprord zmm5, zmm5, 12
+        vprord zmm6, zmm6, 12
+        vprord zmm7, zmm7, 12
+        vpaddd zmm0, zmm0, zmm30
+        vpaddd zmm1, zmm1, zmm21
+        vpaddd zmm2, zmm2, zmm28
+        vpaddd zmm3, zmm3, zmm17
+        vpaddd zmm0, zmm0, zmm4
+        vpaddd zmm1, zmm1, zmm5
+        vpaddd zmm2, zmm2, zmm6
+        vpaddd zmm3, zmm3, zmm7
+        vpxord zmm12, zmm12, zmm0
+        vpxord zmm13, zmm13, zmm1
+        vpxord zmm14, zmm14, zmm2
+        vpxord zmm15, zmm15, zmm3
+        vprord zmm12, zmm12, 8
+        vprord zmm13, zmm13, 8
+        vprord zmm14, zmm14, 8
+        vprord zmm15, zmm15, 8
+        vpaddd zmm8, zmm8, zmm12
+        vpaddd zmm9, zmm9, zmm13
+        vpaddd zmm10, zmm10, zmm14
+        vpaddd zmm11, zmm11, zmm15
+        vpxord zmm4, zmm4, zmm8
+        vpxord zmm5, zmm5, zmm9
+        vpxord zmm6, zmm6, zmm10
+        vpxord zmm7, zmm7, zmm11
+        vprord zmm4, zmm4, 7
+        vprord zmm5, zmm5, 7
+        vprord zmm6, zmm6, 7
+        vprord zmm7, zmm7, 7
+        vpaddd zmm0, zmm0, zmm29
+        vpaddd zmm1, zmm1, zmm16
+        vpaddd zmm2, zmm2, zmm18
+        vpaddd zmm3, zmm3, zmm20
+        vpaddd zmm0, zmm0, zmm5
+        vpaddd zmm1, zmm1, zmm6
+        vpaddd zmm2, zmm2, zmm7
+        vpaddd zmm3, zmm3, zmm4
+        vpxord zmm15, zmm15, zmm0
+        vpxord zmm12, zmm12, zmm1
+        vpxord zmm13, zmm13, zmm2
+        vpxord zmm14, zmm14, zmm3
+        vprord zmm15, zmm15, 16
+        vprord zmm12, zmm12, 16
+        vprord zmm13, zmm13, 16
+        vprord zmm14, zmm14, 16
+        vpaddd zmm10, zmm10, zmm15
+        vpaddd zmm11, zmm11, zmm12
+        vpaddd zmm8, zmm8, zmm13
+        vpaddd zmm9, zmm9, zmm14
+        vpxord zmm5, zmm5, zmm10
+        vpxord zmm6, zmm6, zmm11
+        vpxord zmm7, zmm7, zmm8
+        vpxord zmm4, zmm4, zmm9
+        vprord zmm5, zmm5, 12
+        vprord zmm6, zmm6, 12
+        vprord zmm7, zmm7, 12
+        vprord zmm4, zmm4, 12
+        vpaddd zmm0, zmm0, zmm19
+        vpaddd zmm1, zmm1, zmm26
+        vpaddd zmm2, zmm2, zmm22
+        vpaddd zmm3, zmm3, zmm23
+        vpaddd zmm0, zmm0, zmm5
+        vpaddd zmm1, zmm1, zmm6
+        vpaddd zmm2, zmm2, zmm7
+        vpaddd zmm3, zmm3, zmm4
+        vpxord zmm15, zmm15, zmm0
+        vpxord zmm12, zmm12, zmm1
+        vpxord zmm13, zmm13, zmm2
+        vpxord zmm14, zmm14, zmm3
+        vprord zmm15, zmm15, 8
+        vprord zmm12, zmm12, 8
+        vprord zmm13, zmm13, 8
+        vprord zmm14, zmm14, 8
+        vpaddd zmm10, zmm10, zmm15
+        vpaddd zmm11, zmm11, zmm12
+        vpaddd zmm8, zmm8, zmm13
+        vpaddd zmm9, zmm9, zmm14
+        vpxord zmm5, zmm5, zmm10
+        vpxord zmm6, zmm6, zmm11
+        vpxord zmm7, zmm7, zmm8
+        vpxord zmm4, zmm4, zmm9
+        vprord zmm5, zmm5, 7
+        vprord zmm6, zmm6, 7
+        vprord zmm7, zmm7, 7
+        vprord zmm4, zmm4, 7
+        vpaddd zmm0, zmm0, zmm27
+        vpaddd zmm1, zmm1, zmm21
+        vpaddd zmm2, zmm2, zmm17
+        vpaddd zmm3, zmm3, zmm24
+        vpaddd zmm0, zmm0, zmm4
+        vpaddd zmm1, zmm1, zmm5
+        vpaddd zmm2, zmm2, zmm6
+        vpaddd zmm3, zmm3, zmm7
+        vpxord zmm12, zmm12, zmm0
+        vpxord zmm13, zmm13, zmm1
+        vpxord zmm14, zmm14, zmm2
+        vpxord zmm15, zmm15, zmm3
+        vprord zmm12, zmm12, 16
+        vprord zmm13, zmm13, 16
+        vprord zmm14, zmm14, 16
+        vprord zmm15, zmm15, 16
+        vpaddd zmm8, zmm8, zmm12
+        vpaddd zmm9, zmm9, zmm13
+        vpaddd zmm10, zmm10, zmm14
+        vpaddd zmm11, zmm11, zmm15
+        vpxord zmm4, zmm4, zmm8
+        vpxord zmm5, zmm5, zmm9
+        vpxord zmm6, zmm6, zmm10
+        vpxord zmm7, zmm7, zmm11
+        vprord zmm4, zmm4, 12
+        vprord zmm5, zmm5, 12
+        vprord zmm6, zmm6, 12
+        vprord zmm7, zmm7, 12
+        vpaddd zmm0, zmm0, zmm31
+        vpaddd zmm1, zmm1, zmm16
+        vpaddd zmm2, zmm2, zmm25
+        vpaddd zmm3, zmm3, zmm22
+        vpaddd zmm0, zmm0, zmm4
+        vpaddd zmm1, zmm1, zmm5
+        vpaddd zmm2, zmm2, zmm6
+        vpaddd zmm3, zmm3, zmm7
+        vpxord zmm12, zmm12, zmm0
+        vpxord zmm13, zmm13, zmm1
+        vpxord zmm14, zmm14, zmm2
+        vpxord zmm15, zmm15, zmm3
+        vprord zmm12, zmm12, 8
+        vprord zmm13, zmm13, 8
+        vprord zmm14, zmm14, 8
+        vprord zmm15, zmm15, 8
+        vpaddd zmm8, zmm8, zmm12
+        vpaddd zmm9, zmm9, zmm13
+        vpaddd zmm10, zmm10, zmm14
+        vpaddd zmm11, zmm11, zmm15
+        vpxord zmm4, zmm4, zmm8
+        vpxord zmm5, zmm5, zmm9
+        vpxord zmm6, zmm6, zmm10
+        vpxord zmm7, zmm7, zmm11
+        vprord zmm4, zmm4, 7
+        vprord zmm5, zmm5, 7
+        vprord zmm6, zmm6, 7
+        vprord zmm7, zmm7, 7
+        vpaddd zmm0, zmm0, zmm30
+        vpaddd zmm1, zmm1, zmm18
+        vpaddd zmm2, zmm2, zmm19
+        vpaddd zmm3, zmm3, zmm23
+        vpaddd zmm0, zmm0, zmm5
+        vpaddd zmm1, zmm1, zmm6
+        vpaddd zmm2, zmm2, zmm7
+        vpaddd zmm3, zmm3, zmm4
+        vpxord zmm15, zmm15, zmm0
+        vpxord zmm12, zmm12, zmm1
+        vpxord zmm13, zmm13, zmm2
+        vpxord zmm14, zmm14, zmm3
+        vprord zmm15, zmm15, 16
+        vprord zmm12, zmm12, 16
+        vprord zmm13, zmm13, 16
+        vprord zmm14, zmm14, 16
+        vpaddd zmm10, zmm10, zmm15
+        vpaddd zmm11, zmm11, zmm12
+        vpaddd zmm8, zmm8, zmm13
+        vpaddd zmm9, zmm9, zmm14
+        vpxord zmm5, zmm5, zmm10
+        vpxord zmm6, zmm6, zmm11
+        vpxord zmm7, zmm7, zmm8
+        vpxord zmm4, zmm4, zmm9
+        vprord zmm5, zmm5, 12
+        vprord zmm6, zmm6, 12
+        vprord zmm7, zmm7, 12
+        vprord zmm4, zmm4, 12
+        vpaddd zmm0, zmm0, zmm26
+        vpaddd zmm1, zmm1, zmm28
+        vpaddd zmm2, zmm2, zmm20
+        vpaddd zmm3, zmm3, zmm29
+        vpaddd zmm0, zmm0, zmm5
+        vpaddd zmm1, zmm1, zmm6
+        vpaddd zmm2, zmm2, zmm7
+        vpaddd zmm3, zmm3, zmm4
+        vpxord zmm15, zmm15, zmm0
+        vpxord zmm12, zmm12, zmm1
+        vpxord zmm13, zmm13, zmm2
+        vpxord zmm14, zmm14, zmm3
+        vprord zmm15, zmm15, 8
+        vprord zmm12, zmm12, 8
+        vprord zmm13, zmm13, 8
+        vprord zmm14, zmm14, 8
+        vpaddd zmm10, zmm10, zmm15
+        vpaddd zmm11, zmm11, zmm12
+        vpaddd zmm8, zmm8, zmm13
+        vpaddd zmm9, zmm9, zmm14
+        vpxord zmm5, zmm5, zmm10
+        vpxord zmm6, zmm6, zmm11
+        vpxord zmm7, zmm7, zmm8
+        vpxord zmm4, zmm4, zmm9
+        vprord zmm5, zmm5, 7
+        vprord zmm6, zmm6, 7
+        vprord zmm7, zmm7, 7
+        vprord zmm4, zmm4, 7
+        vpxord zmm0, zmm0, zmm8
+        vpxord zmm1, zmm1, zmm9
+        vpxord zmm2, zmm2, zmm10
+        vpxord zmm3, zmm3, zmm11
+        vpxord zmm4, zmm4, zmm12
+        vpxord zmm5, zmm5, zmm13
+        vpxord zmm6, zmm6, zmm14
+        vpxord zmm7, zmm7, zmm15
+        ret
+.global blake3_avx512_xof_stream_16
+blake3_avx512_xof_stream_16:
+        vmovdqa32 zmm12, zmmword ptr [rip + EVEN_INDEXES]
+        vmovdqa32 zmm13, zmmword ptr [rip + ODD_INDEXES]
+        vpbroadcastd zmm0, dword ptr [rdi+0]
+        vpbroadcastd zmm1, dword ptr [rdi+4]
+        vpbroadcastd zmm2, dword ptr [rdi+8]
+        vpbroadcastd zmm3, dword ptr [rdi+12]
+        vpbroadcastd zmm4, dword ptr [rdi+16]
+        vpbroadcastd zmm5, dword ptr [rdi+20]
+        vpbroadcastd zmm6, dword ptr [rdi+24]
+        vpbroadcastd zmm7, dword ptr [rdi+28]
+        vpbroadcastd zmm16, dword ptr [rsi+0]
+        vpbroadcastd zmm17, dword ptr [rsi+4]
+        vpbroadcastd zmm18, dword ptr [rsi+8]
+        vpbroadcastd zmm19, dword ptr [rsi+12]
+        vpbroadcastd zmm20, dword ptr [rsi+16]
+        vpbroadcastd zmm21, dword ptr [rsi+20]
+        vpbroadcastd zmm22, dword ptr [rsi+24]
+        vpbroadcastd zmm23, dword ptr [rsi+28]
+        vpbroadcastd zmm24, dword ptr [rsi+32]
+        vpbroadcastd zmm25, dword ptr [rsi+36]
+        vpbroadcastd zmm26, dword ptr [rsi+40]
+        vpbroadcastd zmm27, dword ptr [rsi+44]
+        vpbroadcastd zmm28, dword ptr [rsi+48]
+        vpbroadcastd zmm29, dword ptr [rsi+52]
+        vpbroadcastd zmm30, dword ptr [rsi+56]
+        vpbroadcastd zmm31, dword ptr [rsi+60]
+        vmovdqa64 zmm8, zmmword ptr [INCREMENT_3D+rip]
+        vpbroadcastq zmm9, rdx
+        vpaddq zmm9, zmm9, zmm8
+        add rdx, 8
+        vpbroadcastq zmm10, rdx
+        vpaddq zmm10, zmm10, zmm8
+        vpermi2d zmm12, zmm9, zmm10
+        vpermi2d zmm13, zmm9, zmm10
+        vpbroadcastd zmm14, ecx
+        vpbroadcastd zmm15, r8d
+        vpbroadcastd zmm8, dword ptr [BLAKE3_IV+rip+0]
+        vpbroadcastd zmm9, dword ptr [BLAKE3_IV+rip+4]
+        vpbroadcastd zmm10, dword ptr [BLAKE3_IV+rip+8]
+        vpbroadcastd zmm11, dword ptr [BLAKE3_IV+rip+12]
+        call blake3_avx512_kernel_3d_16
+        vpbroadcastd zmm16, dword ptr [rdi + 0 * 4]
+        vpxord zmm8, zmm8, zmm16
+        vpbroadcastd zmm17, dword ptr [rdi + 1 * 4]
+        vpxord zmm9, zmm9, zmm17
+        vpbroadcastd zmm18, dword ptr [rdi + 2 * 4]
+        vpxord zmm10, zmm10, zmm18
+        vpbroadcastd zmm19, dword ptr [rdi + 3 * 4]
+        vpxord zmm11, zmm11, zmm19
+        vpbroadcastd zmm20, dword ptr [rdi + 4 * 4]
+        vpxord zmm12, zmm12, zmm20
+        vpbroadcastd zmm21, dword ptr [rdi + 5 * 4]
+        vpxord zmm13, zmm13, zmm21
+        vpbroadcastd zmm22, dword ptr [rdi + 6 * 4]
+        vpxord zmm14, zmm14, zmm22
+        vpbroadcastd zmm23, dword ptr [rdi + 7 * 4]
+        vpxord zmm15, zmm15, zmm23
+        vpunpckldq zmm16, zmm0, zmm1
+        vpunpckhdq zmm17, zmm0, zmm1
+        vpunpckldq zmm18, zmm2, zmm3
+        vpunpckhdq zmm19, zmm2, zmm3
+        vpunpcklqdq zmm0, zmm16, zmm18
+        vmovdqu32 xmmword ptr [r9 + 0 * 16], xmm0
+        vextracti32x4 xmmword ptr [r9 + 16 * 16], zmm0, 1
+        vextracti32x4 xmmword ptr [r9 + 32 * 16], zmm0, 2
+        vextracti32x4 xmmword ptr [r9 + 48 * 16], zmm0, 3
+        vpunpckhqdq zmm1, zmm16, zmm18
+        vmovdqu32 xmmword ptr [r9 + 4 * 16], xmm1
+        vextracti32x4 xmmword ptr [r9 + 20 * 16], zmm1, 1
+        vextracti32x4 xmmword ptr [r9 + 36 * 16], zmm1, 2
+        vextracti32x4 xmmword ptr [r9 + 52 * 16], zmm1, 3
+        vpunpcklqdq zmm2, zmm17, zmm19
+        vmovdqu32 xmmword ptr [r9 + 8 * 16], xmm2
+        vextracti32x4 xmmword ptr [r9 + 24 * 16], zmm2, 1
+        vextracti32x4 xmmword ptr [r9 + 40 * 16], zmm2, 2
+        vextracti32x4 xmmword ptr [r9 + 56 * 16], zmm2, 3
+        vpunpckhqdq zmm3, zmm17, zmm19
+        vmovdqu32 xmmword ptr [r9 + 12 * 16], xmm3
+        vextracti32x4 xmmword ptr [r9 + 28 * 16], zmm3, 1
+        vextracti32x4 xmmword ptr [r9 + 44 * 16], zmm3, 2
+        vextracti32x4 xmmword ptr [r9 + 60 * 16], zmm3, 3
+        vpunpckldq zmm20, zmm4, zmm5
+        vpunpckhdq zmm21, zmm4, zmm5
+        vpunpckldq zmm22, zmm6, zmm7
+        vpunpckhdq zmm23, zmm6, zmm7
+        vpunpcklqdq zmm4, zmm20, zmm22
+        vmovdqu32 xmmword ptr [r9 + 1 * 16], xmm4
+        vextracti32x4 xmmword ptr [r9 + 17 * 16], zmm4, 1
+        vextracti32x4 xmmword ptr [r9 + 33 * 16], zmm4, 2
+        vextracti32x4 xmmword ptr [r9 + 49 * 16], zmm4, 3
+        vpunpckhqdq zmm5, zmm20, zmm22
+        vmovdqu32 xmmword ptr [r9 + 5 * 16], xmm5
+        vextracti32x4 xmmword ptr [r9 + 21 * 16], zmm5, 1
+        vextracti32x4 xmmword ptr [r9 + 37 * 16], zmm5, 2
+        vextracti32x4 xmmword ptr [r9 + 53 * 16], zmm5, 3
+        vpunpcklqdq zmm6, zmm21, zmm23
+        vmovdqu32 xmmword ptr [r9 + 9 * 16], xmm6
+        vextracti32x4 xmmword ptr [r9 + 25 * 16], zmm6, 1
+        vextracti32x4 xmmword ptr [r9 + 41 * 16], zmm6, 2
+        vextracti32x4 xmmword ptr [r9 + 57 * 16], zmm6, 3
+        vpunpckhqdq zmm7, zmm21, zmm23
+        vmovdqu32 xmmword ptr [r9 + 13 * 16], xmm7
+        vextracti32x4 xmmword ptr [r9 + 29 * 16], zmm7, 1
+        vextracti32x4 xmmword ptr [r9 + 45 * 16], zmm7, 2
+        vextracti32x4 xmmword ptr [r9 + 61 * 16], zmm7, 3
+        vpunpckldq zmm24, zmm8, zmm9
+        vpunpckhdq zmm25, zmm8, zmm9
+        vpunpckldq zmm26, zmm10, zmm11
+        vpunpckhdq zmm27, zmm10, zmm11
+        vpunpcklqdq zmm8, zmm24, zmm26
+        vmovdqu32 xmmword ptr [r9 + 2 * 16], xmm8
+        vextracti32x4 xmmword ptr [r9 + 18 * 16], zmm8, 1
+        vextracti32x4 xmmword ptr [r9 + 34 * 16], zmm8, 2
+        vextracti32x4 xmmword ptr [r9 + 50 * 16], zmm8, 3
+        vpunpckhqdq zmm9, zmm24, zmm26
+        vmovdqu32 xmmword ptr [r9 + 6 * 16], xmm9
+        vextracti32x4 xmmword ptr [r9 + 22 * 16], zmm9, 1
+        vextracti32x4 xmmword ptr [r9 + 38 * 16], zmm9, 2
+        vextracti32x4 xmmword ptr [r9 + 54 * 16], zmm9, 3
+        vpunpcklqdq zmm10, zmm25, zmm27
+        vmovdqu32 xmmword ptr [r9 + 10 * 16], xmm10
+        vextracti32x4 xmmword ptr [r9 + 26 * 16], zmm10, 1
+        vextracti32x4 xmmword ptr [r9 + 42 * 16], zmm10, 2
+        vextracti32x4 xmmword ptr [r9 + 58 * 16], zmm10, 3
+        vpunpckhqdq zmm11, zmm25, zmm27
+        vmovdqu32 xmmword ptr [r9 + 14 * 16], xmm11
+        vextracti32x4 xmmword ptr [r9 + 30 * 16], zmm11, 1
+        vextracti32x4 xmmword ptr [r9 + 46 * 16], zmm11, 2
+        vextracti32x4 xmmword ptr [r9 + 62 * 16], zmm11, 3
+        vpunpckldq zmm28, zmm12, zmm13
+        vpunpckhdq zmm29, zmm12, zmm13
+        vpunpckldq zmm30, zmm14, zmm15
+        vpunpckhdq zmm31, zmm14, zmm15
+        vpunpcklqdq zmm12, zmm28, zmm30
+        vmovdqu32 xmmword ptr [r9 + 3 * 16], xmm12
+        vextracti32x4 xmmword ptr [r9 + 19 * 16], zmm12, 1
+        vextracti32x4 xmmword ptr [r9 + 35 * 16], zmm12, 2
+        vextracti32x4 xmmword ptr [r9 + 51 * 16], zmm12, 3
+        vpunpckhqdq zmm13, zmm28, zmm30
+        vmovdqu32 xmmword ptr [r9 + 7 * 16], xmm13
+        vextracti32x4 xmmword ptr [r9 + 23 * 16], zmm13, 1
+        vextracti32x4 xmmword ptr [r9 + 39 * 16], zmm13, 2
+        vextracti32x4 xmmword ptr [r9 + 55 * 16], zmm13, 3
+        vpunpcklqdq zmm14, zmm29, zmm31
+        vmovdqu32 xmmword ptr [r9 + 11 * 16], xmm14
+        vextracti32x4 xmmword ptr [r9 + 27 * 16], zmm14, 1
+        vextracti32x4 xmmword ptr [r9 + 43 * 16], zmm14, 2
+        vextracti32x4 xmmword ptr [r9 + 59 * 16], zmm14, 3
+        vpunpckhqdq zmm15, zmm29, zmm31
+        vmovdqu32 xmmword ptr [r9 + 15 * 16], xmm15
+        vextracti32x4 xmmword ptr [r9 + 31 * 16], zmm15, 1
+        vextracti32x4 xmmword ptr [r9 + 47 * 16], zmm15, 2
+        vextracti32x4 xmmword ptr [r9 + 63 * 16], zmm15, 3
+        ret
+.global blake3_avx512_xof_xor_16
+blake3_avx512_xof_xor_16:
+        vmovdqa32 zmm12, zmmword ptr [rip + EVEN_INDEXES]
+        vmovdqa32 zmm13, zmmword ptr [rip + ODD_INDEXES]
+        vpbroadcastd zmm0, dword ptr [rdi+0]
+        vpbroadcastd zmm1, dword ptr [rdi+4]
+        vpbroadcastd zmm2, dword ptr [rdi+8]
+        vpbroadcastd zmm3, dword ptr [rdi+12]
+        vpbroadcastd zmm4, dword ptr [rdi+16]
+        vpbroadcastd zmm5, dword ptr [rdi+20]
+        vpbroadcastd zmm6, dword ptr [rdi+24]
+        vpbroadcastd zmm7, dword ptr [rdi+28]
+        vpbroadcastd zmm16, dword ptr [rsi+0]
+        vpbroadcastd zmm17, dword ptr [rsi+4]
+        vpbroadcastd zmm18, dword ptr [rsi+8]
+        vpbroadcastd zmm19, dword ptr [rsi+12]
+        vpbroadcastd zmm20, dword ptr [rsi+16]
+        vpbroadcastd zmm21, dword ptr [rsi+20]
+        vpbroadcastd zmm22, dword ptr [rsi+24]
+        vpbroadcastd zmm23, dword ptr [rsi+28]
+        vpbroadcastd zmm24, dword ptr [rsi+32]
+        vpbroadcastd zmm25, dword ptr [rsi+36]
+        vpbroadcastd zmm26, dword ptr [rsi+40]
+        vpbroadcastd zmm27, dword ptr [rsi+44]
+        vpbroadcastd zmm28, dword ptr [rsi+48]
+        vpbroadcastd zmm29, dword ptr [rsi+52]
+        vpbroadcastd zmm30, dword ptr [rsi+56]
+        vpbroadcastd zmm31, dword ptr [rsi+60]
+        vmovdqa64 zmm8, zmmword ptr [INCREMENT_3D+rip]
+        vpbroadcastq zmm9, rdx
+        vpaddq zmm9, zmm9, zmm8
+        add rdx, 8
+        vpbroadcastq zmm10, rdx
+        vpaddq zmm10, zmm10, zmm8
+        vpermi2d zmm12, zmm9, zmm10
+        vpermi2d zmm13, zmm9, zmm10
+        vpbroadcastd zmm14, ecx
+        vpbroadcastd zmm15, r8d
+        vpbroadcastd zmm8, dword ptr [BLAKE3_IV+rip+0]
+        vpbroadcastd zmm9, dword ptr [BLAKE3_IV+rip+4]
+        vpbroadcastd zmm10, dword ptr [BLAKE3_IV+rip+8]
+        vpbroadcastd zmm11, dword ptr [BLAKE3_IV+rip+12]
+        call blake3_avx512_kernel_3d_16
+        vpbroadcastd zmm16, dword ptr [rdi + 0 * 4]
+        vpxord zmm8, zmm8, zmm16
+        vpbroadcastd zmm17, dword ptr [rdi + 1 * 4]
+        vpxord zmm9, zmm9, zmm17
+        vpbroadcastd zmm18, dword ptr [rdi + 2 * 4]
+        vpxord zmm10, zmm10, zmm18
+        vpbroadcastd zmm19, dword ptr [rdi + 3 * 4]
+        vpxord zmm11, zmm11, zmm19
+        vpbroadcastd zmm20, dword ptr [rdi + 4 * 4]
+        vpxord zmm12, zmm12, zmm20
+        vpbroadcastd zmm21, dword ptr [rdi + 5 * 4]
+        vpxord zmm13, zmm13, zmm21
+        vpbroadcastd zmm22, dword ptr [rdi + 6 * 4]
+        vpxord zmm14, zmm14, zmm22
+        vpbroadcastd zmm23, dword ptr [rdi + 7 * 4]
+        vpxord zmm15, zmm15, zmm23
+        vpunpckldq zmm16, zmm0, zmm1
+        vpunpckhdq zmm17, zmm0, zmm1
+        vpunpckldq zmm18, zmm2, zmm3
+        vpunpckhdq zmm19, zmm2, zmm3
+        vpunpckldq zmm20, zmm4, zmm5
+        vpunpckhdq zmm21, zmm4, zmm5
+        vpunpckldq zmm22, zmm6, zmm7
+        vpunpckhdq zmm23, zmm6, zmm7
+        vpunpckldq zmm24, zmm8, zmm9
+        vpunpckhdq zmm25, zmm8, zmm9
+        vpunpckldq zmm26, zmm10, zmm11
+        vpunpckhdq zmm27, zmm10, zmm11
+        vpunpckldq zmm28, zmm12, zmm13
+        vpunpckhdq zmm29, zmm12, zmm13
+        vpunpckldq zmm30, zmm14, zmm15
+        vpunpckhdq zmm31, zmm14, zmm15
+        vpunpcklqdq zmm0, zmm16, zmm18
+        vpunpckhqdq zmm1, zmm16, zmm18
+        vpunpcklqdq zmm2, zmm17, zmm19
+        vpunpckhqdq zmm3, zmm17, zmm19
+        vpunpcklqdq zmm4, zmm20, zmm22
+        vpunpckhqdq zmm5, zmm20, zmm22
+        vpunpcklqdq zmm6, zmm21, zmm23
+        vpunpckhqdq zmm7, zmm21, zmm23
+        vpunpcklqdq zmm8, zmm24, zmm26
+        vpunpckhqdq zmm9, zmm24, zmm26
+        vpunpcklqdq zmm10, zmm25, zmm27
+        vpunpckhqdq zmm11, zmm25, zmm27
+        vpunpcklqdq zmm12, zmm28, zmm30
+        vpunpckhqdq zmm13, zmm28, zmm30
+        vpunpcklqdq zmm14, zmm29, zmm31
+        vpunpckhqdq zmm15, zmm29, zmm31
+        vshufi32x4 zmm16, zmm0, zmm4, 0x88
+        vshufi32x4 zmm17, zmm1, zmm5, 0x88
+        vshufi32x4 zmm18, zmm2, zmm6, 0x88
+        vshufi32x4 zmm19, zmm3, zmm7, 0x88
+        vshufi32x4 zmm20, zmm0, zmm4, 0xdd
+        vshufi32x4 zmm21, zmm1, zmm5, 0xdd
+        vshufi32x4 zmm22, zmm2, zmm6, 0xdd
+        vshufi32x4 zmm23, zmm3, zmm7, 0xdd
+        vshufi32x4 zmm24, zmm8, zmm12, 0x88
+        vshufi32x4 zmm25, zmm9, zmm13, 0x88
+        vshufi32x4 zmm26, zmm10, zmm14, 0x88
+        vshufi32x4 zmm27, zmm11, zmm15, 0x88
+        vshufi32x4 zmm28, zmm8, zmm12, 0xdd
+        vshufi32x4 zmm29, zmm9, zmm13, 0xdd
+        vshufi32x4 zmm30, zmm10, zmm14, 0xdd
+        vshufi32x4 zmm31, zmm11, zmm15, 0xdd
+        vshufi32x4 zmm0, zmm16, zmm24, 0x88
+        vshufi32x4 zmm1, zmm17, zmm25, 0x88
+        vshufi32x4 zmm2, zmm18, zmm26, 0x88
+        vshufi32x4 zmm3, zmm19, zmm27, 0x88
+        vshufi32x4 zmm4, zmm20, zmm28, 0x88
+        vshufi32x4 zmm5, zmm21, zmm29, 0x88
+        vshufi32x4 zmm6, zmm22, zmm30, 0x88
+        vshufi32x4 zmm7, zmm23, zmm31, 0x88
+        vshufi32x4 zmm8, zmm16, zmm24, 0xdd
+        vshufi32x4 zmm9, zmm17, zmm25, 0xdd
+        vshufi32x4 zmm10, zmm18, zmm26, 0xdd
+        vshufi32x4 zmm11, zmm19, zmm27, 0xdd
+        vshufi32x4 zmm12, zmm20, zmm28, 0xdd
+        vshufi32x4 zmm13, zmm21, zmm29, 0xdd
+        vshufi32x4 zmm14, zmm22, zmm30, 0xdd
+        vshufi32x4 zmm15, zmm23, zmm31, 0xdd
+        vmovdqu32 zmm16, zmmword ptr [r9 + 0 * 64]
+        vpxord zmm0, zmm0, zmm16
+        vmovdqu32 zmmword ptr [r9 + 0 * 64], zmm0
+        vmovdqu32 zmm17, zmmword ptr [r9 + 1 * 64]
+        vpxord zmm1, zmm1, zmm17
+        vmovdqu32 zmmword ptr [r9 + 1 * 64], zmm1
+        vmovdqu32 zmm18, zmmword ptr [r9 + 2 * 64]
+        vpxord zmm2, zmm2, zmm18
+        vmovdqu32 zmmword ptr [r9 + 2 * 64], zmm2
+        vmovdqu32 zmm19, zmmword ptr [r9 + 3 * 64]
+        vpxord zmm3, zmm3, zmm19
+        vmovdqu32 zmmword ptr [r9 + 3 * 64], zmm3
+        vmovdqu32 zmm20, zmmword ptr [r9 + 4 * 64]
+        vpxord zmm4, zmm4, zmm20
+        vmovdqu32 zmmword ptr [r9 + 4 * 64], zmm4
+        vmovdqu32 zmm21, zmmword ptr [r9 + 5 * 64]
+        vpxord zmm5, zmm5, zmm21
+        vmovdqu32 zmmword ptr [r9 + 5 * 64], zmm5
+        vmovdqu32 zmm22, zmmword ptr [r9 + 6 * 64]
+        vpxord zmm6, zmm6, zmm22
+        vmovdqu32 zmmword ptr [r9 + 6 * 64], zmm6
+        vmovdqu32 zmm23, zmmword ptr [r9 + 7 * 64]
+        vpxord zmm7, zmm7, zmm23
+        vmovdqu32 zmmword ptr [r9 + 7 * 64], zmm7
+        vmovdqu32 zmm24, zmmword ptr [r9 + 8 * 64]
+        vpxord zmm8, zmm8, zmm24
+        vmovdqu32 zmmword ptr [r9 + 8 * 64], zmm8
+        vmovdqu32 zmm25, zmmword ptr [r9 + 9 * 64]
+        vpxord zmm9, zmm9, zmm25
+        vmovdqu32 zmmword ptr [r9 + 9 * 64], zmm9
+        vmovdqu32 zmm26, zmmword ptr [r9 + 10 * 64]
+        vpxord zmm10, zmm10, zmm26
+        vmovdqu32 zmmword ptr [r9 + 10 * 64], zmm10
+        vmovdqu32 zmm27, zmmword ptr [r9 + 11 * 64]
+        vpxord zmm11, zmm11, zmm27
+        vmovdqu32 zmmword ptr [r9 + 11 * 64], zmm11
+        vmovdqu32 zmm28, zmmword ptr [r9 + 12 * 64]
+        vpxord zmm12, zmm12, zmm28
+        vmovdqu32 zmmword ptr [r9 + 12 * 64], zmm12
+        vmovdqu32 zmm29, zmmword ptr [r9 + 13 * 64]
+        vpxord zmm13, zmm13, zmm29
+        vmovdqu32 zmmword ptr [r9 + 13 * 64], zmm13
+        vmovdqu32 zmm30, zmmword ptr [r9 + 14 * 64]
+        vpxord zmm14, zmm14, zmm30
+        vmovdqu32 zmmword ptr [r9 + 14 * 64], zmm14
+        vmovdqu32 zmm31, zmmword ptr [r9 + 15 * 64]
+        vpxord zmm15, zmm15, zmm31
+        vmovdqu32 zmmword ptr [r9 + 15 * 64], zmm15
+        ret
 .balign 16
 BLAKE3_IV:
 BLAKE3_IV_0:
@@ -2845,3 +3967,10 @@
 .balign 64
 INCREMENT_2D:
 .quad  0, 0, 1, 0, 2, 0, 3, 0
+INCREMENT_3D:
+.quad  0, 1, 2, 3, 4, 5, 6, 7
+.balign 64
+EVEN_INDEXES:
+.long 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30
+ODD_INDEXES:
+.long 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31
diff --git a/src/kernel.rs b/src/kernel.rs
index cdcb25a..0d7a5b3 100644
--- a/src/kernel.rs
+++ b/src/kernel.rs
@@ -73,6 +73,14 @@
         flags: u32,
         out: *mut [u8; 64 * 4],
     );
+    pub fn blake3_avx512_xof_stream_16(
+        cv: &[u32; 8],
+        block: &[u8; 64],
+        counter: u64,
+        block_len: u32,
+        flags: u32,
+        out: *mut [u8; 64 * 16],
+    );
     pub fn blake3_sse2_xof_xor_1(
         cv: &[u32; 8],
         block: &[u8; 64],
@@ -121,6 +129,14 @@
         flags: u32,
         out: &mut [u8; 64 * 4],
     );
+    pub fn blake3_avx512_xof_xor_16(
+        cv: &[u32; 8],
+        block: &[u8; 64],
+        counter: u64,
+        block_len: u32,
+        flags: u32,
+        out: &mut [u8; 64 * 16],
+    );
 }
 
 pub type CompressionFn =
@@ -311,6 +327,15 @@
         }
         test_xof_functions(blake3_avx512_xof_stream_4, blake3_avx512_xof_xor_4);
     }
+
+    #[test]
+    #[cfg(target_arch = "x86_64")]
+    fn test_avx512_xof_16() {
+        if !is_x86_feature_detected!("avx512f") || !is_x86_feature_detected!("avx512vl") {
+            return;
+        }
+        test_xof_functions(blake3_avx512_xof_stream_16, blake3_avx512_xof_xor_16);
+    }
 }
 
 global_asm!(
@@ -2618,7 +2643,7 @@
     "ret",
     //
     // --------------------------------------------------------------------------------------------
-    // blake3_avx512_xof_stream_16
+    // blake3_avx512_xof_stream_16_ORIGINAL
     //
     // zmm0-zmm31: [clobbered]
     // rdi: pointer to the 16-word message block, 4-byte aligned
@@ -2631,7 +2656,7 @@
     // This routine performs the root compression for 16 consecutive output blocks and writes 1024
     // bytes of output to the out pointer.
     // --------------------------------------------------------------------------------------------
-    "blake3_avx512_xof_stream_16:",
+    "blake3_avx512_xof_stream_16_ORIGINAL:",
     // Broadcast the input CV into zmm0-zmm7, the first two rows of the state.
     "vpbroadcastd zmm0, dword ptr [rsi + 0 * 4]",
     "vpbroadcastd zmm1, dword ptr [rsi + 1 * 4]",
@@ -2801,7 +2826,7 @@
     "ret",
     //
     // --------------------------------------------------------------------------------------------
-    // blake3_avx512_xof_xor_16
+    // blake3_avx512_xof_xor_16_ORIGINAL
     //
     // zmm0-zmm31: [clobbered]
     // rdi: pointer to the 16-word message block, 4-byte aligned
@@ -2814,7 +2839,7 @@
     // This routine performs the root compression for 16 consecutive output blocks and xor's 1024
     // bytes of output into the inout pointer.
     // --------------------------------------------------------------------------------------------
-    "blake3_avx512_xof_xor_16:",
+    "blake3_avx512_xof_xor_16_ORIGINAL:",
     // Broadcast the input CV into zmm0-zmm7, the first two rows of the state.
     "vpbroadcastd zmm0, dword ptr [rsi + 0 * 4]",
     "vpbroadcastd zmm1, dword ptr [rsi + 1 * 4]",
@@ -3143,7 +3168,7 @@
         counter_vectors[1].0[i] = ((counter + i as u64) >> 32) as u32;
     }
     asm!(
-        "call blake3_avx512_xof_stream_16",
+        "call blake3_avx512_xof_stream_16_ORIGINAL",
         inout("rdi") message_words => _,
         inout("rsi") cv_words => _,
         inout("rdx") &counter_vectors => _,
@@ -3176,7 +3201,7 @@
         counter_vectors[1].0[i] = ((counter + i as u64) >> 32) as u32;
     }
     asm!(
-        "call blake3_avx512_xof_xor_16",
+        "call blake3_avx512_xof_xor_16_ORIGINAL",
         inout("rdi") message_words => _,
         inout("rsi") cv_words => _,
         inout("rdx") &counter_vectors => _,