/*
 * Copyright (c) The mldsa-native project authors
 * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
 */

/* References
 * ==========
 *
 * - [REF_AVX2]
 *   CRYSTALS-Dilithium optimized AVX2 implementation
 *   Bai, Ducas, Kiltz, Lepoint, Lyubashevsky, Schwabe, Seiler, Stehlé
 *   https://github.com/pq-crystals/dilithium/tree/master/avx2
 */

/*
 * This file is derived from the public domain
 * AVX2 Dilithium implementation @[REF_AVX2].
 */

/*yaml
  Name: pointwise_acc_l4_avx2_asm
  Description: x86_64 AVX2 pointwise multiply-accumulate of length-4 polynomial vectors
  Signature: void mld_pointwise_acc_l4_avx2_asm(int32_t *c, const int32_t a[4][256], const int32_t b[4][256], const int32_t *qdata)
  ABI:
    Architecture: x86_64
    CallingConvention: SysV
    Features: [AVX2]
    rdi:
      type: buffer
      size_bytes: 1024
      permissions: write-only
      c_parameter: int32_t *c
      description: Output polynomial (256 x int32_t)
    rsi:
      type: buffer
      size_bytes: 4096
      permissions: read-only
      c_parameter: const int32_t a[4][256]
      description: Input polynomial vector a (4 x 256 x int32_t)
    rdx:
      type: buffer
      size_bytes: 4096
      permissions: read-only
      c_parameter: const int32_t b[4][256]
      description: Input polynomial vector b (4 x 256 x int32_t)
    rcx:
      type: buffer
      size_bytes: 2496
      permissions: read-only
      c_parameter: const int32_t *qdata
      description: Precomputed constants (624 x int32_t)
*/


/*
 * WARNING: This file is auto-derived from the mldsa-native source file
 *   dev/x86_64/src/pointwise_acc_l4_avx2_asm.S using scripts/simpasm. Do not modify it directly.
 */

.text
.balign 4
#ifdef __APPLE__
.global _mld_pointwise_acc_l4_avx2_asm
_mld_pointwise_acc_l4_avx2_asm:
#else
.global mld_pointwise_acc_l4_avx2_asm
mld_pointwise_acc_l4_avx2_asm:
#endif

        .cfi_startproc
        endbr64
        vmovdqa 0x20(%rcx), %ymm0
        vmovdqa (%rcx), %ymm1
        xorl %eax, %eax

