// File: /workspace/github_c_makefile_star2_O2/mjosaarinen[P]brutus/crypto_aead/aes256otrpv3/ni_p8m1/encrypt.c
// Function: AFunc
__m128i AFunc(
	const uint8 *header,
	uint32 h_len)
{
	uint32 i;
	uint32 m, last;
	block tmp[PIPE], mask[PIPE + 1], ASum = _mm_setzero_si128();
	uint32 rest_len = h_len;
	const __m128i *hdp = (__m128i*)header;

	mask[0] = _mm_load_si128(&Q);
	while (rest_len > (BLOCK*PIPE)){
		mul2_PIPE(mask);
		for (i = 0; i < PIPE; i++){
			tmp[i] = _mm_xor_si128(mask[i], hdp[i]);
		}
		AES_ecb_encrypt_PIPE(tmp, encrypt_key);
		for (i = 0; i < PIPE; i++){
			ASum = _mm_xor_si128(ASum, tmp[i]);
		}
		rest_len -= (BLOCK*PIPE);
		hdp += PIPE;
		mask[0] = _mm_load_si128(&mask[PIPE]);
	}

	last = rest_len % BLOCK;
	if (last == 0) last = BLOCK;
	m = (rest_len - last) / BLOCK; //header = m blocks + last bytes

	for (i = 0; i < m; i++){
		tmp[0] = _mm_xor_si128(mask[0], hdp[i]);
		AES_encrypt(tmp[0], &tmp[0], encrypt_key);
		ASum = _mm_xor_si128(ASum, tmp[0]);
		mul2(mask[0], &mask[0]);
	}
	hdp += m;
	/* last block */
	ozp(last, (uint8*)&hdp[0], &tmp[0]);
	ASum = _mm_xor_si128(ASum, tmp[0]);
	if (last != BLOCK){
		mul3(mask[0], &mask[0]);
	}
	else{
		mul3twice(mask[0], &mask[0]);
	}
	ASum = _mm_xor_si128(ASum, mask[0]);
	AES_encrypt(ASum, &ASum, encrypt_key);
	return ASum; //TA
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x178, %rsp            # imm = 0x178
movl %esi, %r14d
movq %rdi, %rbx
movq 0x4b62(%rip), %rax      # 0x6fe0
vmovdqa (%rax), %xmm1
vpxor %xmm0, %xmm0, %xmm0
leaq 0x60(%rsp), %r15
leaq 0xf0(%rsp), %r12
vmovdqa %xmm1, 0x60(%rsp)
cmpl $0x81, %r14d
vmovdqa %xmm0, 0x20(%rsp)
jb 0x250e
movq %r15, %rdi
callq 0x195c
xorl %eax, %eax
cmpq $0x80, %rax
je 0x24d4
vmovdqa (%rbx,%rax), %xmm0
vpxor 0x60(%rsp,%rax), %xmm0, %xmm0
vmovdqa %xmm0, 0xf0(%rsp,%rax)
addq $0x10, %rax
jmp 0x24b2
movq %r12, %rdi
callq 0x1a7d
xorl %eax, %eax
vmovdqa 0x20(%rsp), %xmm0
cmpq $0x80, %rax
je 0x24fb
vpxor 0xf0(%rsp,%rax), %xmm0, %xmm0
addq $0x10, %rax
jmp 0x24e4
addl $-0x80, %r14d
subq $-0x80, %rbx
vmovdqa 0xe0(%rsp), %xmm1
jmp 0x2493
vmovdqa %xmm0, 0x30(%rsp)
movl %r14d, %eax
andl $0xf, %eax
pushq $0x10
popq %r12
movl %eax, 0xc(%rsp)
cmovnel %eax, %r12d
subl %r12d, %r14d
shrl $0x4, %r14d
vmovaps 0x60(%rsp), %xmm0
xorl %r13d, %r13d
leaq 0xf0(%rsp), %r15
movq %rbx, %rbp
cmpq %r14, %r13
vmovdqa %xmm1, 0x10(%rsp)
jae 0x25b5
vpxor (%rbp), %xmm1, %xmm0
vmovdqa %xmm0, 0xf0(%rsp)
movq %r15, %rdi
callq 0x11b1
vmovaps 0x20(%rsp), %xmm0
vxorps 0xf0(%rsp), %xmm0, %xmm0
vmovaps %xmm0, 0x20(%rsp)
vmovdqa 0xa81(%rip), %xmm2      # 0x3000
vmovdqa 0x10(%rsp), %xmm0
vpshufb %xmm2, %xmm0, %xmm0
vpshufd $0x93, %xmm0, %xmm1     # xmm1 = xmm0[3,0,1,2]
vpsrad $0x1f, %xmm1, %xmm1
vpaddd %xmm0, %xmm0, %xmm0
vpternlogd $0x78, 0xa6d(%rip), %xmm1, %xmm0 # 0x3010
vpshufb %xmm2, %xmm0, %xmm0
incq %r13
addq $0x10, %rbp
vmovdqa %xmm0, %xmm1
jmp 0x2541
vmovaps %xmm0, 0x60(%rsp)
shll $0x4, %r14d
addq %r14, %rbx
vxorps %xmm0, %xmm0, %xmm0
leaq 0x40(%rsp), %r14
vmovaps %xmm0, (%r14)
movb $0x0, 0x10(%r14)
movl %r12d, %r15d
movq %r14, %rdi
movq %rbx, %rsi
movq %r15, %rdx
callq 0x10b0
movb $-0x80, 0x40(%rsp,%r15)
vmovdqa (%r14), %xmm4
cmpl $0x0, 0xc(%rsp)
je 0x262f
vmovdqa 0x10(%rsp), %xmm0
vmovdqa 0x9fa(%rip), %xmm3      # 0x3000
vpshufb %xmm3, %xmm0, %xmm0
vpshufd $0x93, %xmm0, %xmm1     # xmm1 = xmm0[3,0,1,2]
vpsrad $0x1f, %xmm1, %xmm1
vpand 0x9f3(%rip), %xmm1, %xmm1 # 0x3010
vpaddd %xmm0, %xmm0, %xmm2
vpternlogq $0x96, %xmm1, %xmm0, %xmm2
vpshufb %xmm3, %xmm2, %xmm1
jmp 0x2652
leaq 0x60(%rsp), %rbx
vmovdqa 0x10(%rsp), %xmm0
movq %rbx, %rdi
vmovdqa %xmm4, 0x10(%rsp)
callq 0x1c05
vmovdqa 0x10(%rsp), %xmm4
vmovdqa (%rbx), %xmm1
vmovdqa 0x20(%rsp), %xmm0
vpternlogq $0x96, %xmm1, %xmm4, %xmm0
leaq 0x30(%rsp), %rbx
vmovdqa %xmm0, (%rbx)
movq %rbx, %rdi
callq 0x11b1
vmovaps (%rbx), %xmm0
addq $0x178, %rsp            # imm = 0x178
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq