// File: /workspace/github_c_makefile_star2_O1/mjosaarinen[P]brutus/crypto_aead/aes128poetv2aes4/ref/poet.c
// Function: decrypt_final
int decrypt_final(poet_ctx_t *ctx,
                  const unsigned char *ciphertext,
                  unsigned long long clen,
                  const unsigned char tag[TAGLEN],
                  unsigned char *plaintext, 
                  unsigned long long* plen)
{
    uint64_t offset = 0;
    block s;
    block tmp;
    block tmp2;
    int alpha;
    int beta;

    if (plen) {
        *plen = clen;
    }

    while (clen > BLOCKLEN) {
        decrypt_block(ctx, ciphertext + offset, plaintext + offset);
        clen -= BLOCKLEN;
        offset += BLOCKLEN;
    }

    // Encrypt the message length
    ctx->mlen += clen * 8;
    encode_length(s, ctx->mlen);
    aes_encrypt(s, s, &(ctx->aes_enc));

    // Pad the final ciphertext block if necessary
    memcpy(tmp, ciphertext + offset, clen);
    memcpy(tmp + clen, tag, BLOCKLEN - clen);

    // Process last block and generate the tag
    BOTTOM_HASH;
    xor_block(tmp, s, tmp);

    xor_block(ctx->y, tmp, ctx->y);
    aes_decrypt(ctx->y, tmp, &(ctx->aes_dec));

    TOP_HASH;
    xor_block(tmp2, tmp, ctx->x);
    xor_block(tmp2, s, tmp2);
    memcpy(ctx->x, tmp, BLOCKLEN);

    // Perform tag splitting if needed
    memcpy(plaintext + offset, tmp2, clen);
    alpha = compare_blocks(tmp2 + clen, ctx->tau, BLOCKLEN - clen);

    // Generate tag
    TOP_HASH;
    xor_block(ctx->x, ctx->tau , ctx->x);
    aes_encrypt(ctx->x, tmp, &(ctx->aes_enc));

    BOTTOM_HASH;
    xor_block(tmp, ctx->y, tmp);
    xor_block(tmp, ctx->tau, tmp);

    beta = compare_blocks(tmp, tag + (BLOCKLEN - clen), clen);
    return alpha | beta;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rcx, 0x38(%rsp)
movq %rdx, %r14
movq %rdi, %rcx
testq %r9, %r9
je 0x3ff9
movq %r14, (%r9)
cmpq $0x11, %r14
movq %rcx, (%rsp)
movq %r8, 0x58(%rsp)
movq %rsi, 0x28(%rsp)
jb 0x40ce
leaq 0x31c(%rcx), %r13
leaq 0x1e8(%rcx), %rax
movq %rax, 0x8(%rsp)
leaq 0xf4(%rcx), %rax
movq %rax, 0x30(%rsp)
leaq 0x30c(%rcx), %rbx
xorl %r15d, %r15d
movq %r8, %r12
movq %rsi, %rbp
movq %r13, %rdi
movq %r13, %rsi
movq 0x8(%rsp), %rdx
callq 0x10a0
xorl %eax, %eax
movb (%rbp,%rax), %cl
xorb %cl, (%r13,%rax)
incq %rax
cmpq $0x10, %rax
jne 0x4052
movq %r13, %rdi
leaq 0x10(%rsp), %rsi
movq 0x30(%rsp), %rdx
callq 0x10f0
movq %rbx, %rdi
movq %rbx, %rsi
movq 0x8(%rsp), %rdx
callq 0x10a0
xorl %eax, %eax
movb (%rbx,%rax), %cl
xorb 0x10(%rsp,%rax), %cl
movb %cl, (%r12,%rax)
incq %rax
cmpq $0x10, %rax
jne 0x4088
vmovaps 0x10(%rsp), %xmm0
vmovups %xmm0, (%rbx)
movq (%rsp), %rcx
subq $-0x80, 0x340(%rcx)
addq $-0x10, %r14
addq $0x10, %r15
addq $0x10, %rbp
addq $0x10, %r12
cmpq $0x10, %r14
ja 0x4040
jmp 0x40d1
xorl %r15d, %r15d
leaq (,%r14,8), %rax
addq 0x340(%rcx), %rax
movq %rax, 0x340(%rcx)
vxorps %xmm0, %xmm0, %xmm0
vmovaps %xmm0, 0x10(%rsp)
vpbroadcastq %rax, %ymm0
vpmovsxbq 0x3064(%rip), %ymm1 # 0x7164
xorl %eax, %eax
vpbroadcastq 0x3195(%rip), %ymm2 # 0x72a0
vpsllq $0x3, %ymm1, %ymm3
vpsrlvq %ymm3, %ymm0, %ymm3
vpmovqb %ymm3, 0x10(%rsp,%rax)
addq $0x4, %rax
vpaddq %ymm2, %ymm1, %ymm1
cmpq $0x8, %rax
jne 0x410b
leaq 0x10(%rsp), %rdi
movq %rdi, %rsi
movq %rcx, %rbp
movq %rcx, %rdx
vzeroupper
callq 0x1100
movq 0x28(%rsp), %rsi
addq %r15, %rsi
leaq 0x40(%rsp), %r13
movq %r13, %rdi
movq %r14, %rdx
callq 0x1110
leaq (%rsp,%r14), %rdi
addq $0x40, %rdi
leaq -0x10(%r14), %rdx
negq %rdx
movq 0x38(%rsp), %rsi
movq %rdx, 0x28(%rsp)
callq 0x1110
leaq 0x31c(%rbp), %r12
leaq 0x1e8(%rbp), %rbx
movq %r12, %rdi
movq %r12, %rsi
movq %rbx, %rdx
callq 0x10a0
vmovaps (%r13), %xmm0
leaq 0x10(%rsp), %rax
vxorps (%rax), %xmm0, %xmm0
vmovaps %xmm0, (%r13)
vxorps 0x31c(%rbp), %xmm0, %xmm0
vmovups %xmm0, 0x31c(%rbp)
leaq 0xf4(%rbp), %rdx
movq %r12, 0x8(%rsp)
movq %r12, %rdi
movq %r13, %rsi
callq 0x10f0
leaq 0x30c(%rbp), %r12
movq %r12, %rdi
movq %r12, %rsi
movq %rbx, 0x30(%rsp)
movq %rbx, %rdx
callq 0x10a0
vmovdqa (%r13), %xmm0
vmovdqu 0x30c(%rbp), %xmm1
leaq 0x10(%rsp), %rax
vpternlogq $0x96, (%rax), %xmm0, %xmm1
leaq 0x60(%rsp), %rsi
vmovdqa %xmm1, (%rsi)
vmovdqu %xmm0, 0x30c(%rbp)
movq 0x58(%rsp), %rdi
addq %r15, %rdi
movq %r14, %rdx
callq 0x1110
xorl %r13d, %r13d
movl $0x0, %eax
cmpq $0x10, %r14
je 0x43a7
leaq 0x32c(%rbp), %rax
leaq (%rsp,%r14), %rcx
addq $0x60, %rcx
movl $0x2f, %edx
subl %r14d, %edx
andl $0x20, %edx
movl $0xf, %esi
subq %r14, %rsi
vpbroadcastq %rsi, %ymm1
vpxor %xmm0, %xmm0, %xmm0
xorl %esi, %esi
vpmovsxbq 0x2efb(%rip), %ymm2 # 0x7168
vpmovsxbq 0x2ef6(%rip), %ymm3 # 0x716c
vpmovsxbq 0x2ef1(%rip), %ymm4 # 0x7170
vpmovsxbq 0x2eec(%rip), %ymm5 # 0x7174
vpmovsxbq 0x2ee7(%rip), %ymm6 # 0x7178
vpmovsxbq 0x2ee2(%rip), %ymm7 # 0x717c
vpmovsxbq 0x2edd(%rip), %ymm8 # 0x7180
vpmovsxbq 0x2eb8(%rip), %ymm9 # 0x7164
vpbroadcastq %rsi, %ymm10
vpor %ymm2, %ymm10, %ymm11
vpor %ymm3, %ymm10, %ymm12
vpor %ymm4, %ymm10, %ymm13
vpor %ymm5, %ymm10, %ymm14
vpor %ymm6, %ymm10, %ymm15
vporq %ymm7, %ymm10, %ymm16
vporq %ymm8, %ymm10, %ymm17
vpor %ymm9, %ymm10, %ymm10
vpcmpleuq %ymm1, %ymm10, %k0
vpcmpleuq %ymm1, %ymm17, %k1
kshiftlb $0x4, %k1, %k1
korb %k1, %k0, %k0
vpcmpleuq %ymm1, %ymm16, %k1
vpcmpleuq %ymm1, %ymm15, %k2
kshiftlb $0x4, %k2, %k2
korb %k2, %k1, %k1
kunpckbw %k0, %k1, %k0
vpcmpleuq %ymm1, %ymm14, %k1
vpcmpleuq %ymm1, %ymm13, %k2
kshiftlb $0x4, %k2, %k2
korb %k2, %k1, %k1
vpcmpleuq %ymm1, %ymm12, %k2
vpcmpleuq %ymm1, %ymm11, %k3
kshiftlb $0x4, %k3, %k3
korb %k3, %k2, %k2
kunpckbw %k1, %k2, %k1
kunpckwd %k0, %k1, %k1
vmovdqu8 (%rcx,%rsi), %ymm11 {%k1} {z}
vmovdqa %ymm0, %ymm10
vmovdqu8 (%rax,%rsi), %ymm0 {%k1} {z}
vpternlogq $0xde, %ymm11, %ymm10, %ymm0
addq $0x20, %rsi
cmpq %rsi, %rdx
jne 0x42ac
vmovdqu8 %ymm0, %ymm10 {%k1}
vextracti128 $0x1, %ymm10, %xmm0
vpor %xmm0, %xmm10, %xmm0
vpshufd $0xee, %xmm0, %xmm1     # xmm1 = xmm0[2,3,2,3]
vpor %xmm1, %xmm0, %xmm0
vpsrlq $0x20, %xmm0, %xmm1
vpor %xmm1, %xmm0, %xmm0
vpsrld $0x10, %xmm0, %xmm1
vpor %xmm1, %xmm0, %xmm0
vpsrlw $0x8, %xmm0, %xmm1
vpor %xmm1, %xmm0, %xmm0
vpextrb $0x0, %xmm0, %eax
movq (%rsp), %rbp
movl %eax, (%rsp)
movq %r12, %rdi
movq %r12, %rsi
movq 0x30(%rsp), %r15
movq %r15, %rdx
vzeroupper
callq 0x10a0
vmovups 0x30c(%rbp), %xmm0
vxorps 0x32c(%rbp), %xmm0, %xmm0
vmovups %xmm0, 0x30c(%rbp)
leaq 0x40(%rsp), %rbx
movq %r12, %rdi
movq %rbx, %rsi
movq %rbp, %rdx
callq 0x1100
movq 0x8(%rsp), %rdi
movq %rdi, %rsi
movq %r15, %rdx
callq 0x10a0
vmovdqa (%rbx), %xmm0
vpxor 0x31c(%rbp), %xmm0, %xmm0
vmovdqa %xmm0, (%rbx)
vpxor 0x32c(%rbp), %xmm0, %xmm0
vmovdqa %xmm0, (%rbx)
testq %r14, %r14
je 0x4580
movq 0x38(%rsp), %rdx
addq 0x28(%rsp), %rdx
leal 0x1f(%r14), %eax
andl $0x20, %eax
decq %r14
vpbroadcastq %r14, %ymm1
vpxor %xmm0, %xmm0, %xmm0
xorl %ecx, %ecx
vpmovsxbq 0x2d1f(%rip), %ymm2 # 0x7168
vpmovsxbq 0x2d1a(%rip), %ymm3 # 0x716c
vpmovsxbq 0x2d15(%rip), %ymm4 # 0x7170
vpmovsxbq 0x2d10(%rip), %ymm5 # 0x7174
vpmovsxbq 0x2d0b(%rip), %ymm6 # 0x7178
vpmovsxbq 0x2d06(%rip), %ymm7 # 0x717c
vpmovsxbq 0x2d01(%rip), %ymm8 # 0x7180
vpmovsxbq 0x2cdc(%rip), %ymm9 # 0x7164
vpbroadcastq %rcx, %ymm10
vpor %ymm2, %ymm10, %ymm11
vpor %ymm3, %ymm10, %ymm12
vpor %ymm4, %ymm10, %ymm13
vpor %ymm5, %ymm10, %ymm14
vpor %ymm6, %ymm10, %ymm15
vporq %ymm7, %ymm10, %ymm16
vporq %ymm8, %ymm10, %ymm17
vpor %ymm9, %ymm10, %ymm10
vpcmpleuq %ymm1, %ymm10, %k0
vpcmpleuq %ymm1, %ymm17, %k1
kshiftlb $0x4, %k1, %k1
korb %k1, %k0, %k0
vpcmpleuq %ymm1, %ymm16, %k1
vpcmpleuq %ymm1, %ymm15, %k2
kshiftlb $0x4, %k2, %k2
korb %k2, %k1, %k1
kunpckbw %k0, %k1, %k0
vpcmpleuq %ymm1, %ymm14, %k1
vpcmpleuq %ymm1, %ymm13, %k2
kshiftlb $0x4, %k2, %k2
korb %k2, %k1, %k1
vpcmpleuq %ymm1, %ymm12, %k2
vpcmpleuq %ymm1, %ymm11, %k3
kshiftlb $0x4, %k3, %k3
korb %k3, %k2, %k2
kunpckbw %k1, %k2, %k1
kunpckwd %k0, %k1, %k1
vmovdqu8 0x40(%rsp,%rcx), %ymm11 {%k1} {z}
vmovdqa %ymm0, %ymm10
vmovdqu8 (%rdx,%rcx), %ymm0 {%k1} {z}
vpternlogq $0xde, %ymm11, %ymm10, %ymm0
addq $0x20, %rcx
cmpq %rcx, %rax
jne 0x4488
vmovdqu8 %ymm0, %ymm10 {%k1}
vextracti128 $0x1, %ymm10, %xmm0
vpor %xmm0, %xmm10, %xmm0
vpshufd $0xee, %xmm0, %xmm1     # xmm1 = xmm0[2,3,2,3]
vpor %xmm1, %xmm0, %xmm0
vpsrlq $0x20, %xmm0, %xmm1
vpor %xmm1, %xmm0, %xmm0
vpsrld $0x10, %xmm0, %xmm1
vpor %xmm1, %xmm0, %xmm0
vpsrlw $0x8, %xmm0, %xmm1
vpor %xmm1, %xmm0, %xmm0
vpextrb $0x0, %xmm0, %r13d
orl (%rsp), %r13d
movl %r13d, %eax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
vzeroupper
retq
nopl (%rax)