Lpointwise_acc_l4_avx2_looptop2:
        vmovdqa (%rsi), %ymm6
        vmovdqa 0x20(%rsi), %ymm8
        vmovdqa (%rdx), %ymm10
        vmovdqa 0x20(%rdx), %ymm12
        vpsrlq $0x20, %ymm6, %ymm7
        vpsrlq $0x20, %ymm8, %ymm9
        vmovshdup %ymm10, %ymm11  # ymm11 = ymm10[1,1,3,3,5,5,7,7]
        vmovshdup %ymm12, %ymm13  # ymm13 = ymm12[1,1,3,3,5,5,7,7]
        vpmuldq %ymm10, %ymm6, %ymm6
        vpmuldq %ymm11, %ymm7, %ymm7
        vpmuldq %ymm12, %ymm8, %ymm8
        vpmuldq %ymm13, %ymm9, %ymm9
        vmovdqa %ymm6, %ymm2
        vmovdqa %ymm7, %ymm3
        vmovdqa %ymm8, %ymm4
        vmovdqa %ymm9, %ymm5
        vmovdqa 0x400(%rsi), %ymm6
        vmovdqa 0x420(%rsi), %ymm8
        vmovdqa 0x400(%rdx), %ymm10
        vmovdqa 0x420(%rdx), %ymm12
        vpsrlq $0x20, %ymm6, %ymm7
        vpsrlq $0x20, %ymm8, %ymm9
        vmovshdup %ymm10, %ymm11  # ymm11 = ymm10[1,1,3,3,5,5,7,7]
        vmovshdup %ymm12, %ymm13  # ymm13 = ymm12[1,1,3,3,5,5,7,7]
        vpmuldq %ymm10, %ymm6, %ymm6
        vpmuldq %ymm11, %ymm7, %ymm7
        vpmuldq %ymm12, %ymm8, %ymm8
        vpmuldq %ymm13, %ymm9, %ymm9
        vpaddq %ymm2, %ymm6, %ymm2
        vpaddq %ymm3, %ymm7, %ymm3
        vpaddq %ymm4, %ymm8, %ymm4
        vpaddq %ymm5, %ymm9, %ymm5
        vmovdqa 0x800(%rsi), %ymm6
        vmovdqa 0x820(%rsi), %ymm8
        vmovdqa 0x800(%rdx), %ymm10
        vmovdqa 0x820(%rdx), %ymm12
        vpsrlq $0x20, %ymm6, %ymm7
        vpsrlq $0x20, %ymm8, %ymm9
        vmovshdup %ymm10, %ymm11  # ymm11 = ymm10[1,1,3,3,5,5,7,7]
        vmovshdup %ymm12, %ymm13  # ymm13 = ymm12[1,1,3,3,5,5,7,7]
        vpmuldq %ymm10, %ymm6, %ymm6
        vpmuldq %ymm11, %ymm7, %ymm7
        vpmuldq %ymm12, %ymm8, %ymm8
        vpmuldq %ymm13, %ymm9, %ymm9
        vpaddq %ymm2, %ymm6, %ymm2
        vpaddq %ymm3, %ymm7, %ymm3
        vpaddq %ymm4, %ymm8, %ymm4
        vpaddq %ymm5, %ymm9, %ymm5
        vmovdqa 0xc00(%rsi), %ymm6
        vmovdqa 0xc20(%rsi), %ymm8
        vmovdqa 0xc00(%rdx), %ymm10
        vmovdqa 0xc20(%rdx), %ymm12
        vpsrlq $0x20, %ymm6, %ymm7
        vpsrlq $0x20, %ymm8, %ymm9
        vmovshdup %ymm10, %ymm11  # ymm11 = ymm10[1,1,3,3,5,5,7,7]
        vmovshdup %ymm12, %ymm13  # ymm13 = ymm12[1,1,3,3,5,5,7,7]
        vpmuldq %ymm10, %ymm6, %ymm6
        vpmuldq %ymm11, %ymm7, %ymm7
        vpmuldq %ymm12, %ymm8, %ymm8
        vpmuldq %ymm13, %ymm9, %ymm9
        vpaddq %ymm2, %ymm6, %ymm2
        vpaddq %ymm3, %ymm7, %ymm3
        vpaddq %ymm4, %ymm8, %ymm4
        vpaddq %ymm5, %ymm9, %ymm5
        vpmuldq %ymm2, %ymm0, %ymm6
        vpmuldq %ymm3, %ymm0, %ymm7
        vpmuldq %ymm4, %ymm0, %ymm8
        vpmuldq %ymm5, %ymm0, %ymm9
        vpmuldq %ymm6, %ymm1, %ymm6
        vpmuldq %ymm7, %ymm1, %ymm7
        vpmuldq %ymm8, %ymm1, %ymm8
        vpmuldq %ymm9, %ymm1, %ymm9
        vpsubq %ymm6, %ymm2, %ymm2
        vpsubq %ymm7, %ymm3, %ymm3
        vpsubq %ymm8, %ymm4, %ymm4
        vpsubq %ymm9, %ymm5, %ymm5
        vpsrlq $0x20, %ymm2, %ymm2
        vmovshdup %ymm4, %ymm4    # ymm4 = ymm4[1,1,3,3,5,5,7,7]
        vpblendd $0xaa, %ymm3, %ymm2, %ymm2 # ymm2 = ymm2[0],ymm3[1],ymm2[2],ymm3[3],ymm2[4],ymm3[5],ymm2[6],ymm3[7]
        vpblendd $0xaa, %ymm5, %ymm4, %ymm4 # ymm4 = ymm4[0],ymm5[1],ymm4[2],ymm5[3],ymm4[4],ymm5[5],ymm4[6],ymm5[7]
        vmovdqa %ymm2, (%rdi)
        vmovdqa %ymm4, 0x20(%rdi)
        addq $0x40, %rsi
        addq $0x40, %rdx
        addq $0x40, %rdi
        addl $0x1, %eax
        cmpl $0x10, %eax
        jb Lpointwise_acc_l4_avx2_looptop2
        retq
        .cfi_endproc

#if defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif
