// File: Smattr[P]ibpf/interpreter.cpp
// Function: main
int main(int argc, char **argv) {
    const char *data = nullptr;
    const char *input = nullptr;

    while (true) {
        static struct option opts[] = {
            {"data", required_argument, 0, 'd'},
            {"input", required_argument, 0, 'i'},
            {0, 0, 0, 0},
        };

        int opt_index;
        int c = getopt_long(argc, argv, "d:i:", opts, &opt_index);

        if (c == -1)
            break;

        switch (c) {
            case 'd':
                data = optarg;
                break;

            case 'i':
                input = optarg;
                break;

            default:
                return -1;
        }
    }

    if (data == nullptr || input == nullptr) {
        std::cerr << "usage: " << argv[0] <<
            " --input INPUT_FILE --data DATA_FILE" << std::endl;
        return -1;
    }

    std::vector<char> program;
    try {
        program = read_file(input);
    } catch (std::runtime_error e) {
        std::cerr << "failed to read " << input << std::endl;
        return -1;
    }

    std::vector<char> packet;
    try {
        packet = read_file(data);
    } catch (std::runtime_error e) {
        std::cerr << "failed to read " << data << std::endl;
        return -1;
    }

    Machine m;
    m.load(packet);
    try {
        m.run(program);
    } catch (InterpreterException e) {
        std::cerr << "VM exception: " << e.what() << std::endl;
        return -1;
    }

    std::cout << "result: " << m.ret << std::endl;

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x220, %rsp            # imm = 0x220
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq $0x0, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0x2b8f(%rip), %rdx      # 0x63f6
leaq 0x6902(%rip), %rcx      # 0xa170
leaq -0x24(%rbp), %r8
callq 0x2260
movl %eax, -0x28(%rbp)
cmpl $-0x1, -0x28(%rbp)
jne 0x3882
jmp 0x38cd
movl -0x28(%rbp), %eax
movl %eax, -0x1b4(%rbp)
subl $0x64, %eax
je 0x389f
jmp 0x3892
movl -0x1b4(%rbp), %eax
subl $0x69, %eax
je 0x38af
jmp 0x38bf
movq 0x66f2(%rip), %rax      # 0x9f98
movq (%rax), %rax
movq %rax, -0x18(%rbp)
jmp 0x38cb
movq 0x66e2(%rip), %rax      # 0x9f98
movq (%rax), %rax
movq %rax, -0x20(%rbp)
jmp 0x38cb
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x3d72
jmp 0x3859
cmpq $0x0, -0x18(%rbp)
je 0x38db
cmpq $0x0, -0x20(%rbp)
jne 0x3927
movq 0x6706(%rip), %rdi      # 0x9fe8
leaq 0x2b12(%rip), %rsi      # 0x63fb
callq 0x2140
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq (%rax), %rsi
callq 0x2140
movq %rax, %rdi
leaq 0x2afc(%rip), %rsi      # 0x6403
callq 0x2140
movq %rax, %rdi
movq 0x6672(%rip), %rsi      # 0x9f88
callq 0x2160
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x3d72
leaq -0x40(%rbp), %rdi
callq 0x4630
movq -0x20(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0x3640
jmp 0x393f
leaq -0x40(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x4650
leaq -0x58(%rbp), %rdi
callq 0x45d0
jmp 0x3a3d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
movl -0x64(%rbp), %eax
movl $0x1, %ecx
cmpl %ecx, %eax
jne 0x3d67
movq -0x60(%rbp), %rdi
movq %rdi, -0x1c8(%rbp)
callq 0x2190
movq %rax, %rsi
leaq -0x78(%rbp), %rdi
callq 0x2090
movq -0x1c8(%rbp), %rdi
callq 0x2080
movq 0x6643(%rip), %rdi      # 0x9fe8
leaq 0x2a7c(%rip), %rsi      # 0x6428
callq 0x2140
movq %rax, -0x1c0(%rbp)
jmp 0x39ba
movq -0x1c0(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x2140
movq %rax, -0x1d0(%rbp)
jmp 0x39d3
movq -0x1d0(%rbp), %rdi
movq 0x65a7(%rip), %rsi      # 0x9f88
callq 0x2160
jmp 0x39e8
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x7c(%rbp)
leaq -0x78(%rbp), %rdi
callq 0x22c8
callq 0x2240
jmp 0x3a22
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x78(%rbp), %rdi
callq 0x22c8
callq 0x2240
jmp 0x3a38
jmp 0x3d5c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x3d67
jmp 0x3d67
leaq -0x98(%rbp), %rdi
callq 0x4630
movq -0x18(%rbp), %rsi
leaq -0xb0(%rbp), %rdi
callq 0x3640
jmp 0x3a5b
leaq -0x98(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0x4650
leaq -0xb0(%rbp), %rdi
callq 0x45d0
jmp 0x3b6b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
movl -0x64(%rbp), %eax
movl $0x1, %ecx
cmpl %ecx, %eax
jne 0x3d4e
movq -0x60(%rbp), %rdi
movq %rdi, -0x1e0(%rbp)
callq 0x2190
movq %rax, %rsi
leaq -0xc0(%rbp), %rdi
callq 0x2090
movq -0x1e0(%rbp), %rdi
callq 0x2080
movq 0x651b(%rip), %rdi      # 0x9fe8
leaq 0x2954(%rip), %rsi      # 0x6428
callq 0x2140
movq %rax, -0x1d8(%rbp)
jmp 0x3ae2
movq -0x1d8(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x2140
movq %rax, -0x1e8(%rbp)
jmp 0x3afb
movq -0x1e8(%rbp), %rdi
movq 0x647f(%rip), %rsi      # 0x9f88
callq 0x2160
jmp 0x3b10
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x7c(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x22c8
callq 0x2240
jmp 0x3b50
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x22c8
callq 0x2240
jmp 0x3b66
jmp 0x3d40
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x3d4e
jmp 0x3d4e
leaq -0x168(%rbp), %rdi
callq 0x4690
jmp 0x3b79
leaq -0x180(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0x4720
jmp 0x3b8e
leaq -0x168(%rbp), %rdi
leaq -0x180(%rbp), %rsi
movq %rsi, -0x1f0(%rbp)
callq 0x2420
movq -0x1f0(%rbp), %rdi
callq 0x45d0
leaq -0x198(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x4720
jmp 0x3bc6
leaq -0x168(%rbp), %rdi
leaq -0x198(%rbp), %rsi
callq 0x34f0
jmp 0x3bdb
leaq -0x198(%rbp), %rdi
callq 0x45d0
jmp 0x3ce6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x3c12
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x198(%rbp), %rdi
callq 0x45d0
movl -0x64(%rbp), %eax
movl $0x2, %ecx
cmpl %ecx, %eax
jne 0x3d4e
movq -0x60(%rbp), %rdi
movq %rdi, -0x200(%rbp)
callq 0x2190
movq %rax, %rsi
leaq -0x1b0(%rbp), %rdi
callq 0x4810
movq -0x200(%rbp), %rdi
callq 0x2080
movq 0x6394(%rip), %rdi      # 0x9fe8
leaq 0x27dd(%rip), %rsi      # 0x6438
callq 0x2140
movq %rax, -0x1f8(%rbp)
jmp 0x3c69
leaq -0x1b0(%rbp), %rdi
callq 0x21c0
movq -0x1f8(%rbp), %rdi
movq %rax, %rsi
callq 0x2140
movq %rax, -0x208(%rbp)
jmp 0x3c8d
movq -0x208(%rbp), %rdi
movq 0x62ed(%rip), %rsi      # 0x9f88
callq 0x2160
jmp 0x3ca2
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x7c(%rbp)
leaq -0x1b0(%rbp), %rdi
callq 0x4860
callq 0x2240
jmp 0x3ce2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x1b0(%rbp), %rdi
callq 0x4860
callq 0x2240
jmp 0x3ce4
jmp 0x3d40
jmp 0x3d4e
movq 0x62d3(%rip), %rdi      # 0x9fc0
leaq 0x2753(%rip), %rsi      # 0x6447
callq 0x2140
movq %rax, -0x210(%rbp)
jmp 0x3d02
movq -0x210(%rbp), %rdi
movl -0x168(%rbp), %esi
callq 0x21b0
movq %rax, -0x218(%rbp)
jmp 0x3d1d
movq -0x218(%rbp), %rdi
movq 0x625d(%rip), %rsi      # 0x9f88
callq 0x2160
jmp 0x3d32
movl $0x0, -0x4(%rbp)
movl $0x1, -0x7c(%rbp)
leaq -0x98(%rbp), %rdi
callq 0x45d0
jmp 0x3d5c
leaq -0x98(%rbp), %rdi
callq 0x45d0
jmp 0x3d67
leaq -0x40(%rbp), %rdi
callq 0x45d0
jmp 0x3d72
leaq -0x40(%rbp), %rdi
callq 0x45d0
jmp 0x3d7e
movl -0x4(%rbp), %eax
addq $0x220, %rsp            # imm = 0x220
popq %rbp
retq
movq -0x60(%rbp), %rdi
callq 0x2280
movq %rax, %rdi
callq 0x4680
nop