// File: /workspace/github_c_makefile_star2_O1/janmojzis[P]mcencrypt/poly1305.c
// Function: poly1305_final
void poly1305_final(poly1305_ctx *ctx, unsigned char *o) {

    unsigned long long f;
    unsigned long c, mask;
    unsigned long h0 = ctx->h[0];
    unsigned long h1 = ctx->h[1];
    unsigned long h2 = ctx->h[2];
    unsigned long h3 = ctx->h[3];
    unsigned long h4 = ctx->h[4];
    unsigned long r0 = ctx->r[0];
    unsigned long r1 = ctx->r[1];
    unsigned long r2 = ctx->r[2];
    unsigned long r3 = ctx->r[3];
    unsigned long r4 = ctx->r[4];

    /* fully carry h */
                 c = h1 >> 26; h1 = h1 & 0x3ffffff;
    h2 +=     c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
    h3 +=     c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
    h4 +=     c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
    h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
    h1 +=     c;

    /* compute h + -p */
    r0 = h0 + 5; c = r0 >> 26; r0 &= 0x3ffffff;
    r1 = h1 + c; c = r1 >> 26; r1 &= 0x3ffffff;
    r2 = h2 + c; c = r2 >> 26; r2 &= 0x3ffffff;
    r3 = h3 + c; c = r3 >> 26; r3 &= 0x3ffffff;
    r4 = h4 + c - (1 << 26);

    /* select h if h < p, or h + -p if h >= p */
    mask = (r4 >> ((sizeof(unsigned long) * 8) - 1)) - 1;
    r0 &= mask;
    r1 &= mask;
    r2 &= mask;
    r3 &= mask;
    r4 &= mask;
    mask = ~mask;
    h0 = (h0 & mask) | r0;
    h1 = (h1 & mask) | r1;
    h2 = (h2 & mask) | r2;
    h3 = (h3 & mask) | r3;
    h4 = (h4 & mask) | r4;

    /* h = h % (2^128) */
    h0 = ((h0      ) | (h1 << 26)) & 0xffffffff;
    h1 = ((h1 >>  6) | (h2 << 20)) & 0xffffffff;
    h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
    h3 = ((h3 >> 18) | (h4 <<  8)) & 0xffffffff;

    /* mac = (h + pad) % (2^128) */
    f = (unsigned long long)h0 + ctx->pad[0]            ; h0 = (unsigned long)f;
    f = (unsigned long long)h1 + ctx->pad[1] + (f >> 32); h1 = (unsigned long)f;
    f = (unsigned long long)h2 + ctx->pad[2] + (f >> 32); h2 = (unsigned long)f;
    f = (unsigned long long)h3 + ctx->pad[3] + (f >> 32); h3 = (unsigned long)f;

    pack(o +  0, h0);
    pack(o +  4, h1);
    pack(o +  8, h2);
    pack(o + 12, h3);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
movq 0x8(%rdi), %rdx
movq %rdx, %rcx
shrq $0x1a, %rcx
andl $0x3ffffff, %edx        # imm = 0x3FFFFFF
addq 0x10(%rdi), %rcx
movq %rcx, %rax
shrq $0x1a, %rax
movl $0x3ffffff, %r11d       # imm = 0x3FFFFFF
andl %r11d, %ecx
addq 0x18(%rdi), %rax
movq %rax, %r12
shrq $0x1a, %r12
andl %r11d, %eax
addq 0x20(%rdi), %r12
movq %r12, %r8
shrq $0x1a, %r8
leaq (%r8,%r8,4), %rbx
addq (%rdi), %rbx
movq %rbx, %r15
shrq $0x1a, %r15
addq %rdx, %r15
andl %r11d, %ebx
leal 0x5(%rbx), %ebp
movl %ebp, %edx
shrl $0x1a, %edx
addq %r15, %rdx
movq %rdx, %r13
shrq $0x1a, %r13
addl %ecx, %r13d
movl %r13d, %r14d
shrl $0x1a, %r14d
addl %eax, %r14d
movl %r14d, %r9d
shrl $0x1a, %r9d
movq %r12, %r8
orq $-0x4000000, %r8        # imm = 0xFC000000
addq %r9, %r8
movq %r8, %r9
sarq $0x3f, %r9
movq %r8, %r10
shrq $0x3f, %r10
decl %r10d
andl %r10d, %r11d
andl %r11d, %ebp
andl %r11d, %edx
andl %r11d, %r13d
andl %r14d, %r11d
andl %r9d, %ebx
orl %ebp, %ebx
andl %r9d, %ecx
andl %r9d, %eax
movq %r9, %r14
andq %r15, %r14
orq %rdx, %r14
orl %r13d, %ecx
orl %r11d, %eax
movl %r14d, %edx
shll $0x1a, %edx
orl %ebx, %edx
shrq $0x6, %r14
movl %ecx, %r11d
shll $0x14, %r11d
orl %r11d, %r14d
shrl $0xc, %ecx
movl %eax, %r11d
shrl $0x12, %eax
addq 0x78(%rdi), %rdx
addq 0x80(%rdi), %r14
addq 0x88(%rdi), %rcx
addq 0x90(%rdi), %rax
movb %dl, (%rsi)
movb %dh, 0x1(%rsi)
movl %edx, %edi
shrl $0x10, %edi
movb %dil, 0x2(%rsi)
movq %rdx, %rbx
shrl $0x18, %edx
movb %dl, 0x3(%rsi)
shrq $0x20, %rbx
addq %r14, %rbx
movq %rbx, %rdx
movb %bl, 0x4(%rsi)
movb %bh, 0x5(%rsi)
movl %ebx, %edi
shrl $0x10, %edi
movb %dil, 0x6(%rsi)
shrl $0x18, %ebx
movb %bl, 0x7(%rsi)
shll $0xe, %r11d
shrq $0x20, %rdx
addq %r11, %rcx
addq %rdx, %rcx
movq %rcx, %rdx
movb %cl, 0x8(%rsi)
movb %ch, 0x9(%rsi)
movl %ecx, %edi
shrl $0x10, %edi
movb %dil, 0xa(%rsi)
shrl $0x18, %ecx
movb %cl, 0xb(%rsi)
andl %r9d, %r12d
andl %r10d, %r8d
orl %r8d, %r12d
shll $0x8, %r12d
shrq $0x20, %rdx
addq %r12, %rax
addq %rdx, %rax
movb %al, 0xc(%rsi)
movb %ah, 0xd(%rsi)
movl %eax, %ecx
shrl $0x10, %ecx
movb %cl, 0xe(%rsi)
shrl $0x18, %eax
movb %al, 0xf(%rsi)
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq