// File: simap[P]ecctools/lib/SHA256.cpp
// Function: SHA256::finalize(void*, unsigned long)
void SHA256::finalize(void *hash, size_t len)
{
    // Pad the last chunk.  We may need two padding chunks if there
    // isn't enough room in the first for the padding and length.
    uint8_t *wbytes = (uint8_t *)state.w;
    if (state.chunkSize <= (64 - 9)) {
        wbytes[state.chunkSize] = 0x80;
        memset(wbytes + state.chunkSize + 1, 0x00, 64 - 8 - (state.chunkSize + 1));
        state.w[14] = htobe32((uint32_t)(state.length >> 32));
        state.w[15] = htobe32((uint32_t)state.length);
        processChunk();
    } else {
        wbytes[state.chunkSize] = 0x80;
        memset(wbytes + state.chunkSize + 1, 0x00, 64 - (state.chunkSize + 1));
        processChunk();
        memset(wbytes, 0x00, 64 - 8);
        state.w[14] = htobe32((uint32_t)(state.length >> 32));
        state.w[15] = htobe32((uint32_t)state.length);
        processChunk();
    }

    // Convert the result into big endian and return it.
    for (uint8_t posn = 0; posn < 8; ++posn)
        state.w[posn] = htobe32(state.h[posn]);

    // Copy the hash to the caller's return buffer.
    if (len > 32)
        len = 32;
    memcpy(hash, state.w, len);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x58(%rbp)
movq %rax, %rcx
addq $0x8, %rcx
addq $0x20, %rcx
movq %rcx, -0x20(%rbp)
movzbl 0x70(%rax), %eax
cmpl $0x37, %eax
jg 0x6e6e
movq -0x58(%rbp), %rax
movq -0x20(%rbp), %rcx
movzbl 0x70(%rax), %edx
movb $-0x80, (%rcx,%rdx)
movq -0x20(%rbp), %rdi
movzbl 0x70(%rax), %ecx
movslq %ecx, %rcx
addq %rcx, %rdi
addq $0x1, %rdi
movzbl 0x70(%rax), %ecx
addl $0x1, %ecx
movl $0x38, %eax
subl %ecx, %eax
movslq %eax, %rdx
xorl %esi, %esi
callq 0x1090
movq -0x58(%rbp), %rdi
movq 0x68(%rdi), %rax
shrq $0x20, %rax
movl %eax, -0x24(%rbp)
movl -0x24(%rbp), %eax
shrl $0x18, %eax
andl $0xff, %eax
movl -0x24(%rbp), %ecx
shrl $0x8, %ecx
andl $0xff00, %ecx           # imm = 0xFF00
orl %ecx, %eax
movl -0x24(%rbp), %ecx
shll $0x8, %ecx
andl $0xff0000, %ecx         # imm = 0xFF0000
orl %ecx, %eax
movl -0x24(%rbp), %ecx
shll $0x18, %ecx
andl $0xff000000, %ecx       # imm = 0xFF000000
orl %ecx, %eax
movl %eax, -0x28(%rbp)
movl -0x28(%rbp), %eax
movl %eax, 0x60(%rdi)
movq 0x68(%rdi), %rax
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
shrl $0x18, %eax
andl $0xff, %eax
movl -0x2c(%rbp), %ecx
shrl $0x8, %ecx
andl $0xff00, %ecx           # imm = 0xFF00
orl %ecx, %eax
movl -0x2c(%rbp), %ecx
shll $0x8, %ecx
andl $0xff0000, %ecx         # imm = 0xFF0000
orl %ecx, %eax
movl -0x2c(%rbp), %ecx
shll $0x18, %ecx
andl $0xff000000, %ecx       # imm = 0xFF000000
orl %ecx, %eax
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %eax
movl %eax, 0x64(%rdi)
callq 0x6840
jmp 0x6f58
movq -0x58(%rbp), %rax
movq -0x20(%rbp), %rcx
movzbl 0x70(%rax), %edx
movb $-0x80, (%rcx,%rdx)
movq -0x20(%rbp), %rdi
movzbl 0x70(%rax), %ecx
movslq %ecx, %rcx
addq %rcx, %rdi
addq $0x1, %rdi
movzbl 0x70(%rax), %ecx
addl $0x1, %ecx
movl $0x40, %eax
subl %ecx, %eax
movslq %eax, %rdx
xorl %esi, %esi
callq 0x1090
movq -0x58(%rbp), %rdi
callq 0x6840
movq -0x20(%rbp), %rdi
xorl %esi, %esi
movl $0x38, %edx
callq 0x1090
movq -0x58(%rbp), %rdi
movq 0x68(%rdi), %rax
shrq $0x20, %rax
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
shrl $0x18, %eax
andl $0xff, %eax
movl -0x34(%rbp), %ecx
shrl $0x8, %ecx
andl $0xff00, %ecx           # imm = 0xFF00
orl %ecx, %eax
movl -0x34(%rbp), %ecx
shll $0x8, %ecx
andl $0xff0000, %ecx         # imm = 0xFF0000
orl %ecx, %eax
movl -0x34(%rbp), %ecx
shll $0x18, %ecx
andl $0xff000000, %ecx       # imm = 0xFF000000
orl %ecx, %eax
movl %eax, -0x38(%rbp)
movl -0x38(%rbp), %eax
movl %eax, 0x60(%rdi)
movq 0x68(%rdi), %rax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
shrl $0x18, %eax
andl $0xff, %eax
movl -0x3c(%rbp), %ecx
shrl $0x8, %ecx
andl $0xff00, %ecx           # imm = 0xFF00
orl %ecx, %eax
movl -0x3c(%rbp), %ecx
shll $0x8, %ecx
andl $0xff0000, %ecx         # imm = 0xFF0000
orl %ecx, %eax
movl -0x3c(%rbp), %ecx
shll $0x18, %ecx
andl $0xff000000, %ecx       # imm = 0xFF000000
orl %ecx, %eax
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
movl %eax, 0x64(%rdi)
callq 0x6840
movb $0x0, -0x41(%rbp)
movzbl -0x41(%rbp), %eax
cmpl $0x8, %eax
jge 0x6fc2
movq -0x58(%rbp), %rax
movzbl -0x41(%rbp), %ecx
movl 0x8(%rax,%rcx,4), %ecx
movl %ecx, -0x48(%rbp)
movl -0x48(%rbp), %ecx
shrl $0x18, %ecx
andl $0xff, %ecx
movl -0x48(%rbp), %edx
shrl $0x8, %edx
andl $0xff00, %edx           # imm = 0xFF00
orl %edx, %ecx
movl -0x48(%rbp), %edx
shll $0x8, %edx
andl $0xff0000, %edx         # imm = 0xFF0000
orl %edx, %ecx
movl -0x48(%rbp), %edx
shll $0x18, %edx
andl $0xff000000, %edx       # imm = 0xFF000000
orl %edx, %ecx
movl %ecx, -0x4c(%rbp)
movl -0x4c(%rbp), %edx
movzbl -0x41(%rbp), %ecx
movl %edx, 0x28(%rax,%rcx,4)
movb -0x41(%rbp), %al
addb $0x1, %al
movb %al, -0x41(%rbp)
jmp 0x6f5c
cmpq $0x20, -0x18(%rbp)
jbe 0x6fd1
movq $0x20, -0x18(%rbp)
movq -0x58(%rbp), %rsi
movq -0x10(%rbp), %rdi
addq $0x8, %rsi
addq $0x20, %rsi
movq -0x18(%rbp), %rdx
callq 0x10b0
addq $0x60, %rsp
popq %rbp
retq