// File: occivink[P]pyct/monocypher.cpp
// Function: crypto_blake2b_update
void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
                           const u8 *message, size_t message_size)
{
    // Align ourselves with block boundaries
    // The block that may result is not compressed yet
    size_t aligned = MIN(align(ctx->input_idx, 128), message_size);
    FOR (i, 0, aligned) {
        blake2b_set_input(ctx, *message, ctx->input_idx);
        ctx->input_idx++;
        message++;
        message_size--;
    }

    // Process the message block by block
    // The last block is not compressed yet.
    size_t nb_blocks = message_size >> 7;
    FOR (i, 0, nb_blocks) {
        if (ctx->input_idx == 128) {
            blake2b_compress(ctx, 0);
        }
        load64_le_buf(ctx->input, message, 16);
        message += 128;
        ctx->input_idx = 128;
    }
    message_size &= 127;

    // Fill remaining bytes (not the whole buffer)
    // The last block is never fully filled
    FOR (i, 0, message_size) {
        if (ctx->input_idx == 128) {
            blake2b_compress(ctx, 0);
            ctx->input_idx = 0;
        }
        blake2b_set_input(ctx, message[i], ctx->input_idx);
        ctx->input_idx++;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq 0xd0(%rax), %rdi
movl $0x80, %esi
callq 0x4750
cmpq -0x18(%rbp), %rax
ja 0x4eba
movq -0x8(%rbp), %rax
movq 0xd0(%rax), %rdi
movl $0x80, %esi
callq 0x4750
movq %rax, -0x48(%rbp)
jmp 0x4ec2
movq -0x18(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movq -0x28(%rbp), %rax
cmpq -0x20(%rbp), %rax
jae 0x4f35
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movb (%rax), %al
movq -0x8(%rbp), %rcx
movq 0xd0(%rcx), %rdx
movzbl %al, %esi
callq 0x5050
movq -0x8(%rbp), %rax
movq 0xd0(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0xd0(%rax)
movq -0x10(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x10(%rbp)
movq -0x18(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x18(%rbp)
movq -0x28(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x4ed2
movq -0x18(%rbp), %rax
shrq $0x7, %rax
movq %rax, -0x30(%rbp)
movq $0x0, -0x38(%rbp)
movq -0x38(%rbp), %rax
cmpq -0x30(%rbp), %rax
jae 0x4fb0
movq -0x8(%rbp), %rax
cmpq $0x80, 0xd0(%rax)
jne 0x4f6f
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0x50e0
movq -0x8(%rbp), %rdi
addq $0x50, %rdi
movq -0x10(%rbp), %rsi
movl $0x10, %edx
callq 0x4de0
movq -0x10(%rbp), %rax
addq $0x80, %rax
movq %rax, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq $0x80, 0xd0(%rax)
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x4f49
movq -0x18(%rbp), %rax
andq $0x7f, %rax
movq %rax, -0x18(%rbp)
movq $0x0, -0x40(%rbp)
movq -0x40(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0x503f
movq -0x8(%rbp), %rax
cmpq $0x80, 0xd0(%rax)
jne 0x4ff9
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0x50e0
movq -0x8(%rbp), %rax
movq $0x0, 0xd0(%rax)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq -0x40(%rbp), %rcx
movb (%rax,%rcx), %al
movq -0x8(%rbp), %rcx
movq 0xd0(%rcx), %rdx
movzbl %al, %esi
callq 0x5050
movq -0x8(%rbp), %rax
movq 0xd0(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0xd0(%rax)
movq -0x40(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x40(%rbp)
jmp 0x4fc4
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)