// File: NishadSaraf[P]Championship-Simulator/src/ooo_cpu.cc
// Function: O3_CPU::handle_branch()
void O3_CPU::handle_branch()
{
    // actual processors do not work like this but for easier implementation,
    // we read instruction traces and virtually add them in the ROB
    // note that these traces are not yet translated and fetched 

    uint8_t continue_reading = 1;
    uint32_t num_reads = 0;
    instrs_to_read_this_cycle = FETCH_WIDTH;

    // first, read PIN trace
    while (continue_reading) {

        size_t instr_size = knob_cloudsuite ? sizeof(cloudsuite_instr) : sizeof(input_instr);

        if (knob_cloudsuite) {
            if (!fread(&current_cloudsuite_instr, instr_size, 1, trace_file)) {
                // reached end of file for this trace
                cout << "*** Reached end of trace for Core: " << cpu << " Repeating trace: " << trace_string << endl; 

                // close the trace file and re-open it
                pclose(trace_file);
                trace_file = popen(gunzip_command, "r");
                if (trace_file == NULL) {
                    cerr << endl << "*** CANNOT REOPEN TRACE FILE: " << trace_string << " ***" << endl;
                    assert(0);
                }
            } else { // successfully read the trace

                // copy the instruction into the performance model's instruction format
                ooo_model_instr arch_instr;
                int num_reg_ops = 0, num_mem_ops = 0;

                arch_instr.instr_id = instr_unique_id;
                arch_instr.ip = current_cloudsuite_instr.ip;
                arch_instr.is_branch = current_cloudsuite_instr.is_branch;
                arch_instr.branch_taken = current_cloudsuite_instr.branch_taken;

                arch_instr.asid[0] = current_cloudsuite_instr.asid[0];
                arch_instr.asid[1] = current_cloudsuite_instr.asid[1];

                for (uint32_t i=0; i<MAX_INSTR_DESTINATIONS; i++) {
                    arch_instr.destination_registers[i] = current_cloudsuite_instr.destination_registers[i];
                    arch_instr.destination_memory[i] = current_cloudsuite_instr.destination_memory[i];
                    arch_instr.destination_virtual_address[i] = current_cloudsuite_instr.destination_memory[i];

                    if (arch_instr.destination_registers[i])
                        num_reg_ops++;
                    if (arch_instr.destination_memory[i]) {
                        num_mem_ops++;

                        // update STA, this structure is required to execute store instructios properly without deadlock
                        if (num_mem_ops > 0) {
#ifdef SANITY_CHECK
                            if (STA[STA_tail] < UINT64_MAX) {
                                if (STA_head != STA_tail)
                                    assert(0);
                            }
#endif
                            STA[STA_tail] = instr_unique_id;
                            STA_tail++;

                            if (STA_tail == STA_SIZE)
                                STA_tail = 0;
                        }
                    }
                }

                for (int i=0; i<NUM_INSTR_SOURCES; i++) {
                    arch_instr.source_registers[i] = current_cloudsuite_instr.source_registers[i];
                    arch_instr.source_memory[i] = current_cloudsuite_instr.source_memory[i];
                    arch_instr.source_virtual_address[i] = current_cloudsuite_instr.source_memory[i];

                    if (arch_instr.source_registers[i])
                        num_reg_ops++;
                    if (arch_instr.source_memory[i])
                        num_mem_ops++;
                }

                arch_instr.num_reg_ops = num_reg_ops;
                arch_instr.num_mem_ops = num_mem_ops;
                if (num_mem_ops > 0) 
                    arch_instr.is_memory = 1;

                // virtually add this instruction to the ROB
                if (ROB.occupancy < ROB.SIZE) {
                    uint32_t rob_index = add_to_rob(&arch_instr);
                    num_reads++;

                    // branch prediction
                    if (arch_instr.is_branch) {

                        DP( if (warmup_complete[cpu]) {
                        cout << "[BRANCH] instr_id: " << instr_unique_id << " ip: " << hex << arch_instr.ip << dec << " taken: " << +arch_instr.branch_taken << endl; });

                        num_branch++;

                        /*
                        uint8_t branch_prediction;
                        // for faster simulation, force perfect prediction during the warmup
                        // note that branch predictor is still learning with real branch results
                        if (all_warmup_complete == 0)
                            branch_prediction = arch_instr.branch_taken; 
                        else
                            branch_prediction = predict_branch(arch_instr.ip);
                        */
                        uint8_t branch_prediction = predict_branch(arch_instr.ip);
                        
                        if (arch_instr.branch_taken != branch_prediction) {
                            branch_mispredictions++;

                            DP( if (warmup_complete[cpu]) {
                            cout << "[BRANCH] MISPREDICTED instr_id: " << instr_unique_id << " ip: " << hex << arch_instr.ip << dec;
                            cout << " taken: " << +arch_instr.branch_taken << " predicted: " << +branch_prediction << endl; });

                            // halt any further fetch this cycle
                            instrs_to_read_this_cycle = 0;

                            // and stall any additional fetches until the branch is executed
                            fetch_stall = 1; // FIXME

                            ROB.entry[rob_index].branch_mispredicted = 1;
                        }
                        else {
                            if (branch_prediction == 1) {
                                // if we are accurately predicting a branch to be taken, then we can't possibly fetch down that path this cycle,
                                // so we have to wait until the next cycle to fetch those
                                instrs_to_read_this_cycle = 0;
                            }

                            DP( if (warmup_complete[cpu]) {
                            cout << "[BRANCH] PREDICTED    instr_id: " << instr_unique_id << " ip: " << hex << arch_instr.ip << dec;
                            cout << " taken: " << +arch_instr.branch_taken << " predicted: " << +branch_prediction << endl; });
                        }

                        last_branch_result(arch_instr.ip, arch_instr.branch_taken);
                    }

                    //if ((num_reads == FETCH_WIDTH) || (ROB.occupancy == ROB.SIZE))
                    if ((num_reads >= instrs_to_read_this_cycle) || (ROB.occupancy == ROB.SIZE))
                        continue_reading = 0;
                }
                instr_unique_id++;
            }
        } else {
            if (!fread(&current_instr, instr_size, 1, trace_file)) {
                // reached end of file for this trace
                cout << "*** Reached end of trace for Core: " << cpu << " Repeating trace: " << trace_string << endl; 

                // close the trace file and re-open it
                pclose(trace_file);
                trace_file = popen(gunzip_command, "r");
                if (trace_file == NULL) {
                    cerr << endl << "*** CANNOT REOPEN TRACE FILE: " << trace_string << " ***" << endl;
                    assert(0);
                }
            } else { // successfully read the trace

                // copy the instruction into the performance model's instruction format
                ooo_model_instr arch_instr;
                int num_reg_ops = 0, num_mem_ops = 0;

                arch_instr.instr_id = instr_unique_id;
                arch_instr.ip = current_instr.ip;
                arch_instr.is_branch = current_instr.is_branch;
                arch_instr.branch_taken = current_instr.branch_taken;

                arch_instr.asid[0] = cpu;
                arch_instr.asid[1] = cpu;

                for (uint32_t i=0; i<MAX_INSTR_DESTINATIONS; i++) {
                    arch_instr.destination_registers[i] = current_instr.destination_registers[i];
                    arch_instr.destination_memory[i] = current_instr.destination_memory[i];
                    arch_instr.destination_virtual_address[i] = current_instr.destination_memory[i];

                    if (arch_instr.destination_registers[i])
                        num_reg_ops++;
                    if (arch_instr.destination_memory[i]) {
                        num_mem_ops++;

                        // update STA, this structure is required to execute store instructios properly without deadlock
                        if (num_mem_ops > 0) {
#ifdef SANITY_CHECK
                            if (STA[STA_tail] < UINT64_MAX) {
                                if (STA_head != STA_tail)
                                    assert(0);
                            }
#endif
                            STA[STA_tail] = instr_unique_id;
                            STA_tail++;

                            if (STA_tail == STA_SIZE)
                                STA_tail = 0;
                        }
                    }
                }

                for (int i=0; i<NUM_INSTR_SOURCES; i++) {
                    arch_instr.source_registers[i] = current_instr.source_registers[i];
                    arch_instr.source_memory[i] = current_instr.source_memory[i];
                    arch_instr.source_virtual_address[i] = current_instr.source_memory[i];

                    if (arch_instr.source_registers[i])
                        num_reg_ops++;
                    if (arch_instr.source_memory[i])
                        num_mem_ops++;
                }

                arch_instr.num_reg_ops = num_reg_ops;
                arch_instr.num_mem_ops = num_mem_ops;
                if (num_mem_ops > 0) 
                    arch_instr.is_memory = 1;

                // virtually add this instruction to the ROB
                if (ROB.occupancy < ROB.SIZE) {
                    uint32_t rob_index = add_to_rob(&arch_instr);
                    num_reads++;

                    // branch prediction
                    if (arch_instr.is_branch) {

                        DP( if (warmup_complete[cpu]) {
                        cout << "[BRANCH] instr_id: " << instr_unique_id << " ip: " << hex << arch_instr.ip << dec << " taken: " << +arch_instr.branch_taken << endl; });

                        num_branch++;

                        /*
                        uint8_t branch_prediction;
                        // for faster simulation, force perfect prediction during the warmup
                        // note that branch predictor is still learning with real branch results
                        if (all_warmup_complete == 0)
                            branch_prediction = arch_instr.branch_taken; 
                        else
                            branch_prediction = predict_branch(arch_instr.ip);
                        */
                        uint8_t branch_prediction = predict_branch(arch_instr.ip);
                        
                        if (arch_instr.branch_taken != branch_prediction) {
                            branch_mispredictions++;

                            DP( if (warmup_complete[cpu]) {
                            cout << "[BRANCH] MISPREDICTED instr_id: " << instr_unique_id << " ip: " << hex << arch_instr.ip << dec;
                            cout << " taken: " << +arch_instr.branch_taken << " predicted: " << +branch_prediction << endl; });

                            // halt any further fetch this cycle
                            instrs_to_read_this_cycle = 0;

                            // and stall any additional fetches until the branch is executed
                            fetch_stall = 1; // FIXME

                            ROB.entry[rob_index].branch_mispredicted = 1;
                        }
                        else {
                            if (branch_prediction == 1) {
                                // if we are accurately predicting a branch to be taken, then we can't possibly fetch down that path this cycle,
                                // so we have to wait until the next cycle to fetch those
                                instrs_to_read_this_cycle = 0;
                            }

                            DP( if (warmup_complete[cpu]) {
                            cout << "[BRANCH] PREDICTED    instr_id: " << instr_unique_id << " ip: " << hex << arch_instr.ip << dec;
                            cout << " taken: " << +arch_instr.branch_taken << " predicted: " << +branch_prediction << endl; });
                        }

                        last_branch_result(arch_instr.ip, arch_instr.branch_taken);
                    }

                    //if ((num_reads == FETCH_WIDTH) || (ROB.occupancy == ROB.SIZE))
                    if ((num_reads >= instrs_to_read_this_cycle) || (ROB.occupancy == ROB.SIZE))
                        continue_reading = 0;
                }
                instr_unique_id++;
            }
        }
    }

    //instrs_to_fetch_this_cycle = num_reads;
}

// Assembly:
subq $0xf08, %rsp            # imm = 0xF08
movq %rdi, 0xf00(%rsp)
movq 0xf00(%rsp), %rax
movq %rax, 0x8(%rsp)
movb $0x1, 0xeff(%rsp)
movl $0x0, 0xef8(%rsp)
movq $0x4, 0x900(%rax)
cmpb $0x0, 0xeff(%rsp)
je 0x15ccf
leaq 0x14126(%rip), %rax     # 0x29345
movb (%rax), %dl
movl $0x40, %eax
movl $0x60, %ecx
cmpb $0x0, %dl
cmovneq %rcx, %rax
movq %rax, 0xef0(%rsp)
leaq 0x14104(%rip), %rax     # 0x29345
cmpb $0x0, (%rax)
je 0x157e2
movq 0x8(%rsp), %rax
movq %rax, %rdi
addq $0x850, %rdi            # imm = 0x850
movq 0xef0(%rsp), %rsi
movq 0x8(%rax), %rcx
movl $0x1, %edx
callq 0x3340
cmpq $0x0, %rax
jne 0x15378
movq 0x13d50(%rip), %rdi     # 0x28fd0
leaq 0xe8d8(%rip), %rsi      # 0x23b5f
callq 0x3220
movq %rax, %rdi
movq 0x8(%rsp), %rax
movl (%rax), %esi
callq 0x32c0
movq %rax, %rdi
leaq 0xe8de(%rip), %rsi      # 0x23b83
callq 0x3220
movq 0x8(%rsp), %rsi
movq %rax, %rdi
addq $0x10, %rsi
callq 0x3220
movq %rax, %rdi
movq 0x13cf3(%rip), %rsi     # 0x28fb8
callq 0x3250
movq 0x8(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0x3320
movq 0x8(%rsp), %rdi
addq $0x410, %rdi            # imm = 0x410
leaq 0xede9(%rip), %rsi      # 0x240d4
callq 0x30c0
movq %rax, %rcx
movq 0x8(%rsp), %rax
movq %rcx, 0x8(%rax)
cmpq $0x0, 0x8(%rax)
jne 0x15373
movq 0x13ce6(%rip), %rdi     # 0x28ff0
movq 0x13ca7(%rip), %rsi     # 0x28fb8
callq 0x3250
movq %rax, %rdi
leaq 0xe876(%rip), %rsi      # 0x23b96
callq 0x3220
movq 0x8(%rsp), %rsi
movq %rax, %rdi
addq $0x10, %rsi
callq 0x3220
movq %rax, %rdi
leaq 0xe45c(%rip), %rsi      # 0x2379c
callq 0x3220
movq %rax, %rdi
movq 0x13c69(%rip), %rsi     # 0x28fb8
callq 0x3250
leaq 0xdca9(%rip), %rdi      # 0x23004
leaq 0xe853(%rip), %rsi      # 0x23bb5
movl $0x26, %edx
leaq 0xe856(%rip), %rcx      # 0x23bc4
callq 0x3160
jmp 0x157dd
leaq 0x798(%rsp), %rdi
callq 0x1c430
movq 0x8(%rsp), %rax
movl $0x0, 0x794(%rsp)
movl $0x0, 0x790(%rsp)
movq 0x8b0(%rax), %rcx
movq %rcx, 0x798(%rsp)
movq 0x850(%rax), %rcx
movq %rcx, 0x7a0(%rsp)
movb 0x858(%rax), %cl
movb %cl, 0x7e0(%rsp)
movb 0x859(%rax), %cl
movb %cl, 0x7e2(%rsp)
movb 0x8a8(%rax), %cl
movb %cl, 0x7f3(%rsp)
movb 0x8a9(%rax), %al
movb %al, 0x7f4(%rsp)
movl $0x0, 0x78c(%rsp)
movl 0x78c(%rsp), %eax
leaq 0x13e05(%rip), %rcx     # 0x29210
movzbl (%rcx), %ecx
cmpl %ecx, %eax
jae 0x1557d
movq 0x8(%rsp), %rax
movl 0x78c(%rsp), %ecx
movb 0x85a(%rax,%rcx), %dl
movl 0x78c(%rsp), %ecx
movb %dl, 0x814(%rsp,%rcx)
movl 0x78c(%rsp), %ecx
movq 0x868(%rax,%rcx,8), %rdx
movl 0x78c(%rsp), %ecx
movq %rdx, 0xd40(%rsp,%rcx,8)
movl 0x78c(%rsp), %ecx
movq 0x868(%rax,%rcx,8), %rcx
movl 0x78c(%rsp), %eax
movq %rcx, 0xd80(%rsp,%rax,8)
movl 0x78c(%rsp), %eax
cmpb $0x0, 0x814(%rsp,%rax)
je 0x15495
movl 0x794(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x794(%rsp)
movl 0x78c(%rsp), %eax
cmpq $0x0, 0xd40(%rsp,%rax,8)
je 0x15565
movl 0x790(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x790(%rsp)
cmpl $0x0, 0x790(%rsp)
jle 0x15563
movq 0x8(%rsp), %rax
movq 0x2a38(%rax), %rcx
cmpq $-0x1, 0xa30(%rax,%rcx,8)
jae 0x15517
movq 0x8(%rsp), %rcx
movq 0x2a30(%rcx), %rax
cmpq 0x2a38(%rcx), %rax
je 0x15515
leaq 0xdb07(%rip), %rdi      # 0x23004
leaq 0xe6b1(%rip), %rsi      # 0x23bb5
movl $0x45, %edx
leaq 0xe6b4(%rip), %rcx      # 0x23bc4
callq 0x3160
jmp 0x15517
movq 0x8(%rsp), %rax
movq 0x8b0(%rax), %rdx
movq 0x2a38(%rax), %rcx
movq %rdx, 0xa30(%rax,%rcx,8)
movq 0x2a38(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x2a38(%rax)
cmpq $0x400, 0x2a38(%rax) # imm = 0x400
jne 0x15561
movq 0x8(%rsp), %rax
movq $0x0, 0x2a38(%rax)
jmp 0x15563
jmp 0x15565
jmp 0x15567
movl 0x78c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x78c(%rsp)
jmp 0x153fd
movl $0x0, 0x788(%rsp)
cmpl $0x4, 0x788(%rsp)
jge 0x15658
movq 0x8(%rsp), %rax
movslq 0x788(%rsp), %rcx
movb 0x85e(%rax,%rcx), %dl
movslq 0x788(%rsp), %rcx
movb %dl, 0x818(%rsp,%rcx)
movslq 0x788(%rsp), %rcx
movq 0x888(%rax,%rcx,8), %rdx
movslq 0x788(%rsp), %rcx
movq %rdx, 0xd60(%rsp,%rcx,8)
movslq 0x788(%rsp), %rcx
movq 0x888(%rax,%rcx,8), %rcx
movslq 0x788(%rsp), %rax
movq %rcx, 0xda0(%rsp,%rax,8)
movslq 0x788(%rsp), %rax
cmpb $0x0, 0x818(%rsp,%rax)
je 0x1561c
movl 0x794(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x794(%rsp)
movslq 0x788(%rsp), %rax
cmpq $0x0, 0xd60(%rsp,%rax,8)
je 0x15640
movl 0x790(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x790(%rsp)
jmp 0x15642
movl 0x788(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x788(%rsp)
jmp 0x15588
movl 0x794(%rsp), %eax
movl %eax, 0x804(%rsp)
movl 0x790(%rsp), %eax
movl %eax, 0x808(%rsp)
cmpl $0x0, 0x790(%rsp)
jle 0x15686
movb $0x1, 0x7e1(%rsp)
movq 0x8(%rsp), %rcx
movl 0x960(%rcx), %eax
cmpl 0x950(%rcx), %eax
jae 0x157c6
movq 0x8(%rsp), %rdi
leaq 0x798(%rsp), %rsi
callq 0x15ce0
movl %eax, 0x784(%rsp)
movl 0xef8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xef8(%rsp)
cmpb $0x0, 0x7e0(%rsp)
je 0x15794
movq 0x8(%rsp), %rdi
movq 0x3680(%rdi), %rax
addq $0x1, %rax
movq %rax, 0x3680(%rdi)
movq 0x7a0(%rsp), %rsi
callq 0x221b0
movb %al, 0x783(%rsp)
movzbl 0x7e2(%rsp), %eax
movzbl 0x783(%rsp), %ecx
cmpl %ecx, %eax
je 0x1575b
movq 0x8(%rsp), %rax
movq 0x3688(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x3688(%rax)
movq $0x0, 0x900(%rax)
movb $0x1, 0x3678(%rax)
movq 0x9b8(%rax), %rax
movl 0x784(%rsp), %ecx
imulq $0x758, %rcx, %rcx      # imm = 0x758
addq %rcx, %rax
movb $0x1, 0x4b(%rax)
jmp 0x1577a
movzbl 0x783(%rsp), %eax
cmpl $0x1, %eax
jne 0x15778
movq 0x8(%rsp), %rax
movq $0x0, 0x900(%rax)
jmp 0x1577a
movq 0x8(%rsp), %rdi
movq 0x7a0(%rsp), %rsi
movzbl 0x7e2(%rsp), %edx
callq 0x22220
movq 0x8(%rsp), %rcx
movl 0xef8(%rsp), %eax
cmpq 0x900(%rcx), %rax
jae 0x157bc
movq 0x8(%rsp), %rcx
movl 0x960(%rcx), %eax
cmpl 0x950(%rcx), %eax
jne 0x157c4
movb $0x0, 0xeff(%rsp)
jmp 0x157c6
movq 0x8(%rsp), %rax
movq 0x8b0(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x8b0(%rax)
jmp 0x15cca
movq 0x8(%rsp), %rax
movq %rax, %rdi
addq $0x810, %rdi            # imm = 0x810
movq 0xef0(%rsp), %rsi
movq 0x8(%rax), %rcx
movl $0x1, %edx
callq 0x3340
cmpq $0x0, %rax
jne 0x15910
movq 0x137b8(%rip), %rdi     # 0x28fd0
leaq 0xe340(%rip), %rsi      # 0x23b5f
callq 0x3220
movq %rax, %rdi
movq 0x8(%rsp), %rax
movl (%rax), %esi
callq 0x32c0
movq %rax, %rdi
leaq 0xe346(%rip), %rsi      # 0x23b83
callq 0x3220
movq 0x8(%rsp), %rsi
movq %rax, %rdi
addq $0x10, %rsi
callq 0x3220
movq %rax, %rdi
movq 0x1375b(%rip), %rsi     # 0x28fb8
callq 0x3250
movq 0x8(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0x3320
movq 0x8(%rsp), %rdi
addq $0x410, %rdi            # imm = 0x410
leaq 0xe851(%rip), %rsi      # 0x240d4
callq 0x30c0
movq %rax, %rcx
movq 0x8(%rsp), %rax
movq %rcx, 0x8(%rax)
cmpq $0x0, 0x8(%rax)
jne 0x1590b
movq 0x1374e(%rip), %rdi     # 0x28ff0
movq 0x1370f(%rip), %rsi     # 0x28fb8
callq 0x3250
movq %rax, %rdi
leaq 0xe2de(%rip), %rsi      # 0x23b96
callq 0x3220
movq 0x8(%rsp), %rsi
movq %rax, %rdi
addq $0x10, %rsi
callq 0x3220
movq %rax, %rdi
leaq 0xdec4(%rip), %rsi      # 0x2379c
callq 0x3220
movq %rax, %rdi
movq 0x136d1(%rip), %rsi     # 0x28fb8
callq 0x3250
leaq 0xd711(%rip), %rdi      # 0x23004
leaq 0xe2bb(%rip), %rsi      # 0x23bb5
movl $0xa7, %edx
leaq 0xe2be(%rip), %rcx      # 0x23bc4
callq 0x3160
jmp 0x15cc8
leaq 0x28(%rsp), %rdi
callq 0x1c430
movq 0x8(%rsp), %rax
movl $0x0, 0x24(%rsp)
movl $0x0, 0x20(%rsp)
movq 0x8b0(%rax), %rcx
movq %rcx, 0x28(%rsp)
movq 0x810(%rax), %rcx
movq %rcx, 0x30(%rsp)
movb 0x818(%rax), %cl
movb %cl, 0x70(%rsp)
movb 0x819(%rax), %cl
movb %cl, 0x72(%rsp)
movl (%rax), %ecx
movb %cl, 0x83(%rsp)
movl (%rax), %eax
movb %al, 0x84(%rsp)
movl $0x0, 0x1c(%rsp)
movl 0x1c(%rsp), %eax
leaq 0x13890(%rip), %rcx     # 0x29210
movzbl (%rcx), %ecx
cmpl %ecx, %eax
jae 0x15ac5
movq 0x8(%rsp), %rax
movl 0x1c(%rsp), %ecx
movb 0x81a(%rax,%rcx), %dl
movl 0x1c(%rsp), %ecx
movb %dl, 0xa4(%rsp,%rcx)
movl 0x1c(%rsp), %ecx
movq 0x820(%rax,%rcx,8), %rdx
movl 0x1c(%rsp), %ecx
movq %rdx, 0x5d0(%rsp,%rcx,8)
movl 0x1c(%rsp), %ecx
movq 0x820(%rax,%rcx,8), %rcx
movl 0x1c(%rsp), %eax
movq %rcx, 0x610(%rsp,%rax,8)
movl 0x1c(%rsp), %eax
cmpb $0x0, 0xa4(%rsp,%rax)
je 0x159ef
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
movl 0x1c(%rsp), %eax
cmpq $0x0, 0x5d0(%rsp,%rax,8)
je 0x15ab3
movl 0x20(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x20(%rsp)
cmpl $0x0, 0x20(%rsp)
jle 0x15ab1
movq 0x8(%rsp), %rax
movq 0x2a38(%rax), %rcx
cmpq $-0x1, 0xa30(%rax,%rcx,8)
jae 0x15a65
movq 0x8(%rsp), %rcx
movq 0x2a30(%rcx), %rax
cmpq 0x2a38(%rcx), %rax
je 0x15a63
leaq 0xd5b9(%rip), %rdi      # 0x23004
leaq 0xe163(%rip), %rsi      # 0x23bb5
movl $0xc6, %edx
leaq 0xe166(%rip), %rcx      # 0x23bc4
callq 0x3160
jmp 0x15a65
movq 0x8(%rsp), %rax
movq 0x8b0(%rax), %rdx
movq 0x2a38(%rax), %rcx
movq %rdx, 0xa30(%rax,%rcx,8)
movq 0x2a38(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x2a38(%rax)
cmpq $0x400, 0x2a38(%rax) # imm = 0x400
jne 0x15aaf
movq 0x8(%rsp), %rax
movq $0x0, 0x2a38(%rax)
jmp 0x15ab1
jmp 0x15ab3
jmp 0x15ab5
movl 0x1c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
jmp 0x15975
movl $0x0, 0x18(%rsp)
cmpl $0x4, 0x18(%rsp)
jge 0x15b70
movq 0x8(%rsp), %rax
movslq 0x18(%rsp), %rcx
movb 0x81c(%rax,%rcx), %dl
movslq 0x18(%rsp), %rcx
movb %dl, 0xa8(%rsp,%rcx)
movslq 0x18(%rsp), %rcx
movq 0x830(%rax,%rcx,8), %rdx
movslq 0x18(%rsp), %rcx
movq %rdx, 0x5f0(%rsp,%rcx,8)
movslq 0x18(%rsp), %rcx
movq 0x830(%rax,%rcx,8), %rcx
movslq 0x18(%rsp), %rax
movq %rcx, 0x630(%rsp,%rax,8)
movslq 0x18(%rsp), %rax
cmpb $0x0, 0xa8(%rsp,%rax)
je 0x15b43
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
movslq 0x18(%rsp), %rax
cmpq $0x0, 0x5f0(%rsp,%rax,8)
je 0x15b5e
movl 0x20(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x20(%rsp)
jmp 0x15b60
movl 0x18(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x18(%rsp)
jmp 0x15acd
movl 0x24(%rsp), %eax
movl %eax, 0x94(%rsp)
movl 0x20(%rsp), %eax
movl %eax, 0x98(%rsp)
cmpl $0x0, 0x20(%rsp)
jle 0x15b92
movb $0x1, 0x71(%rsp)
movq 0x8(%rsp), %rcx
movl 0x960(%rcx), %eax
cmpl 0x950(%rcx), %eax
jae 0x15cb1
movq 0x8(%rsp), %rdi
leaq 0x28(%rsp), %rsi
callq 0x15ce0
movl %eax, 0x14(%rsp)
movl 0xef8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xef8(%rsp)
cmpb $0x0, 0x70(%rsp)
je 0x15c7f
movq 0x8(%rsp), %rdi
movq 0x3680(%rdi), %rax
addq $0x1, %rax
movq %rax, 0x3680(%rdi)
movq 0x30(%rsp), %rsi
callq 0x221b0
movb %al, 0x13(%rsp)
movzbl 0x72(%rsp), %eax
movzbl 0x13(%rsp), %ecx
cmpl %ecx, %eax
je 0x15c4f
movq 0x8(%rsp), %rax
movq 0x3688(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x3688(%rax)
movq $0x0, 0x900(%rax)
movb $0x1, 0x3678(%rax)
movq 0x9b8(%rax), %rax
movl 0x14(%rsp), %ecx
imulq $0x758, %rcx, %rcx      # imm = 0x758
addq %rcx, %rax
movb $0x1, 0x4b(%rax)
jmp 0x15c6b
movzbl 0x13(%rsp), %eax
cmpl $0x1, %eax
jne 0x15c69
movq 0x8(%rsp), %rax
movq $0x0, 0x900(%rax)
jmp 0x15c6b
movq 0x8(%rsp), %rdi
movq 0x30(%rsp), %rsi
movzbl 0x72(%rsp), %edx
callq 0x22220
movq 0x8(%rsp), %rcx
movl 0xef8(%rsp), %eax
cmpq 0x900(%rcx), %rax
jae 0x15ca7
movq 0x8(%rsp), %rcx
movl 0x960(%rcx), %eax
cmpl 0x950(%rcx), %eax
jne 0x15caf
movb $0x0, 0xeff(%rsp)
jmp 0x15cb1
movq 0x8(%rsp), %rax
movq 0x8b0(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x8b0(%rax)
jmp 0x15cca
jmp 0x1520a
addq $0xf08, %rsp            # imm = 0xF08
retq
nopw (%rax,%rax)