// File: /workspace/github_cpp_makefile_star2_O3/Jumperr-labs[P]at25sf081/AT25SF081.cpp
// Function: AT25SF081::Main()
void AT25SF081::Main() {
    while (!should_stop_) {
        uint8_t opcode = 0;
        if (spi_slave_->Transmit(&opcode, nullptr, 1) == 0) {
            continue;
        }

        switch (opcode) {
            case (OP_READ_ARRAY_0B): {
                ReadArray(true);
                break;
            }

            case (OP_READ_ARRAY_03): {
                ReadArray(false);
                break;
            }

            case (OP_BYTE_OR_PAGE_PROGRAM): {
                ByteOrPageProgram();
                break;
            }

            case (OP_WRITE_ENABLE): {
                WriteEnable();
                break;
            }

            case (OP_WRITE_DISABLE): {
                WriteDisable();
                break;
            }

            case (OP_BLOCK_ERASE_4KB): {
                BlockErase(1U << 12);
                break;
            }

            case (OP_BLOCK_ERASE_32KB): {
                BlockErase(1U << 15);
                break;
            }

            case (OP_BLOCK_ERASE_64KB): {
                BlockErase(1U << 16);
                break;
            }

            case (OP_CHIP_ERASE_60): {
                ChipErase();
                break;
            }

            case (OP_CHIP_ERASE_C7): {
                ChipErase();
                break;
            }

            case (OP_READ_STATUS_REGISTER_BYTE_1): {
                ReadStatusRegister(STATUS_REGISTER_BYTE_1);
                break;
            }

            case (OP_READ_STATUS_REGISTER_BYTE_2): {
                ReadStatusRegister(STATUS_REGISTER_BYTE_2);
                break;
            }

            case (OP_READ_MANUFACTURER_AND_DEVICE_ID): {
                ReadManufacturerAndDeviceId();
                break;
            }

            case (OP_READ_DEVICE_ID): {
                ReadDeviceId();
                break;
            }

            default: {
                std::cerr << "AT25SF081: [Warning] Unsupported opcode 0x" << std::hex << (int) opcode << std::dec << std::endl;
                throw std::logic_error("AT25SF081: Unsupported opcode " + std::to_string(opcode));
            }
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x50, %rsp
cmpb $0x0, 0x100018(%rdi)
jne 0x49ed
movq %rdi, %rbx
leaq 0xf(%rsp), %r14
leaq 0x2756(%rip), %r12      # 0x7000
leaq 0x5987(%rip), %r15      # 0xa238
movb $0x0, 0xf(%rsp)
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movl $0x1, %ecx
movq %r14, %rsi
xorl %edx, %edx
callq *(%rax)
testq %rax, %rax
je 0x49e0
movzbl 0xf(%rsp), %eax
cmpl $0x34, %eax
jg 0x48fe
leal -0x2(%rax), %ecx
cmpl $0x9, %ecx
ja 0x497d
movslq (%r12,%rcx,4), %rax
addq %r12, %rax
jmpq *%rax
movq %rbx, %rdi
callq 0x41f0
jmp 0x49e0
cmpl $0x8f, %eax
jle 0x4942
cmpl $0xc6, %eax
jg 0x495a
cmpl $0x90, %eax
je 0x49c9
cmpl $0x9f, %eax
jne 0x49fa
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movl $0x3, %ecx
xorl %esi, %esi
movq %r15, %rdx
callq *(%rax)
movq %rbx, %rdi
callq 0x4250
jmp 0x49e0
cmpl $0x35, %eax
je 0x49ba
cmpl $0x52, %eax
je 0x49d3
cmpl $0x60, %eax
je 0x4973
jmp 0x49fa
cmpl $0xc7, %eax
je 0x4973
cmpl $0xd8, %eax
jne 0x49fa
movl $0x10000, %esi          # imm = 0x10000
jmp 0x49d8
movq %rbx, %rdi
callq 0x4220
jmp 0x49e0
cmpl $0x20, %eax
jne 0x49fa
movl $0x1000, %esi           # imm = 0x1000
jmp 0x49d8
movq %rbx, %rdi
xorl %esi, %esi
jmp 0x49c2
movq %rbx, %rdi
callq 0x41b0
jmp 0x49e0
movq %rbx, %rdi
callq 0x4430
jmp 0x49e0
movq %rbx, %rdi
xorl %esi, %esi
jmp 0x49b3
movq %rbx, %rdi
movl $0x1, %esi
callq 0x4180
jmp 0x49e0
movq %rbx, %rdi
movl $0x1, %esi
callq 0x4100
jmp 0x49e0
movq %rbx, %rdi
callq 0x43d0
jmp 0x49e0
movl $0x8000, %esi           # imm = 0x8000
movq %rbx, %rdi
callq 0x4060
cmpb $0x1, 0x100018(%rbx)
jne 0x48b1
addq $0x50, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
movq 0x55ef(%rip), %rbx      # 0x9ff0
leaq 0x2640(%rip), %rsi      # 0x7048
movl $0x2a, %edx
movq %rbx, %rdi
callq 0x4280
movq (%rbx), %rax
movq -0x18(%rax), %rax
movl 0x18(%rbx,%rax), %ecx
andl $-0x4b, %ecx
orl $0x8, %ecx
movl %ecx, 0x18(%rbx,%rax)
movzbl 0xf(%rsp), %esi
movq %rbx, %rdi
callq 0x4400
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
movl 0x18(%rax,%rcx), %edx
andl $-0x4b, %edx
orl $0x2, %edx
movl %edx, 0x18(%rax,%rcx)
movq %rax, %rdi
callq 0x4110
movl $0x10, %edi
callq 0x4120
movq %rax, %rbx
movzbl 0xf(%rsp), %esi
leaq 0x10(%rsp), %rdi
callq 0x42d0
leaq 0x25fc(%rip), %rsi      # 0x7073
leaq 0x30(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x43e0
movb $0x1, %bpl
leaq 0x30(%rsp), %rsi
movq %rbx, %rdi
callq 0x4360
xorl %ebp, %ebp
movq 0x5531(%rip), %rsi      # 0x9fd0
movq 0x5512(%rip), %rdx      # 0x9fb8
movq %rbx, %rdi
callq 0x43f0
movq %rax, %r14
leaq 0x40(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x4acc
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x4240
leaq 0x20(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x4ae7
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x4240
testb %bpl, %bpl
jne 0x4b11
jmp 0x4b19
movq %rax, %r14
leaq 0x20(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x4b11
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x4240
jmp 0x4b11
movq %rax, %r14
movq %rbx, %rdi
callq 0x41a0
movq %r14, %rdi
callq 0x4410
nop