// File: /workspace/github_c_makefile_star2_O1/mjosaarinen[P]brutus/crypto_aead/paeq128/aesni/encrypt.cpp
// Function: FPerm(unsigned char const*, unsigned char*)
void FPerm(const unsigned char* input, unsigned char* output)//AESQ permutation
{

	unsigned char Registers[4][16];  //AES state registers
	unsigned char Registers_tmp[4][16];  //AES state registers

	for (unsigned i = 0; i<4; ++i)//Filling registers
	{
		for (unsigned j = 0; j<16; ++j)
			Registers[i][j] = input[16 * i + j];
	}

	//Main permutation
	for (unsigned i = 0; i<AES_GROUPS; ++i)//Group loop
	{
		//AES rounds
		for (unsigned r = 0; r<4; ++r)//Register loop
		{
			for (unsigned j = 0; j<AES_GROUP_ROUNDS; ++j)//Middle rounds
			{
				AES_Round(Registers[r]); //SB-SR-MC
				for (unsigned k = 0; k<4; ++k)  //Round constants
				{
					Registers[r][4 * k] ^= 8 * i + 4 * j + r + 1;
				}
			}
		}
		//Permutation
		for (unsigned r = 0; r<4; ++r)//Register loop
			for (unsigned j = 0; j<16; ++j)
				Registers_tmp[r][j] = Registers[r][j];

		for (unsigned r = 0; r<4; ++r)//Register loop
		{
			for (unsigned i = 0; i<4; ++i)//Column loop
			{
				unsigned char r_out = Shuffle[4 * r + i] / 4;  //Register index
				unsigned char c_out = Shuffle[4 * r + i] % 4;  //Column index
				for (unsigned j = 0; j<4; ++j)
					Registers[r_out][4 * c_out + j] = Registers_tmp[r][4 * i + j];
			}
		}


	}
	for (unsigned i = 0; i<4; ++i)//Filling registers
	{
		for (unsigned j = 0; j<16; ++j)
			output[16 * i + j] = Registers[i][j];
	}

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %rsi, (%rsp)
xorl %eax, %eax
vmovdqu (%rdi,%rax), %xmm0
vmovdqu %xmm0, 0x10(%rsp,%rax)
addq $0x10, %rax
cmpq $0x40, %rax
jne 0x12a2
xorl %eax, %eax
leaq 0x10(%rsp), %rbx
movq %rax, 0x8(%rsp)
leal (,%rax,8), %ebp
movq %rbx, %r12
xorl %r15d, %r15d
movq %r15, %rax
shlq $0x4, %rax
leaq (%rsp,%rax), %r14
addq $0x10, %r14
xorl %r13d, %r13d
movq %r14, %rdi
vzeroupper
callq 0x10a0
leal (%rbp,%r13,4), %eax
addl %r15d, %eax
incb %al
xorl %ecx, %ecx
xorb %al, (%r12,%rcx,4)
incq %rcx
cmpq $0x4, %rcx
jne 0x12f9
leal 0x1(%r13), %eax
testl %r13d, %r13d
movl %eax, %r13d
je 0x12e2
incq %r15
addq $0x10, %r12
cmpq $0x4, %r15
jne 0x12d0
vmovups 0x10(%rsp), %ymm0
vmovups 0x30(%rsp), %ymm1
vmovups %ymm1, 0x70(%rsp)
vmovups %ymm0, 0x50(%rsp)
xorl %eax, %eax
movq 0x3c98(%rip), %rcx      # 0x4fd8
vpbroadcastb 0x1cb7(%rip), %xmm2 # 0x3000
vpbroadcastb 0x1caf(%rip), %xmm3 # 0x3001
vmovd (%rcx,%rax), %xmm0
vpsrlw $0x2, %xmm0, %xmm1
vpand %xmm2, %xmm1, %xmm1
vpmovzxbq %xmm1, %ymm1    # ymm1 = xmm1[0],zero,zero,zero,zero,zero,zero,zero,xmm1[1],zero,zero,zero,zero,zero,zero,zero,xmm1[2],zero,zero,zero,zero,zero,zero,zero,xmm1[3],zero,zero,zero,zero,zero,zero,zero
vpsllq $0x4, %ymm1, %ymm1
vpsllw $0x2, %xmm0, %xmm0
vpand %xmm3, %xmm0, %xmm0
vpmovzxbq %xmm0, %ymm0    # ymm0 = xmm0[0],zero,zero,zero,zero,zero,zero,zero,xmm0[1],zero,zero,zero,zero,zero,zero,zero,xmm0[2],zero,zero,zero,zero,zero,zero,zero,xmm0[3],zero,zero,zero,zero,zero,zero,zero
vpor %ymm0, %ymm1, %ymm0
vmovdqa 0x50(%rsp,%rax,4), %xmm1
kxnorw %k0, %k0, %k1
vpscatterqd %xmm1, (%rbx,%ymm0) {%k1}
addq $0x4, %rax
cmpq $0x10, %rax
jne 0x1352
movq 0x8(%rsp), %rax
incl %eax
cmpl $0xa, %eax
jne 0x12be
xorl %eax, %eax
movq (%rsp), %rcx
vmovdqu 0x10(%rsp,%rax), %xmm0
vmovdqu %xmm0, (%rcx,%rax)
addq $0x10, %rax
cmpq $0x40, %rax
jne 0x13ad
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
vzeroupper
retq