// File: protonpopsicle[P]lang/src/vm/VMachine.cpp
// Function: main
int main(int argc, char *argv[]) {
    if (argv[1] == 0) {
        fprintf(stderr, "missing argument 1: filename\n");
        return(0);
    }
    
    /*
    * Read bytecode
    */
    char *file = argv[1];
    FILE *fp = fopen(file, "r");
    if (fp == 0) {
        fprintf(stderr, "error opening file\n");
        return(0);
    }
    
    int boolCount, intCount, strCount, litCount, opCount;
    
    if (fscanf(fp, "%i %i %i %i %i:", &boolCount, &intCount, &strCount, &litCount, &opCount) != 5) {
        fprintf(stderr, "error reading bytecode");
        return 0;
    }
    
    strCount = strCount + litCount + 1; // string vars + string literals + temp string
    
    char bools[boolCount];
    int ints[intCount];
    std::vector<std::string> strings(strCount);
    Op ops[opCount];
    
    char c;
    for (int i = 0; i < litCount; i++) {
        c = fgetc(fp);
        while (c != ':') {
            strings[i] += c;
            c = fgetc(fp);
        }
    }

    for (int i = 0; i < opCount; i++) {
        fscanf(fp, "%hi %i ", &ops[i].opcode, &ops[i].operand);
    }
    
    fclose(fp);
    
    /*
    * Print debug information
    */
    /*  
    printf("\nBools...\n");
    for (int i = 0; i < boolCount; i++) {
        printf("%i: %i\n", i, bools[i]);
    }
    
    printf("\nInts...\n");
    for (int i = 0; i < intCount; i++) {
        printf("%i: %i\n", i, ints[i]);
    }
    
    printf("\nStrings...\n");
    for (int i = 0; i < strCount; i++) {
        printf("%i: %s\n", i, strings[i].c_str());
    }
    
    printf("\nOpcodes...\n");
    for (int i = 0; i < opCount; i++) {
        std::string opcode;
        
        switch (ops[i].opcode) {
            case OP_PUSH:
                opcode = "OP_PUSH";
                break;
            case OP_GET_BOOL:
                opcode = "OP_GET_BOOL";
                break;
            case OP_GET_INT:
                opcode = "OP_GET_INT";
                break;
            case OP_GET_STRING:
                opcode = "OP_GET_STRING";
                break;
            case OP_ASSIGN_BOOL:
                opcode = "OP_ASSIGN_BOOL";
                break;
            case OP_ASSIGN_INT:
                opcode = "OP_ASSIGN_INT";
                break;
            case OP_ASSIGN_STRING:
                opcode = "OP_ASSIGN_STRING";
                break;
            case OP_ADD:
                opcode = "OP_ADD";
                break;
            case OP_SUBTRACT:
                opcode = "OP_SUBTRACT";
                break;
            case OP_MULTIPLY:
                opcode = "OP_MULTIPLY";
                break;
            case OP_DIVIDE:
                opcode = "OP_DIVIDE";
                break;
            case OP_CAT_STRING:
                opcode = "OP_CAT_STRING";
                break;
            case OP_CAT_STRING_INT:
                opcode = "OP_CAT_STRING_INT";
                break;
            case OP_CAT_INT_STRING:
                opcode = "OP_CAT_INT_STRING";
                break;
            case OP_PRINT_INT:
                opcode = "OP_PRINT_INT";
                break;
            case OP_PRINT_STRING:
                opcode = "OP_PRINT_STRING";
                break;
            case OP_JUMP:
                opcode = "OP_JUMP";
                break;
            case OP_JUMP_IF_FALSE:
                opcode = "OP_JUMP_IF_FALSE";
                break;
            case OP_L:
                opcode = "OP_L";
                break;
            case OP_G:
                opcode = "OP_G";
                break;
            case OP_LE:
                opcode = "OP_LE";
                break;
            case OP_GE:
                opcode = "OP_GE";
                break;
            case OP_EQ:
                opcode = "OP_EQ";
                break;
            case OP_NE:
                opcode = "OP_NE";
                break;
            case OP_AND:
                opcode = "OP_AND";
                break;
            case OP_OR:
                opcode = "OP_OR";
                break;
            default:
                opcode = "undefined";
        }
        
        printf("%i: %s %i\n", i, opcode.c_str(), ops[i].operand);
    }
    printf("\n");
    */  
    /*
    * Run program
    */
    bool a, b;
    int x, y;
    std::string strA, strB;
    char intBuffer[12];
    Stack stack(2);
    
    for (int i = 0; i < opCount; i++) {
        switch (ops[i].opcode) {
            case OP_PUSH:
                stack.push(i, ops[i].operand);
                break;
            case OP_GET_BOOL:
                stack.push(i, bools[ops[i].operand]);
                break;
            case OP_GET_INT:
                stack.push(i,ints[ops[i].operand]);
                break;
            case OP_GET_STRING:
                // offset by litCount because variables come after literals in array
                stack.push(i, ops[i].operand + litCount);
                break;
            case OP_ASSIGN_BOOL:
                bools[ops[i].operand] = stack.pop();
                break;
            case OP_ASSIGN_INT:
                ints[ops[i].operand] = stack.pop();
                break;
            case OP_ASSIGN_STRING:
                strings[ops[i].operand + litCount] = strings[stack.pop()];
                break;
            case OP_ADD:
                y = stack.pop(); 
                x = stack.pop();
                stack.push(i, x + y);
                break;
            case OP_SUBTRACT:
                y = stack.pop();
                x = stack.pop();
                stack.push(i, x - y);
                break;
            case OP_MULTIPLY:
                y = stack.pop();
                x = stack.pop();
                stack.push(i, x * y);
                break;
            case OP_DIVIDE:
                y = stack.pop();
                x = stack.pop();
                stack.push(i, x / y);
                break;
            case OP_CAT_STRING:
                strB = strings[stack.pop()];
                strA = strings[stack.pop()];
                strings[strCount - 1] = strA + strB;
                stack.push(i, strCount - 1);
                break;
            case OP_CAT_STRING_INT:
                x = stack.pop();
                strA = strings[stack.pop()];
                snprintf(intBuffer, sizeof(intBuffer), "%i", x);
                strings[strCount - 1] = strA.append(intBuffer);
                stack.push(i, strCount - 1);
                break;
            case OP_CAT_INT_STRING:
                strA = strings[stack.pop()];
                x = stack.pop();
                snprintf(intBuffer, sizeof(intBuffer), "%i", x);
                strings[strCount - 1] = strA.insert(0, intBuffer);
                stack.push(i, strCount - 1);
                break;
            case OP_PRINT_INT:
                x = stack.pop();
                printf("%i", x);
                break;
            case OP_JUMP:
                i += ops[i].operand - 1;
                break;
            case OP_JUMP_IF_FALSE:
                if (!stack.pop()) {
                    i += ops[i].operand;
                }
                break;
            case OP_PRINT_STRING:
                strA = strings[stack.pop()];
                printf("%s", strA.c_str());
                break;
            case OP_L:
                y = stack.pop();
                x = stack.pop();
                stack.push(i, x < y);
                break;
            case OP_G:
                y = stack.pop();
                x = stack.pop();
                stack.push(i, x > y);
                break;
            case OP_LE:
                y = stack.pop();
                x = stack.pop();
                stack.push(i, x <= y);
                break;
            case OP_GE:
                y = stack.pop();
                x = stack.pop();
                stack.push(i, x >= y);
                break;
            case OP_EQ:
                y = stack.pop();
                x = stack.pop();
                stack.push(i, x == y);
                break;
            case OP_NE:
                y = stack.pop();
                x = stack.pop();
                stack.push(i, x != y);
                break;
            case OP_AND:
                b = stack.pop();
                a = stack.pop();
                stack.push(i, a && b);
                break;
            case OP_OR:
                b = stack.pop();
                a = stack.pop();
                stack.push(i, b || a);
                break;
        }
    }
    
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x250, %rsp            # imm = 0x250
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x8(%rax)
jne 0x2438
movq 0x3bc5(%rip), %rax      # 0x5fe0
movq (%rax), %rdi
leaq 0x1c4f(%rip), %rsi      # 0x4074
movb $0x0, %al
callq 0x2170
movl $0x0, -0x4(%rbp)
jmp 0x3289
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
leaq 0x1c43(%rip), %rsi      # 0x4092
callq 0x2130
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
jne 0x2483
movq 0x3b7a(%rip), %rax      # 0x5fe0
movq (%rax), %rdi
leaq 0x1c24(%rip), %rsi      # 0x4094
movb $0x0, %al
callq 0x2170
movl $0x0, -0x4(%rbp)
jmp 0x3289
movq -0x20(%rbp), %rdi
leaq 0x1c1a(%rip), %rsi      # 0x40a8
leaq -0x24(%rbp), %rdx
leaq -0x28(%rbp), %rcx
leaq -0x2c(%rbp), %r8
leaq -0x30(%rbp), %r9
leaq -0x34(%rbp), %rax
subq $0x10, %rsp
movq %rax, (%rsp)
movb $0x0, %al
callq 0x21d0
addq $0x10, %rsp
cmpl $0x5, %eax
je 0x24de
movq 0x3b1f(%rip), %rax      # 0x5fe0
movq (%rax), %rdi
leaq 0x1bed(%rip), %rsi      # 0x40b8
movb $0x0, %al
callq 0x2170
movl $0x0, -0x4(%rbp)
jmp 0x3289
movl -0x2c(%rbp), %edx
movl -0x30(%rbp), %eax
movl %eax, %ecx
movl %edx, %eax
leal 0x1(%rax,%rcx), %eax
movl %eax, -0x2c(%rbp)
movl -0x24(%rbp), %eax
movq %rsp, %rcx
movq %rcx, -0x40(%rbp)
movq %rax, %rdx
addq $0xf, %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x148(%rbp)
movq %rcx, %rsp
movq %rax, -0x48(%rbp)
movl -0x28(%rbp), %eax
leaq 0xf(,%rax,4), %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x140(%rbp)
movq %rcx, %rsp
movq %rax, -0x50(%rbp)
movslq -0x2c(%rbp), %rax
movq %rax, -0x138(%rbp)
leaq -0x69(%rbp), %rdi
movq %rdi, -0x130(%rbp)
callq 0x32a0
movq -0x138(%rbp), %rsi
movq -0x130(%rbp), %rdx
leaq -0x68(%rbp), %rdi
callq 0x32c0
jmp 0x256f
leaq -0x69(%rbp), %rdi
callq 0x3330
movl -0x34(%rbp), %eax
leaq 0xf(,%rax,8), %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x150(%rbp)
movq %rcx, %rsp
movq %rax, -0x88(%rbp)
movl $0x0, -0x90(%rbp)
movl -0x90(%rbp), %eax
cmpl -0x30(%rbp), %eax
jge 0x266d
movq -0x20(%rbp), %rdi
callq 0x2190
movl %eax, -0x154(%rbp)
jmp 0x25c8
movl -0x154(%rbp), %eax
movb %al, -0x89(%rbp)
movsbl -0x89(%rbp), %eax
cmpl $0x3a, %eax
je 0x2657
movsbl -0x89(%rbp), %eax
movl %eax, -0x158(%rbp)
movslq -0x90(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x3350
movl -0x158(%rbp), %esi
movq %rax, %rdi
callq 0x20e0
jmp 0x260d
movq -0x20(%rbp), %rdi
callq 0x2190
movl %eax, -0x15c(%rbp)
jmp 0x261e
movl -0x15c(%rbp), %eax
movb %al, -0x89(%rbp)
jmp 0x25d4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x69(%rbp), %rdi
callq 0x3330
jmp 0x3291
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0x327e
jmp 0x2659
movl -0x90(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x90(%rbp)
jmp 0x25a8
movl $0x0, -0x94(%rbp)
movl -0x94(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0x26c0
movq -0x150(%rbp), %rax
movq -0x20(%rbp), %rdi
movslq -0x94(%rbp), %rcx
leaq (%rax,%rcx,8), %rdx
leaq 0x4(%rax,%rcx,8), %rcx
leaq 0x1a2b(%rip), %rsi      # 0x40cf
xorl %eax, %eax
callq 0x21d0
jmp 0x26ad
jmp 0x26af
movl -0x94(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x94(%rbp)
jmp 0x2677
movq -0x20(%rbp), %rdi
callq 0x2100
jmp 0x26cb
leaq -0xc0(%rbp), %rdi
callq 0x2160
leaq -0xe0(%rbp), %rdi
callq 0x2160
leaq -0x100(%rbp), %rdi
movl $0x2, %esi
callq 0x2300
jmp 0x26f6
movl $0x0, -0x104(%rbp)
movl -0x104(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0x3229
movq -0x150(%rbp), %rax
movslq -0x104(%rbp), %rcx
movswl (%rax,%rcx,8), %eax
movl %eax, %ecx
movq %rcx, -0x168(%rbp)
subl $0x1b, %eax
ja 0x3213
movq -0x168(%rbp), %rax
leaq 0x18c3(%rip), %rcx      # 0x4004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0x3266
movq -0x150(%rbp), %rax
movslq -0x104(%rbp), %rcx
movl %ecx, %esi
movl 0x4(%rax,%rcx,8), %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x277d
jmp 0x3213
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x23c0
jmp 0x3266
movq -0x148(%rbp), %rax
movq -0x150(%rbp), %rcx
movslq -0x104(%rbp), %rdx
movl %edx, %esi
movslq 0x4(%rcx,%rdx,8), %rcx
movsbl (%rax,%rcx), %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x27cd
jmp 0x3213
movq -0x140(%rbp), %rax
movq -0x150(%rbp), %rcx
movslq -0x104(%rbp), %rdx
movl %edx, %esi
movslq 0x4(%rcx,%rdx,8), %rcx
movl (%rax,%rcx,4), %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x27ff
jmp 0x3213
movq -0x150(%rbp), %rax
movslq -0x104(%rbp), %rcx
movl %ecx, %esi
movl 0x4(%rax,%rcx,8), %edx
movl -0x30(%rbp), %eax
addl %eax, %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x282b
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x16c(%rbp)
jmp 0x2844
movq -0x148(%rbp), %rax
movq -0x150(%rbp), %rcx
movl -0x16c(%rbp), %edx
movslq -0x104(%rbp), %rsi
movslq 0x4(%rcx,%rsi,8), %rcx
movb %dl, (%rax,%rcx)
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x170(%rbp)
jmp 0x2880
movq -0x140(%rbp), %rax
movl -0x170(%rbp), %edx
movq -0x150(%rbp), %rcx
movslq -0x104(%rbp), %rsi
movslq 0x4(%rcx,%rsi,8), %rcx
movl %edx, (%rax,%rcx,4)
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x174(%rbp)
jmp 0x28bc
movl -0x174(%rbp), %eax
movslq %eax, %rsi
leaq -0x68(%rbp), %rdi
movq %rdi, -0x188(%rbp)
callq 0x3350
movq -0x188(%rbp), %rdi
movq %rax, %rcx
movq -0x150(%rbp), %rax
movq %rcx, -0x180(%rbp)
movslq -0x104(%rbp), %rcx
movl 0x4(%rax,%rcx,8), %eax
movl -0x30(%rbp), %ecx
addl %ecx, %eax
movslq %eax, %rsi
callq 0x3350
movq -0x180(%rbp), %rsi
movq %rax, %rdi
callq 0x2040
jmp 0x2916
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x18c(%rbp)
jmp 0x292f
movl -0x18c(%rbp), %eax
movl %eax, -0xa0(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x190(%rbp)
jmp 0x294f
movl -0x190(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x104(%rbp), %esi
movl -0x9c(%rbp), %edx
movl -0xa0(%rbp), %eax
addl %eax, %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x297d
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x194(%rbp)
jmp 0x2996
movl -0x194(%rbp), %eax
movl %eax, -0xa0(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x198(%rbp)
jmp 0x29b6
movl -0x198(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x104(%rbp), %esi
movl -0x9c(%rbp), %edx
movl -0xa0(%rbp), %eax
subl %eax, %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x29e4
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x19c(%rbp)
jmp 0x29fd
movl -0x19c(%rbp), %eax
movl %eax, -0xa0(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x1a0(%rbp)
jmp 0x2a1d
movl -0x1a0(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x104(%rbp), %esi
movl -0x9c(%rbp), %edx
movl -0xa0(%rbp), %eax
imull %eax, %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x2a4c
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x1a4(%rbp)
jmp 0x2a65
movl -0x1a4(%rbp), %eax
movl %eax, -0xa0(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x1a8(%rbp)
jmp 0x2a85
movl -0x1a8(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x104(%rbp), %esi
movl -0x9c(%rbp), %eax
movl -0xa0(%rbp), %ecx
cltd
idivl %ecx
movl %eax, %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x2ab6
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x1ac(%rbp)
jmp 0x2acf
movl -0x1ac(%rbp), %eax
movslq %eax, %rsi
leaq -0x68(%rbp), %rdi
callq 0x3350
movq %rax, %rsi
leaq -0xe0(%rbp), %rdi
callq 0x2040
jmp 0x2af2
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x1b0(%rbp)
jmp 0x2b06
movl -0x1b0(%rbp), %eax
movslq %eax, %rsi
leaq -0x68(%rbp), %rdi
callq 0x3350
movq %rax, %rsi
leaq -0xc0(%rbp), %rdi
callq 0x2040
jmp 0x2b29
leaq -0x128(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
leaq -0xe0(%rbp), %rdx
callq 0x3370
jmp 0x2b45
movl -0x2c(%rbp), %eax
decl %eax
movslq %eax, %rsi
leaq -0x68(%rbp), %rdi
callq 0x3350
movq %rax, %rdi
leaq -0x128(%rbp), %rsi
movq %rsi, -0x1b8(%rbp)
callq 0x2140
movq -0x1b8(%rbp), %rdi
callq 0x20d0
movl -0x104(%rbp), %esi
movl -0x2c(%rbp), %edx
decl %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x2b91
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x1bc(%rbp)
jmp 0x2baa
movl -0x1bc(%rbp), %eax
movl %eax, -0x9c(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x1c0(%rbp)
jmp 0x2bca
movl -0x1c0(%rbp), %eax
movslq %eax, %rsi
leaq -0x68(%rbp), %rdi
callq 0x3350
movq %rax, %rsi
leaq -0xc0(%rbp), %rdi
callq 0x2040
jmp 0x2bed
movl -0x9c(%rbp), %ecx
leaq 0x14dd(%rip), %rdx      # 0x40d7
xorl %eax, %eax
leaq -0xec(%rbp), %rdi
movq %rdi, -0x1d0(%rbp)
movl $0xc, %esi
callq 0x21a0
movq -0x1d0(%rbp), %rsi
leaq -0xc0(%rbp), %rdi
callq 0x21e0
movq %rax, -0x1c8(%rbp)
jmp 0x2c30
movl -0x2c(%rbp), %eax
decl %eax
movslq %eax, %rsi
leaq -0x68(%rbp), %rdi
callq 0x3350
movq -0x1c8(%rbp), %rsi
movq %rax, %rdi
callq 0x2040
jmp 0x2c52
movl -0x104(%rbp), %esi
movl -0x2c(%rbp), %edx
decl %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x2c6b
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x1d4(%rbp)
jmp 0x2c84
movl -0x1d4(%rbp), %eax
movslq %eax, %rsi
leaq -0x68(%rbp), %rdi
callq 0x3350
movq %rax, %rsi
leaq -0xc0(%rbp), %rdi
callq 0x2040
jmp 0x2ca7
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x1d8(%rbp)
jmp 0x2cbb
movl -0x1d8(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x9c(%rbp), %ecx
leaq 0x1403(%rip), %rdx      # 0x40d7
xorl %eax, %eax
movl %eax, -0x1e4(%rbp)
leaq -0xec(%rbp), %rdi
movq %rdi, -0x1f0(%rbp)
movl $0xc, %esi
callq 0x21a0
movq -0x1f0(%rbp), %rdx
movl -0x1e4(%rbp), %eax
movl %eax, %esi
leaq -0xc0(%rbp), %rdi
callq 0x2060
movq %rax, -0x1e0(%rbp)
jmp 0x2d18
movl -0x2c(%rbp), %eax
decl %eax
movslq %eax, %rsi
leaq -0x68(%rbp), %rdi
callq 0x3350
movq -0x1e0(%rbp), %rsi
movq %rax, %rdi
callq 0x2040
jmp 0x2d3a
movl -0x104(%rbp), %esi
movl -0x2c(%rbp), %edx
decl %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x2d53
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x1f4(%rbp)
jmp 0x2d6c
movl -0x1f4(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x9c(%rbp), %esi
leaq 0x1352(%rip), %rdi      # 0x40d7
xorl %eax, %eax
callq 0x2050
jmp 0x2d8e
jmp 0x3213
movq -0x150(%rbp), %rax
movslq -0x104(%rbp), %rcx
movl 0x4(%rax,%rcx,8), %eax
subl $0x1, %eax
addl -0x104(%rbp), %eax
movl %eax, -0x104(%rbp)
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x1f8(%rbp)
jmp 0x2dcd
movl -0x1f8(%rbp), %eax
cmpl $0x0, %eax
jne 0x2df6
movq -0x150(%rbp), %rax
movslq -0x104(%rbp), %rcx
movl 0x4(%rax,%rcx,8), %eax
addl -0x104(%rbp), %eax
movl %eax, -0x104(%rbp)
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x1fc(%rbp)
jmp 0x2e0f
movl -0x1fc(%rbp), %eax
movslq %eax, %rsi
leaq -0x68(%rbp), %rdi
callq 0x3350
movq %rax, %rsi
leaq -0xc0(%rbp), %rdi
callq 0x2040
jmp 0x2e32
leaq -0xc0(%rbp), %rdi
callq 0x20a0
movq %rax, %rsi
leaq 0x1292(%rip), %rdi      # 0x40da
xorl %eax, %eax
callq 0x2050
jmp 0x2e51
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x200(%rbp)
jmp 0x2e6a
movl -0x200(%rbp), %eax
movl %eax, -0xa0(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x204(%rbp)
jmp 0x2e8a
movl -0x204(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x104(%rbp), %esi
movl -0x9c(%rbp), %eax
movl -0xa0(%rbp), %ecx
subl %ecx, %eax
setl %al
movzbl %al, %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x2ebe
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x208(%rbp)
jmp 0x2ed7
movl -0x208(%rbp), %eax
movl %eax, -0xa0(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x20c(%rbp)
jmp 0x2ef7
movl -0x20c(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x104(%rbp), %esi
movl -0x9c(%rbp), %eax
movl -0xa0(%rbp), %ecx
subl %ecx, %eax
setg %al
movzbl %al, %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x2f2b
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x210(%rbp)
jmp 0x2f44
movl -0x210(%rbp), %eax
movl %eax, -0xa0(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x214(%rbp)
jmp 0x2f64
movl -0x214(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x104(%rbp), %esi
movl -0x9c(%rbp), %eax
movl -0xa0(%rbp), %ecx
subl %ecx, %eax
setle %al
movzbl %al, %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x2f98
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x218(%rbp)
jmp 0x2fb1
movl -0x218(%rbp), %eax
movl %eax, -0xa0(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x21c(%rbp)
jmp 0x2fd1
movl -0x21c(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x104(%rbp), %esi
movl -0x9c(%rbp), %eax
movl -0xa0(%rbp), %ecx
subl %ecx, %eax
setge %al
movzbl %al, %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x3005
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x220(%rbp)
jmp 0x301e
movl -0x220(%rbp), %eax
movl %eax, -0xa0(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x224(%rbp)
jmp 0x303e
movl -0x224(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x104(%rbp), %esi
movl -0x9c(%rbp), %eax
movl -0xa0(%rbp), %ecx
subl %ecx, %eax
sete %al
movzbl %al, %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x3072
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x228(%rbp)
jmp 0x308b
movl -0x228(%rbp), %eax
movl %eax, -0xa0(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x22c(%rbp)
jmp 0x30ab
movl -0x22c(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x104(%rbp), %esi
movl -0x9c(%rbp), %eax
movl -0xa0(%rbp), %ecx
subl %ecx, %eax
setne %al
movzbl %al, %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x30df
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x230(%rbp)
jmp 0x30f8
movl -0x230(%rbp), %eax
testl %eax, %eax
setne -0x96(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x234(%rbp)
jmp 0x311b
movl -0x234(%rbp), %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, -0x95(%rbp)
movl -0x104(%rbp), %eax
movl %eax, -0x23c(%rbp)
xorl %eax, %eax
testb $0x1, -0x95(%rbp)
movb %al, -0x235(%rbp)
je 0x3158
movb -0x96(%rbp), %al
movb %al, -0x235(%rbp)
movl -0x23c(%rbp), %esi
movb -0x235(%rbp), %al
movzbl %al, %edx
andl $0x1, %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x3178
jmp 0x3213
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x240(%rbp)
jmp 0x3191
movl -0x240(%rbp), %eax
testl %eax, %eax
setne -0x96(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x2390
movl %eax, -0x244(%rbp)
jmp 0x31b4
movl -0x244(%rbp), %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, -0x95(%rbp)
movl -0x104(%rbp), %eax
movl %eax, -0x24c(%rbp)
movb $0x1, %al
testb $0x1, -0x96(%rbp)
movb %al, -0x245(%rbp)
jne 0x31f1
movb -0x95(%rbp), %al
movb %al, -0x245(%rbp)
movl -0x24c(%rbp), %esi
movb -0x245(%rbp), %al
movzbl %al, %edx
andl $0x1, %edx
leaq -0x100(%rbp), %rdi
callq 0x2360
jmp 0x3211
jmp 0x3213
jmp 0x3215
movl -0x104(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x104(%rbp)
jmp 0x2700
movl $0x0, -0x4(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x23c0
leaq -0xe0(%rbp), %rdi
callq 0x20d0
leaq -0xc0(%rbp), %rdi
callq 0x20d0
leaq -0x68(%rbp), %rdi
callq 0x33f0
movq -0x40(%rbp), %rax
movq %rax, %rsp
jmp 0x3289
leaq -0xe0(%rbp), %rdi
callq 0x20d0
leaq -0xc0(%rbp), %rdi
callq 0x20d0
leaq -0x68(%rbp), %rdi
callq 0x33f0
jmp 0x3291
movl -0x4(%rbp), %eax
movq %rbp, %rsp
popq %rbp
retq
movq -0x78(%rbp), %rdi
callq 0x21c0
nopw (%rax,%rax)