// File: /workspace/github_cpp_makefile_star2_O2/IshaySela[P]ChaCha20/src/ChaCha.cpp
// Function: ChaCha::ChaCha20::GenerateKeyBlock(long long, long long)
std::array<char, BLOCK_SIZE_BYTES> ChaCha20::GenerateKeyBlock(long long position, long long nonce)
    {
        std::array<char, BLOCK_SIZE_BYTES> block = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

        int matrix[4][4] = {
            {0x65787061, 0x6e642033, 0x322d6279, 0x7465206b}, // The constatnts, "expand 32 by te k" in ascii.
            {this->key[0], this->key[1], this->key[2], this->key[3]},
            {this->key[4], this->key[5], this->key[6], this->key[7]},
            {static_cast<int>(position), static_cast<int>(position >> 32), static_cast<int>(nonce), static_cast<int>(nonce >> 32)}};

        for (int i = 0; i < this->rounds; i++)
        {
            // Perform the querter round on the columns
            this->QuerterRound(matrix[0][0], matrix[1][0], matrix[2][0], matrix[3][0]);
            this->QuerterRound(matrix[0][1], matrix[1][1], matrix[2][1], matrix[3][1]);
            this->QuerterRound(matrix[0][2], matrix[1][2], matrix[2][2], matrix[3][2]);
            this->QuerterRound(matrix[0][3], matrix[1][3], matrix[2][3], matrix[3][3]);

            // Perform the querter round on the diagonals
            this->QuerterRound(matrix[0][0], matrix[1][1], matrix[2][2], matrix[3][3]);
            this->QuerterRound(matrix[0][1], matrix[1][2], matrix[2][3], matrix[3][0]);
            this->QuerterRound(matrix[0][2], matrix[1][3], matrix[2][0], matrix[3][1]);
            this->QuerterRound(matrix[0][3], matrix[1][0], matrix[2][1], matrix[3][2]);
        }

        std::copy_n(reinterpret_cast<char *>(&matrix), BLOCK_SIZE_BYTES, block.data());

        return block;
    }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rdi)
movq %rdi, 0x50(%rsp)
movups %xmm0, (%rdi)
leaq 0xc(%rsp), %rax
movaps 0xd35(%rip), %xmm0      # 0x2010
movaps %xmm0, -0xc(%rax)
leaq 0x1c(%rsp), %rax
movups (%rsi), %xmm0
movaps %xmm0, -0xc(%rax)
leaq 0x2c(%rsp), %rax
movups 0x10(%rsi), %xmm0
movaps %xmm0, -0xc(%rax)
leaq 0x30(%rsp), %rax
movl %edx, (%rax)
leaq 0x34(%rsp), %rax
shrq $0x20, %rdx
movl %edx, (%rax)
leaq 0x38(%rsp), %rax
movl %ecx, (%rax)
leaq 0x3c(%rsp), %rax
shrq $0x20, %rcx
movl %ecx, (%rax)
movl 0x20(%rsi), %eax
movl %eax, 0x4c(%rsp)
xorl %ebx, %ebx
cmpl 0x4c(%rsp), %ebx
jge 0x13ff
movq %rsp, %rsi
leaq 0x10(%rsp), %rdx
leaq 0x20(%rsp), %rcx
leaq 0x30(%rsp), %r8
callq 0x1424
leaq 0x4(%rsp), %rsi
leaq 0x14(%rsp), %rdx
leaq 0x24(%rsp), %rcx
leaq 0x34(%rsp), %r8
callq 0x1424
leaq 0x8(%rsp), %rsi
leaq 0x18(%rsp), %rbp
movq %rbp, %rdx
leaq 0x28(%rsp), %r13
movq %r13, %rcx
leaq 0x38(%rsp), %r8
callq 0x1424
leaq 0xc(%rsp), %rsi
leaq 0x1c(%rsp), %r14
movq %r14, %rdx
leaq 0x2c(%rsp), %r15
movq %r15, %rcx
leaq 0x3c(%rsp), %r12
movq %r12, %r8
callq 0x1424
movq %rsp, %rsi
leaq 0x14(%rsp), %rdx
movq %r13, %rcx
movq %r12, %r8
callq 0x1424
leaq 0x4(%rsp), %rsi
movq %rbp, %rdx
movq %r15, %rcx
leaq 0x30(%rsp), %r8
callq 0x1424
leaq 0x8(%rsp), %rsi
movq %r14, %rdx
leaq 0x20(%rsp), %rcx
leaq 0x34(%rsp), %r8
callq 0x1424
leaq 0xc(%rsp), %rsi
leaq 0x10(%rsp), %rdx
leaq 0x24(%rsp), %rcx
leaq 0x38(%rsp), %r8
callq 0x1424
incl %ebx
jmp 0x1325
movaps (%rsp), %xmm0
movaps 0x10(%rsp), %xmm1
movq 0x50(%rsp), %rax
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop