// File: /workspace/github_cpp_makefile_star2_O3/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x798, %rsp            # imm = 0x798
movq %rdi, %r14
movq $0x4, 0x900(%rdi)
leaq 0x850(%rdi), %rax
movq %rax, 0x38(%rsp)
leaq 0x888(%rdi), %rbp
leaq 0x40(%rsp), %rax
leaq 0x5c8(%rax), %rcx
movq %rcx, 0x20(%rsp)
leaq 0x608(%rax), %r15
leaq 0x10(%rdi), %rax
movq %rax, 0x8(%rsp)
leaq 0x410(%rdi), %rax
movq %rax, 0x18(%rsp)
leaq 0x810(%rdi), %rax
movq %rax, 0x30(%rsp)
leaq 0x830(%rdi), %rax
movq %rax, 0x28(%rsp)
movq $0x0, 0x10(%rsp)
leaq 0xdc73(%rip), %rbx      # 0x1a210
leaq 0xdda1(%rip), %rax      # 0x1a345
cmpb $0x0, (%rax)
movq 0x8(%r14), %rcx
je 0xc6f1
movl $0x60, %esi
movl $0x1, %edx
movq 0x38(%rsp), %rdi
callq 0x3320
testq %rax, %rax
je 0xc826
leaq 0x40(%rsp), %rdi
callq 0x10550
movq 0x8b0(%r14), %rax
movq %rax, 0x40(%rsp)
movq 0x850(%r14), %rcx
movq %rcx, 0x48(%rsp)
movb 0x858(%r14), %cl
movb %cl, 0x88(%rsp)
movb 0x859(%r14), %cl
movb %cl, 0x8a(%rsp)
movb 0x8a8(%r14), %cl
movb %cl, 0x9b(%rsp)
movb 0x8a9(%r14), %cl
movb %cl, 0x9c(%rsp)
movb (%rbx), %dil
testb %dil, %dil
je 0xc8d5
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
pxor %xmm4, %xmm4
pcmpeqd %xmm5, %xmm5
movdqa 0x85f5(%rip), %xmm6     # 0x14c40
movb 0x85a(%r14,%rdx), %sil
movb %sil, 0xbc(%rsp,%rdx)
movq 0x868(%r14,%rdx,8), %r9
movq %r9, 0x5e8(%rsp,%rdx,8)
movq %r9, 0x628(%rsp,%rdx,8)
cmpb $0x1, %sil
sbbl $-0x1, %ecx
testq %r9, %r9
je 0xc6d6
leal 0x1(%r8), %esi
testl %r8d, %r8d
js 0xc6d9
movq 0x2a38(%r14), %rdi
cmpq $-0x1, 0xa30(%r14,%rdi,8)
je 0xc6a7
cmpq %rdi, 0x2a30(%r14)
jne 0xcc21
movq %rax, 0xa30(%r14,%rdi,8)
movq 0x2a38(%r14), %rdi
incq %rdi
cmpq $0x400, %rdi            # imm = 0x400
movl $0x0, %r8d
cmovneq %rdi, %r8
movq %r8, 0x2a38(%r14)
movb (%rbx), %dil
jmp 0xc6d9
movl %r8d, %esi
incq %rdx
movzbl %dil, %r9d
movl %esi, %r8d
cmpq %r9, %rdx
jb 0xc64b
jmp 0xc8e9
movl $0x40, %esi
movl $0x1, %edx
movq 0x30(%rsp), %rdi
callq 0x3320
testq %rax, %rax
je 0xc9a7
leaq 0x40(%rsp), %rdi
callq 0x10550
movq 0x8b0(%r14), %rax
movq %rax, 0x40(%rsp)
movq 0x810(%r14), %rcx
movq %rcx, 0x48(%rsp)
movb 0x818(%r14), %cl
movb %cl, 0x88(%rsp)
movb 0x819(%r14), %cl
movb %cl, 0x8a(%rsp)
movb (%r14), %cl
movb %cl, 0x9b(%rsp)
movb %cl, 0x9c(%rsp)
movb (%rbx), %dil
testb %dil, %dil
je 0xca56
xorl %edx, %edx
xorl %r8d, %r8d
xorl %ecx, %ecx
pxor %xmm4, %xmm4
pcmpeqd %xmm5, %xmm5
movdqa 0x84c0(%rip), %xmm6     # 0x14c40
movb 0x81a(%r14,%rdx), %sil
movb %sil, 0xbc(%rsp,%rdx)
movq 0x820(%r14,%rdx,8), %r9
movq %r9, 0x5e8(%rsp,%rdx,8)
movq %r9, 0x628(%rsp,%rdx,8)
cmpb $0x1, %sil
sbbl $-0x1, %ecx
testq %r9, %r9
je 0xc80b
leal 0x1(%r8), %esi
testl %r8d, %r8d
js 0xc80e
movq 0x2a38(%r14), %rdi
cmpq $-0x1, 0xa30(%r14,%rdi,8)
je 0xc7dc
cmpq %rdi, 0x2a30(%r14)
jne 0xcc40
movq %rax, 0xa30(%r14,%rdi,8)
movq 0x2a38(%r14), %rdi
incq %rdi
cmpq $0x400, %rdi            # imm = 0x400
movl $0x0, %r8d
cmovneq %rdi, %r8
movq %r8, 0x2a38(%r14)
movb (%rbx), %dil
jmp 0xc80e
movl %r8d, %esi
incq %rdx
movzbl %dil, %r9d
movl %esi, %r8d
cmpq %r9, %rdx
jb 0xc780
jmp 0xca6a
movl $0x23, %edx
movq 0xd79e(%rip), %r12      # 0x19fd0
movq %r12, %rdi
leaq 0x8454(%rip), %rsi      # 0x14c90
callq 0x3280
movl (%r14), %esi
movq %r12, %rdi
callq 0x3170
movq %rax, %r13
movl $0x12, %edx
movq %rax, %rdi
leaq 0x8456(%rip), %rsi      # 0x14cb4
callq 0x3280
movq 0x8(%rsp), %r12
movq %r12, %rdi
callq 0x3100
movq %r13, %rdi
movq %r12, %rsi
movq %rax, %rdx
callq 0x3280
movq (%r13), %rax
movq -0x18(%rax), %rdi
addq %r13, %rdi
movl $0xa, %esi
callq 0x3240
movsbl %al, %esi
movq %r13, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x3180
movq 0x8(%r14), %rdi
callq 0x3300
movq 0x18(%rsp), %rdi
leaq 0x894d(%rip), %rsi      # 0x15208
callq 0x30d0
movq %rax, 0x8(%r14)
movb $0x1, %r12b
testq %rax, %rax
jne 0xcc06
jmp 0xcc5f
xorl %esi, %esi
xorl %ecx, %ecx
pxor %xmm4, %xmm4
pcmpeqd %xmm5, %xmm5
movdqa 0x8357(%rip), %xmm6     # 0x14c40
movl 0x85e(%r14), %eax
movl %eax, 0xc0(%rsp)
movups (%rbp), %xmm0
movups 0x10(%rbp), %xmm1
movq 0x20(%rsp), %rax
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
movups (%rbp), %xmm0
movups 0x10(%rbp), %xmm1
movups %xmm1, 0x10(%r15)
movups %xmm0, (%r15)
movd %ecx, %xmm1
movd %esi, %xmm0
movq $-0x4, %rax
movzwl 0x862(%r14,%rax), %ecx
movd %ecx, %xmm2
movdqu 0x8a8(%r14,%rax,8), %xmm3
pcmpeqb %xmm4, %xmm2
pxor %xmm5, %xmm2
punpcklbw %xmm2, %xmm2    # xmm2 = xmm2[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
punpcklwd %xmm2, %xmm2    # xmm2 = xmm2[0,0,1,1,2,2,3,3]
pand %xmm6, %xmm2
paddd %xmm2, %xmm1
pcmpeqd %xmm4, %xmm3
pshufd $0xbd, %xmm3, %xmm2     # xmm2 = xmm3[1,3,3,2]
pshufd $0xe8, %xmm3, %xmm3     # xmm3 = xmm3[0,2,2,3]
pand %xmm2, %xmm3
paddd %xmm3, %xmm0
psubd %xmm5, %xmm0
addq $0x2, %rax
jne 0xc92b
pshufd $0x55, %xmm1, %xmm2     # xmm2 = xmm1[1,1,1,1]
paddd %xmm1, %xmm2
pshufd $0x55, %xmm0, %xmm1     # xmm1 = xmm0[1,1,1,1]
paddd %xmm0, %xmm1
movd %xmm1, %eax
movd %xmm2, 0xac(%rsp)
movd %xmm1, 0xb0(%rsp)
jmp 0xcb26
movl $0x23, %edx
movq 0xd61d(%rip), %r12      # 0x19fd0
movq %r12, %rdi
leaq 0x82d3(%rip), %rsi      # 0x14c90
callq 0x3280
movl (%r14), %esi
movq %r12, %rdi
callq 0x3170
movq %rax, %r13
movl $0x12, %edx
movq %rax, %rdi
leaq 0x82d5(%rip), %rsi      # 0x14cb4
callq 0x3280
movq 0x8(%rsp), %r12
movq %r12, %rdi
callq 0x3100
movq %r13, %rdi
movq %r12, %rsi
movq %rax, %rdx
callq 0x3280
movq (%r13), %rax
movq -0x18(%rax), %rdi
addq %r13, %rdi
movl $0xa, %esi
callq 0x3240
movsbl %al, %esi
movq %r13, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x3180
movq 0x8(%r14), %rdi
callq 0x3300
movq 0x18(%rsp), %rdi
leaq 0x87cc(%rip), %rsi      # 0x15208
callq 0x30d0
movq %rax, 0x8(%r14)
movb $0x1, %r12b
testq %rax, %rax
jne 0xcc06
jmp 0xccbd
xorl %ecx, %ecx
xorl %esi, %esi
pxor %xmm4, %xmm4
pcmpeqd %xmm5, %xmm5
movdqa 0x81d6(%rip), %xmm6     # 0x14c40
movl 0x81c(%r14), %eax
movl %eax, 0xc0(%rsp)
movq 0x28(%rsp), %rdx
movups (%rdx), %xmm0
movups 0x10(%rdx), %xmm1
movq 0x20(%rsp), %rax
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
movups (%rdx), %xmm0
movups 0x10(%rdx), %xmm1
movups %xmm1, 0x10(%r15)
movups %xmm0, (%r15)
movd %esi, %xmm1
movd %ecx, %xmm0
movq $-0x4, %rax
movzwl 0x820(%r14,%rax), %ecx
movd %ecx, %xmm2
movdqu 0x850(%r14,%rax,8), %xmm3
pcmpeqb %xmm4, %xmm2
pxor %xmm5, %xmm2
punpcklbw %xmm2, %xmm2    # xmm2 = xmm2[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
punpcklwd %xmm2, %xmm2    # xmm2 = xmm2[0,0,1,1,2,2,3,3]
pand %xmm6, %xmm2
paddd %xmm2, %xmm0
pcmpeqd %xmm4, %xmm3
pshufd $0xbd, %xmm3, %xmm2     # xmm2 = xmm3[1,3,3,2]
pshufd $0xe8, %xmm3, %xmm3     # xmm3 = xmm3[0,2,2,3]
pand %xmm2, %xmm3
paddd %xmm3, %xmm1
psubd %xmm5, %xmm1
addq $0x2, %rax
jne 0xcaaf
pshufd $0x55, %xmm1, %xmm2     # xmm2 = xmm1[1,1,1,1]
paddd %xmm1, %xmm2
movd %xmm2, %eax
pshufd $0x55, %xmm0, %xmm1     # xmm1 = xmm0[1,1,1,1]
paddd %xmm0, %xmm1
movd %xmm1, 0xac(%rsp)
movd %xmm2, 0xb0(%rsp)
testl %eax, %eax
jle 0xcb32
movb $0x1, 0x89(%rsp)
movl 0x960(%r14), %eax
movb $0x1, %r12b
cmpl 0x950(%r14), %eax
jae 0xcbff
movq %r14, %rdi
leaq 0x40(%rsp), %rsi
callq 0xcd1c
cmpb $0x0, 0x88(%rsp)
je 0xcbd5
movl %eax, %r13d
incq 0x3680(%r14)
movq 0x48(%rsp), %rsi
movq %r14, %rdi
callq 0x1344a
movb 0x8a(%rsp), %cl
cmpb %al, %cl
jne 0xcb93
cmpb $0x1, %al
jne 0xcbc5
movq $0x0, 0x900(%r14)
jmp 0xcbc5
incq 0x3688(%r14)
movq $0x0, 0x900(%r14)
movb $0x1, %sil
movb %sil, 0x3678(%r14)
movq 0x9b8(%r14), %rax
movl %r13d, %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
movb %sil, 0x4b(%rax,%rdx)
movq 0x48(%rsp), %rsi
movzbl %cl, %edx
movq %r14, %rdi
callq 0x1347e
movq 0x10(%rsp), %rax
incl %eax
movq %rax, 0x10(%rsp)
movl %eax, %eax
cmpq %rax, 0x900(%r14)
jbe 0xcbfc
movl 0x960(%r14), %eax
cmpl 0x950(%r14), %eax
jne 0xcbff
xorl %r12d, %r12d
incq 0x8b0(%r14)
testb %r12b, %r12b
jne 0xc59d
addq $0x798, %rsp            # imm = 0x798
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x743f(%rip), %rdi      # 0x14067
leaq 0x80b7(%rip), %rsi      # 0x14ce6
leaq 0x80bf(%rip), %rcx      # 0x14cf5
movl $0x45, %edx
callq 0x3160
leaq 0x7420(%rip), %rdi      # 0x14067
leaq 0x8098(%rip), %rsi      # 0x14ce6
leaq 0x80a0(%rip), %rcx      # 0x14cf5
movl $0xc6, %edx
callq 0x3160
movq 0xd38a(%rip), %rdi      # 0x19ff0
callq 0x3110
leaq 0x8055(%rip), %rsi      # 0x14cc7
movq %rax, %rdi
callq 0x3250
movq %rax, %rdi
movq 0x8(%rsp), %rsi
callq 0x3250
leaq 0x7b79(%rip), %rsi      # 0x14807
movq %rax, %rdi
callq 0x3250
movq %rax, %rdi
callq 0x3110
leaq 0x73c2(%rip), %rdi      # 0x14067
leaq 0x803a(%rip), %rsi      # 0x14ce6
leaq 0x8042(%rip), %rcx      # 0x14cf5
movl $0x26, %edx
callq 0x3160
movq 0xd32c(%rip), %rdi      # 0x19ff0
callq 0x3110
leaq 0x7ff7(%rip), %rsi      # 0x14cc7
movq %rax, %rdi
callq 0x3250
movq %rax, %rdi
movq 0x8(%rsp), %rsi
callq 0x3250
leaq 0x7b1b(%rip), %rsi      # 0x14807
movq %rax, %rdi
callq 0x3250
movq %rax, %rdi
callq 0x3110
leaq 0x7364(%rip), %rdi      # 0x14067
leaq 0x7fdc(%rip), %rsi      # 0x14ce6
leaq 0x7fe4(%rip), %rcx      # 0x14cf5
movl $0xa7, %edx
callq 0x3160
nop