// File: NishadSaraf[P]Championship-Simulator/src/cache.cc
// Function: CACHE::handle_read()
void CACHE::handle_read()
{
    // handle read
    uint32_t read_cpu = RQ.entry[RQ.head].cpu;
    if (read_cpu == NUM_CPUS)
        return;

    for (uint32_t i=0; i<MAX_READ; i++) {

        // handle the oldest entry
        if ((RQ.entry[RQ.head].event_cycle <= current_core_cycle[read_cpu]) && (RQ.occupancy > 0)) {
            int index = RQ.head;

            // access cache
            uint32_t set = get_set(RQ.entry[index].address);
            int way = check_hit(&RQ.entry[index]);
            
            if (way >= 0) { // read hit

                if (cache_type == IS_ITLB) {
                    RQ.entry[index].instruction_pa = block[set][way].data;
                    if (PROCESSED.occupancy < PROCESSED.SIZE)
                        PROCESSED.add_queue(&RQ.entry[index]);
                }
                else if (cache_type == IS_DTLB) {
                    RQ.entry[index].data_pa = block[set][way].data;
                    if (PROCESSED.occupancy < PROCESSED.SIZE)
                        PROCESSED.add_queue(&RQ.entry[index]);
                }
                else if (cache_type == IS_STLB) 
                    RQ.entry[index].data = block[set][way].data;
                else if (cache_type == IS_L1I) {
                    if (PROCESSED.occupancy < PROCESSED.SIZE)
                        PROCESSED.add_queue(&RQ.entry[index]);
                }
                //else if (cache_type == IS_L1D) {
                else if ((cache_type == IS_L1D) && (RQ.entry[index].type != PREFETCH)) {
                    if (PROCESSED.occupancy < PROCESSED.SIZE)
                        PROCESSED.add_queue(&RQ.entry[index]);
                }

                // update prefetcher on load instruction
                if (RQ.entry[index].type == LOAD) {
                    if (cache_type == IS_L1D) 
                        l1d_prefetcher_operate(block[set][way].full_addr, RQ.entry[index].ip, 1, RQ.entry[index].type);
                    else if (cache_type == IS_L2C)
                        l2c_prefetcher_operate(block[set][way].full_addr, RQ.entry[index].ip, 1, RQ.entry[index].type);
                }

                // update replacement policy
                if (cache_type == IS_LLC) {
                    llc_update_replacement_state(read_cpu, set, way, block[set][way].full_addr, RQ.entry[index].ip, 0, RQ.entry[index].type, 1);

                }
                else
                    update_replacement_state(read_cpu, set, way, block[set][way].full_addr, RQ.entry[index].ip, 0, RQ.entry[index].type, 1);

                // COLLECT STATS
                sim_hit[read_cpu][RQ.entry[index].type]++;
                sim_access[read_cpu][RQ.entry[index].type]++;

                // check fill level
                if (RQ.entry[index].fill_level < fill_level) {

                    if (RQ.entry[index].instruction) 
                        upper_level_icache[read_cpu]->return_data(&RQ.entry[index]);
                    else // data
                        upper_level_dcache[read_cpu]->return_data(&RQ.entry[index]);
                }

                // update prefetch stats and reset prefetch bit
                if (block[set][way].prefetch) {
                    STATS.pf_useful++;
                    block[set][way].prefetch = 0;
                }
                block[set][way].used = 1;

                HIT[RQ.entry[index].type]++;
                ACCESS[RQ.entry[index].type]++;
                
                // remove this entry from RQ
                RQ.remove_queue(&RQ.entry[index]);
            }
            else { // read miss

                DP ( if (warmup_complete[read_cpu]) {
                cout << "[" << NAME << "] " << __func__ << " read miss";
                cout << " instr_id: " << RQ.entry[index].instr_id << " address: " << hex << RQ.entry[index].address;
                cout << " full_addr: " << RQ.entry[index].full_addr << dec;
                cout << " cycle: " << RQ.entry[index].event_cycle << endl; });

                // check mshr
                uint8_t miss_handled = 1;
                int mshr_index = check_mshr(&RQ.entry[index]);

                if ((mshr_index == -1) && (MSHR.occupancy < MSHR_SIZE)) { // this is a new miss

                    // add it to mshr (read miss)
                    add_mshr(&RQ.entry[index]);

                    // add it to the next level's read queue
                    if (lower_level)
                        lower_level->add_rq(&RQ.entry[index]);
                    else { // this is the last level
                        if (cache_type == IS_STLB) {
                            // TODO: need to differentiate page table walk and actual swap

                            // emulate page table walk
                            uint64_t pa = va_to_pa(read_cpu, RQ.entry[index].instr_id, RQ.entry[index].full_addr, RQ.entry[index].address);

                            RQ.entry[index].data = pa >> PAGE_SHIFT; 
                            RQ.entry[index].event_cycle = current_core_cycle[read_cpu];
                            return_data(&RQ.entry[index]);
                        }
                    }
                }
                else {
                    if ((mshr_index == -1) && (MSHR.occupancy == MSHR_SIZE)) { // not enough MSHR resource
                        
                        // cannot handle miss request until one of MSHRs is available
                        miss_handled = 0;
                        STALL[RQ.entry[index].type]++;
                    }
                    else if (mshr_index != -1) { // already in-flight miss

                        // mark merged consumer
                        if (RQ.entry[index].type == RFO) {

                            if (RQ.entry[index].tlb_access) {
                                uint32_t sq_index = RQ.entry[index].sq_index;
                                MSHR.entry[mshr_index].store_merged = 1;
                                MSHR.entry[mshr_index].sq_index_depend_on_me[sq_index] = 1;
                                for (uint32_t i=0; i<SQ_SIZE; i++) {
                                    if (RQ.entry[index].sq_index_depend_on_me[i])
                                        MSHR.entry[mshr_index].sq_index_depend_on_me[i] = 1;
                                    else
                                        continue;
                                }
                            }

                            if (RQ.entry[index].load_merged) {
                                //uint32_t lq_index = RQ.entry[index].lq_index; 
                                MSHR.entry[mshr_index].load_merged = 1;
                                //MSHR.entry[mshr_index].lq_index_depend_on_me[lq_index] = 1;
                                for (uint32_t i=0; i<LQ_SIZE; i++) {
                                    if (RQ.entry[index].lq_index_depend_on_me[i])
                                        MSHR.entry[mshr_index].lq_index_depend_on_me[i] = 1;
                                }
                            }
                        }
                        else {
                            if (RQ.entry[index].instruction) {
                                uint32_t rob_index = RQ.entry[index].rob_index;
                                MSHR.entry[mshr_index].instr_merged = 1;
                                MSHR.entry[mshr_index].rob_index_depend_on_me[rob_index] = 1;

                                DP (if (warmup_complete[MSHR.entry[mshr_index].cpu]) {
                                cout << "[INSTR_MERGED] " << __func__ << " cpu: " << MSHR.entry[mshr_index].cpu << " instr_id: " << MSHR.entry[mshr_index].instr_id;
                                cout << " merged rob_index: " << rob_index << " instr_id: " << RQ.entry[index].instr_id << endl; });

                                if (RQ.entry[index].instr_merged) {
                                    for (uint32_t i=0; i<ROB_SIZE; i++) {
                                        if (RQ.entry[index].rob_index_depend_on_me[i]) {
                                            MSHR.entry[mshr_index].rob_index_depend_on_me[i] = 1;

                                            DP (if (warmup_complete[MSHR.entry[mshr_index].cpu]) {
                                            cout << "[INSTR_MERGED] " << __func__ << " cpu: " << MSHR.entry[mshr_index].cpu << " instr_id: " << MSHR.entry[mshr_index].instr_id;
                                            cout << " merged rob_index: " << i << " instr_id: N/A" << endl; });
                                        }
                                    }
                                }
                            }
                            else 
                            {
                                uint32_t lq_index = RQ.entry[index].lq_index;
                                MSHR.entry[mshr_index].load_merged = 1;
                                MSHR.entry[mshr_index].lq_index_depend_on_me[lq_index] = 1;

                                DP (if (warmup_complete[read_cpu]) {
                                cout << "[DATA_MERGED] " << __func__ << " cpu: " << read_cpu << " instr_id: " << RQ.entry[index].instr_id;
                                cout << " merged rob_index: " << RQ.entry[index].rob_index << " instr_id: " << RQ.entry[index].instr_id << " lq_index: " << RQ.entry[index].lq_index << endl; });

                                for (uint32_t i=0; i<LQ_SIZE; i++) {
                                    if (RQ.entry[index].lq_index_depend_on_me[i]) 
                                        MSHR.entry[mshr_index].lq_index_depend_on_me[i] = 1;
                                }

                                if (RQ.entry[index].store_merged) {
                                    //uint32_t sq_index = RQ.entry[index].sq_index;
                                    MSHR.entry[mshr_index].store_merged = 1;
                                    //MSHR.entry[mshr_index].sq_index_depend_on_me[sq_index] = 1;
                                    for (uint32_t i=0; i<SQ_SIZE; i++) {
                                        if (RQ.entry[index].sq_index_depend_on_me[i])
                                            MSHR.entry[mshr_index].sq_index_depend_on_me[i] = 1;
                                        else
                                            continue;
                                    }
                                }
                            }
                        }

                        // update fill_level
                        if (RQ.entry[index].fill_level < MSHR.entry[mshr_index].fill_level)
                            MSHR.entry[mshr_index].fill_level = RQ.entry[index].fill_level;

                        // update request
                        if (MSHR.entry[mshr_index].type == PREFETCH) {
                            uint8_t  prior_returned = MSHR.entry[mshr_index].returned;
                            uint64_t prior_event_cycle = MSHR.entry[mshr_index].event_cycle;
                            memcpy(&MSHR.entry[mshr_index], &RQ.entry[index], sizeof(PACKET));
                            
                            // in case request is already returned, we should keep event_cycle and retunred variables
                            MSHR.entry[mshr_index].returned = prior_returned;
                            MSHR.entry[mshr_index].event_cycle = prior_event_cycle;
                        }

                        MSHR_MERGED[RQ.entry[index].type]++;

                        DP ( if (warmup_complete[read_cpu]) {
                        cout << "[" << NAME << "] " << __func__ << " mshr merged";
                        cout << " instr_id: " << RQ.entry[index].instr_id << " prior_id: " << MSHR.entry[mshr_index].instr_id; 
                        cout << " address: " << hex << RQ.entry[index].address;
                        cout << " full_addr: " << RQ.entry[index].full_addr << dec;
                        cout << " cycle: " << RQ.entry[index].event_cycle << endl; });
                    }
                    else { // WE SHOULD NOT REACH HERE
                        cerr << "[" << NAME << "] MSHR errors" << endl;
                        assert(0);
                    }
                }

                if (miss_handled) {
                    // update prefetcher on load instruction
                    if (RQ.entry[index].type == LOAD) {
                        if (cache_type == IS_L1D) 
                            l1d_prefetcher_operate(RQ.entry[index].full_addr, RQ.entry[index].ip, 0, RQ.entry[index].type);
                        if (cache_type == IS_L2C)
                            l2c_prefetcher_operate(RQ.entry[index].full_addr, RQ.entry[index].ip, 0, RQ.entry[index].type);
                    }

                    MISS[RQ.entry[index].type]++;
                    ACCESS[RQ.entry[index].type]++;

                    // remove this entry from RQ
                    RQ.remove_queue(&RQ.entry[index]);
                }
            }
        }
    }
}

// Assembly:
subq $0x88, %rsp
movq %rdi, 0x80(%rsp)
movq 0x80(%rsp), %rcx
movq %rcx, 0x20(%rsp)
movq 0x90e0(%rcx), %rax
movl 0x9074(%rcx), %ecx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x330(%rax), %eax
movl %eax, 0x7c(%rsp)
cmpl $0x1, 0x7c(%rsp)
jne 0x6529
jmp 0x76fc
movl $0x0, 0x78(%rsp)
movq 0x20(%rsp), %rcx
movl 0x78(%rsp), %eax
cmpl 0x739c(%rcx), %eax
jae 0x76fc
movq 0x20(%rsp), %rcx
movq 0x90e0(%rcx), %rax
movl 0x9074(%rcx), %ecx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movq 0x378(%rax), %rax
movl 0x7c(%rsp), %ecx
movl %ecx, %edx
leaq 0x8994a(%rip), %rcx     # 0x8fec0
cmpq (%rcx,%rdx,8), %rax
ja 0x76ea
movq 0x20(%rsp), %rax
cmpl $0x0, 0x907c(%rax)
jbe 0x76ea
movq 0x20(%rsp), %rdi
movl 0x9074(%rdi), %eax
movl %eax, 0x74(%rsp)
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movq 0x340(%rax), %rsi
callq 0x49b0
movq 0x20(%rsp), %rdi
movl %eax, 0x70(%rsp)
movq 0x90e0(%rdi), %rsi
movslq 0x74(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
callq 0x6150
movl %eax, 0x6c(%rsp)
cmpl $0x0, 0x6c(%rsp)
jl 0x6cab
movq 0x20(%rsp), %rax
movzbl 0x73a4(%rax), %eax
cmpl $0x0, %eax
jne 0x6685
movq 0x20(%rsp), %rcx
movq 0x7390(%rcx), %rax
movl 0x70(%rsp), %edx
movq (%rax,%rdx,8), %rax
movslq 0x6c(%rsp), %rdx
imulq $0x50, %rdx, %rdx
addq %rdx, %rax
movq 0x30(%rax), %rdx
movq 0x90e0(%rcx), %rax
movslq 0x74(%rsp), %rsi
imulq $0x380, %rsi, %rsi      # imm = 0x380
addq %rsi, %rax
movq %rdx, 0x350(%rax)
movl 0xe65c(%rcx), %eax
cmpl 0xe648(%rcx), %eax
jae 0x6680
movq 0x20(%rsp), %rax
movq %rax, %rdi
addq $0xe628, %rdi           # imm = 0xE628
movq 0x90e0(%rax), %rsi
movslq 0x74(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
callq 0x15040
jmp 0x683a
movq 0x20(%rsp), %rax
movzbl 0x73a4(%rax), %eax
cmpl $0x1, %eax
jne 0x6714
movq 0x20(%rsp), %rcx
movq 0x7390(%rcx), %rax
movl 0x70(%rsp), %edx
movq (%rax,%rdx,8), %rax
movslq 0x6c(%rsp), %rdx
imulq $0x50, %rdx, %rdx
addq %rdx, %rax
movq 0x30(%rax), %rdx
movq 0x90e0(%rcx), %rax
movslq 0x74(%rsp), %rsi
imulq $0x380, %rsi, %rsi      # imm = 0x380
addq %rsi, %rax
movq %rdx, 0x358(%rax)
movl 0xe65c(%rcx), %eax
cmpl 0xe648(%rcx), %eax
jae 0x670f
movq 0x20(%rsp), %rax
movq %rax, %rdi
addq $0xe628, %rdi           # imm = 0xE628
movq 0x90e0(%rax), %rsi
movslq 0x74(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
callq 0x15040
jmp 0x6838
movq 0x20(%rsp), %rax
movzbl 0x73a4(%rax), %eax
cmpl $0x2, %eax
jne 0x676b
movq 0x20(%rsp), %rax
movq 0x7390(%rax), %rcx
movl 0x70(%rsp), %edx
movq (%rcx,%rdx,8), %rcx
movslq 0x6c(%rsp), %rdx
imulq $0x50, %rdx, %rdx
addq %rdx, %rcx
movq 0x30(%rcx), %rcx
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rax
movq %rcx, 0x360(%rax)
jmp 0x6836
movq 0x20(%rsp), %rax
movzbl 0x73a4(%rax), %eax
cmpl $0x3, %eax
jne 0x67bb
movq 0x20(%rsp), %rcx
movl 0xe65c(%rcx), %eax
cmpl 0xe648(%rcx), %eax
jae 0x67b9
movq 0x20(%rsp), %rax
movq %rax, %rdi
addq $0xe628, %rdi           # imm = 0xE628
movq 0x90e0(%rax), %rsi
movslq 0x74(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
callq 0x15040
jmp 0x6834
movq 0x20(%rsp), %rax
movzbl 0x73a4(%rax), %eax
cmpl $0x4, %eax
jne 0x6832
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movzbl 0x32f(%rax), %eax
cmpl $0x2, %eax
je 0x6832
movq 0x20(%rsp), %rcx
movl 0xe65c(%rcx), %eax
cmpl 0xe648(%rcx), %eax
jae 0x6830
movq 0x20(%rsp), %rax
movq %rax, %rdi
addq $0xe628, %rdi           # imm = 0xE628
movq 0x90e0(%rax), %rsi
movslq 0x74(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
callq 0x15040
jmp 0x6832
jmp 0x6834
jmp 0x6836
jmp 0x6838
jmp 0x683a
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movzbl 0x32f(%rax), %eax
cmpl $0x0, %eax
jne 0x695f
movq 0x20(%rsp), %rax
movzbl 0x73a4(%rax), %eax
cmpl $0x4, %eax
jne 0x68e1
movq 0x20(%rsp), %rdi
movq 0x7390(%rdi), %rax
movl 0x70(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movslq 0x6c(%rsp), %rcx
imulq $0x50, %rcx, %rcx
addq %rcx, %rax
movq 0x20(%rax), %rsi
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movq 0x370(%rax), %rdx
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl $0x1, %ecx
movzbl 0x32f(%rax), %r8d
callq 0x22980
jmp 0x695d
movq 0x20(%rsp), %rax
movzbl 0x73a4(%rax), %eax
cmpl $0x5, %eax
jne 0x695b
movq 0x20(%rsp), %rdi
movq 0x7390(%rdi), %rax
movl 0x70(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movslq 0x6c(%rsp), %rcx
imulq $0x50, %rcx, %rcx
addq %rcx, %rax
movq 0x20(%rax), %rsi
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movq 0x370(%rax), %rdx
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl $0x1, %ecx
movzbl 0x32f(%rax), %r8d
callq 0x22920
jmp 0x695d
jmp 0x695f
movq 0x20(%rsp), %rax
movzbl 0x73a4(%rax), %eax
cmpl $0x6, %eax
jne 0x6a00
movq 0x20(%rsp), %rdi
movl 0x7c(%rsp), %esi
movl 0x70(%rsp), %edx
movl 0x6c(%rsp), %ecx
movq 0x7390(%rdi), %rax
movl 0x70(%rsp), %r8d
movq (%rax,%r8,8), %rax
movslq 0x6c(%rsp), %r8
imulq $0x50, %r8, %r8
addq %r8, %rax
movq 0x20(%rax), %r8
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %r9
imulq $0x380, %r9, %r9        # imm = 0x380
addq %r9, %rax
movq 0x370(%rax), %r9
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %r10
imulq $0x380, %r10, %r10      # imm = 0x380
addq %r10, %rax
movzbl 0x32f(%rax), %eax
xorl %r10d, %r10d
movq $0x0, (%rsp)
movl %eax, 0x8(%rsp)
movl $0x1, 0x10(%rsp)
callq 0x22750
jmp 0x6a87
movq 0x20(%rsp), %rdi
movl 0x7c(%rsp), %esi
movl 0x70(%rsp), %edx
movl 0x6c(%rsp), %ecx
movq 0x7390(%rdi), %rax
movl 0x70(%rsp), %r8d
movq (%rax,%r8,8), %rax
movslq 0x6c(%rsp), %r8
imulq $0x50, %r8, %r8
addq %r8, %rax
movq 0x20(%rax), %r8
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %r9
imulq $0x380, %r9, %r9        # imm = 0x380
addq %r9, %rax
movq 0x370(%rax), %r9
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %r10
imulq $0x380, %r10, %r10      # imm = 0x380
addq %r10, %rax
movzbl 0x32f(%rax), %eax
xorl %r10d, %r10d
movq $0x0, (%rsp)
movl %eax, 0x8(%rsp)
movl $0x1, 0x10(%rsp)
callq 0x22510
movq 0x20(%rsp), %rcx
movq %rcx, %rax
addq $0x10308, %rax          # imm = 0x10308
movl 0x7c(%rsp), %edx
shlq $0x5, %rdx
addq %rdx, %rax
movq 0x90e0(%rcx), %rdx
movslq 0x74(%rsp), %rsi
imulq $0x380, %rsi, %rsi      # imm = 0x380
addq %rsi, %rdx
movzbl 0x32f(%rdx), %edx
movq (%rax,%rdx,8), %rsi
addq $0x1, %rsi
movq %rsi, (%rax,%rdx,8)
movq %rcx, %rax
addq $0x102e8, %rax          # imm = 0x102E8
movl 0x7c(%rsp), %edx
shlq $0x5, %rdx
addq %rdx, %rax
movq 0x90e0(%rcx), %rdx
movslq 0x74(%rsp), %rsi
imulq $0x380, %rsi, %rsi      # imm = 0x380
addq %rsi, %rdx
movzbl 0x32f(%rdx), %edx
movq (%rax,%rdx,8), %rsi
addq $0x1, %rsi
movq %rsi, (%rax,%rdx,8)
movq 0x90e0(%rcx), %rax
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rax
movl 0x8(%rax), %eax
cmpl 0x7398(%rcx), %eax
jge 0x6b9f
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
cmpb $0x0, (%rax)
je 0x6b73
movq 0x20(%rsp), %rax
movl 0x7c(%rsp), %ecx
movq 0x8(%rax,%rcx,8), %rdi
movq 0x90e0(%rax), %rsi
movslq 0x74(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
movq (%rdi), %rax
callq *0x18(%rax)
jmp 0x6b9d
movq 0x20(%rsp), %rax
movl 0x7c(%rsp), %ecx
movq 0x10(%rax,%rcx,8), %rdi
movq 0x90e0(%rax), %rsi
movslq 0x74(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
movq (%rdi), %rax
callq *0x18(%rax)
jmp 0x6b9f
movq 0x20(%rsp), %rax
movq 0x7390(%rax), %rax
movl 0x70(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movslq 0x6c(%rsp), %rcx
imulq $0x50, %rcx, %rcx
addq %rcx, %rax
cmpb $0x0, 0x1(%rax)
je 0x6bfb
movq 0x20(%rsp), %rax
movq 0x102d0(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x102d0(%rax)
movq 0x7390(%rax), %rax
movl 0x70(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movslq 0x6c(%rsp), %rcx
imulq $0x50, %rcx, %rcx
addq %rcx, %rax
movb $0x0, 0x1(%rax)
movq 0x20(%rsp), %rax
movq 0x7390(%rax), %rcx
movl 0x70(%rsp), %edx
movq (%rcx,%rdx,8), %rcx
movslq 0x6c(%rsp), %rdx
imulq $0x50, %rdx, %rdx
addq %rdx, %rcx
movb $0x1, 0x3(%rcx)
movq 0x90e0(%rax), %rcx
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movzbl 0x32f(%rcx), %ecx
movq 0x72c8(%rax,%rcx,8), %rdx
addq $0x1, %rdx
movq %rdx, 0x72c8(%rax,%rcx,8)
movq 0x90e0(%rax), %rcx
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movzbl 0x32f(%rcx), %ecx
movq 0x72a8(%rax,%rcx,8), %rdx
addq $0x1, %rdx
movq %rdx, 0x72a8(%rax,%rcx,8)
movq %rax, %rdi
addq $0x9048, %rdi           # imm = 0x9048
movq 0x90e0(%rax), %rsi
movslq 0x74(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
callq 0x150e0
jmp 0x76e8
movq 0x20(%rsp), %rdi
movb $0x1, 0x6b(%rsp)
movq 0x90e0(%rdi), %rsi
movslq 0x74(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
callq 0x6370
movl %eax, 0x64(%rsp)
cmpl $-0x1, 0x64(%rsp)
jne 0x6e46
movq 0x20(%rsp), %rcx
movl 0xc9bc(%rcx), %eax
cmpl 0x7388(%rcx), %eax
jae 0x6e46
movq 0x20(%rsp), %rdi
movq 0x90e0(%rdi), %rsi
movslq 0x74(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
callq 0x6400
movq 0x20(%rsp), %rax
cmpq $0x0, 0x18(%rax)
je 0x6d4b
movq 0x20(%rsp), %rax
movq 0x18(%rax), %rdi
movq 0x90e0(%rax), %rsi
movslq 0x74(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
movq (%rdi), %rax
callq *(%rax)
jmp 0x6e41
movq 0x20(%rsp), %rax
movzbl 0x73a4(%rax), %eax
cmpl $0x2, %eax
jne 0x6e3f
movq 0x20(%rsp), %rax
movl 0x7c(%rsp), %edi
movq 0x90e0(%rax), %rcx
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movq 0x368(%rcx), %rsi
movq 0x90e0(%rax), %rcx
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movq 0x348(%rcx), %rdx
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movq 0x340(%rax), %rcx
callq 0xd230
movq 0x20(%rsp), %rdi
movq %rax, 0x58(%rsp)
movq 0x58(%rsp), %rcx
shrq $0xc, %rcx
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rax
movq %rcx, 0x360(%rax)
movl 0x7c(%rsp), %eax
movl %eax, %ecx
leaq 0x890be(%rip), %rax     # 0x8fec0
movq (%rax,%rcx,8), %rcx
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rax
movq %rcx, 0x378(%rax)
movq 0x90e0(%rdi), %rsi
movslq 0x74(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
movq (%rdi), %rax
callq *0x18(%rax)
jmp 0x6e41
jmp 0x7538
cmpl $-0x1, 0x64(%rsp)
jne 0x6ea0
movq 0x20(%rsp), %rcx
movl 0xc9bc(%rcx), %eax
cmpl 0x7388(%rcx), %eax
jne 0x6ea0
movq 0x20(%rsp), %rax
movb $0x0, 0x6b(%rsp)
movq 0x90e0(%rax), %rcx
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movzbl 0x32f(%rcx), %ecx
movq 0x7328(%rax,%rcx,8), %rdx
addq $0x1, %rdx
movq %rdx, 0x7328(%rax,%rcx,8)
jmp 0x7536
cmpl $-0x1, 0x64(%rsp)
je 0x74d0
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movzbl 0x32f(%rax), %eax
cmpl $0x1, %eax
jne 0x7092
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
cmpb $0x0, 0x1(%rax)
je 0x6fd3
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rcx
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movl 0x33c(%rcx), %ecx
movl %ecx, 0x54(%rsp)
movq 0xca20(%rax), %rcx
movslq 0x64(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movb $0x1, 0x32b(%rcx)
movq 0xca20(%rax), %rax
movslq 0x64(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x54(%rsp), %ecx
movb $0x1, 0x229(%rax,%rcx)
movl $0x0, 0x50(%rsp)
cmpl $0x38, 0x50(%rsp)
jae 0x6fd1
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x50(%rsp), %ecx
cmpb $0x0, 0x229(%rax,%rcx)
je 0x6fc0
movq 0x20(%rsp), %rax
movq 0xca20(%rax), %rax
movslq 0x64(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x50(%rsp), %ecx
movb $0x1, 0x229(%rax,%rcx)
jmp 0x6fc2
jmp 0x6fc4
jmp 0x6fc4
movl 0x50(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x50(%rsp)
jmp 0x6f67
jmp 0x6fd3
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
cmpb $0x0, 0x32a(%rax)
je 0x708d
movq 0x20(%rsp), %rax
movq 0xca20(%rax), %rax
movslq 0x64(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movb $0x1, 0x32a(%rax)
movl $0x0, 0x4c(%rsp)
cmpl $0x48, 0x4c(%rsp)
jae 0x708b
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x4c(%rsp), %ecx
cmpb $0x0, 0x129(%rax,%rcx)
je 0x707c
movq 0x20(%rsp), %rax
movq 0xca20(%rax), %rax
movslq 0x64(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x4c(%rsp), %ecx
movb $0x1, 0x129(%rax,%rcx)
jmp 0x707e
movl 0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
jmp 0x7025
jmp 0x708d
jmp 0x7339
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
cmpb $0x0, (%rax)
je 0x71a5
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rcx
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movl 0x10(%rcx), %ecx
movl %ecx, 0x48(%rsp)
movq 0xca20(%rax), %rcx
movslq 0x64(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movb $0x1, 0x329(%rcx)
movq 0xca20(%rax), %rcx
movslq 0x64(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movl 0x48(%rsp), %edx
movb $0x1, 0x29(%rcx,%rdx)
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
cmpb $0x0, 0x329(%rax)
je 0x71a0
movl $0x0, 0x44(%rsp)
cmpl $0x100, 0x44(%rsp)      # imm = 0x100
jae 0x719e
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x44(%rsp), %ecx
cmpb $0x0, 0x29(%rax,%rcx)
je 0x718f
movq 0x20(%rsp), %rax
movq 0xca20(%rax), %rax
movslq 0x64(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x44(%rsp), %ecx
movb $0x1, 0x29(%rax,%rcx)
jmp 0x7191
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
jmp 0x713b
jmp 0x71a0
jmp 0x7337
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rcx
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movl 0x338(%rcx), %ecx
movl %ecx, 0x40(%rsp)
movq 0xca20(%rax), %rcx
movslq 0x64(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movb $0x1, 0x32a(%rcx)
movq 0xca20(%rax), %rax
movslq 0x64(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x40(%rsp), %ecx
movb $0x1, 0x129(%rax,%rcx)
movl $0x0, 0x3c(%rsp)
cmpl $0x48, 0x3c(%rsp)
jae 0x7277
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x3c(%rsp), %ecx
cmpb $0x0, 0x129(%rax,%rcx)
je 0x7268
movq 0x20(%rsp), %rax
movq 0xca20(%rax), %rax
movslq 0x64(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x3c(%rsp), %ecx
movb $0x1, 0x129(%rax,%rcx)
jmp 0x726a
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0x7211
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
cmpb $0x0, 0x32b(%rax)
je 0x7335
movq 0x20(%rsp), %rax
movq 0xca20(%rax), %rax
movslq 0x64(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movb $0x1, 0x32b(%rax)
movl $0x0, 0x38(%rsp)
cmpl $0x38, 0x38(%rsp)
jae 0x7333
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x38(%rsp), %ecx
cmpb $0x0, 0x229(%rax,%rcx)
je 0x7322
movq 0x20(%rsp), %rax
movq 0xca20(%rax), %rax
movslq 0x64(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x38(%rsp), %ecx
movb $0x1, 0x229(%rax,%rcx)
jmp 0x7324
jmp 0x7326
jmp 0x7326
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0x72c9
jmp 0x7335
jmp 0x7337
jmp 0x7339
movq 0x20(%rsp), %rcx
movq 0x90e0(%rcx), %rax
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rax
movl 0x8(%rax), %eax
movq 0xca20(%rcx), %rcx
movslq 0x64(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
cmpl 0x8(%rcx), %eax
jge 0x73a9
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rcx
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movl 0x8(%rcx), %ecx
movq 0xca20(%rax), %rax
movslq 0x64(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rax
movl %ecx, 0x8(%rax)
movq 0x20(%rsp), %rax
movq 0xca20(%rax), %rax
movslq 0x64(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movzbl 0x32f(%rax), %eax
cmpl $0x2, %eax
jne 0x7498
movq 0x20(%rsp), %rax
movq 0xca20(%rax), %rcx
movslq 0x64(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movb 0x32c(%rcx), %cl
movb %cl, 0x37(%rsp)
movq 0xca20(%rax), %rcx
movslq 0x64(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movq 0x378(%rcx), %rcx
movq %rcx, 0x28(%rsp)
movq 0xca20(%rax), %rdi
movslq 0x64(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rdi
movq 0x90e0(%rax), %rsi
movslq 0x74(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
movl $0x380, %edx            # imm = 0x380
callq 0x31a0
movq 0x20(%rsp), %rax
movb 0x37(%rsp), %dl
movq 0xca20(%rax), %rcx
movslq 0x64(%rsp), %rsi
imulq $0x380, %rsi, %rsi      # imm = 0x380
addq %rsi, %rcx
movb %dl, 0x32c(%rcx)
movq 0x28(%rsp), %rcx
movq 0xca20(%rax), %rax
movslq 0x64(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rax
movq %rcx, 0x378(%rax)
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rcx
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movzbl 0x32f(%rcx), %ecx
movq 0x7308(%rax,%rcx,8), %rdx
addq $0x1, %rdx
movq %rdx, 0x7308(%rax,%rcx,8)
jmp 0x7534
movq 0x21b19(%rip), %rdi     # 0x28ff0
leaq 0x1bb4f(%rip), %rsi     # 0x2302d
callq 0x3220
movq 0x20(%rsp), %rsi
movq %rax, %rdi
addq $0x7350, %rsi           # imm = 0x7350
callq 0x31c0
movq %rax, %rdi
leaq 0x1bb2e(%rip), %rsi     # 0x2302f
callq 0x3220
movq %rax, %rdi
movq 0x21aa8(%rip), %rsi     # 0x28fb8
callq 0x3250
leaq 0x1bae8(%rip), %rdi     # 0x23004
leaq 0x1bae3(%rip), %rsi     # 0x23006
movl $0x273, %edx            # imm = 0x273
leaq 0x1bb5a(%rip), %rcx     # 0x23089
callq 0x3160
jmp 0x7536
jmp 0x7538
cmpb $0x0, 0x6b(%rsp)
je 0x76e6
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movzbl 0x32f(%rax), %eax
cmpl $0x0, %eax
jne 0x765a
movq 0x20(%rsp), %rax
movzbl 0x73a4(%rax), %eax
cmpl $0x4, %eax
jne 0x75e3
movq 0x20(%rsp), %rdi
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movq 0x348(%rax), %rsi
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movq 0x370(%rax), %rdx
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
xorl %ecx, %ecx
movzbl 0x32f(%rax), %r8d
callq 0x22980
movq 0x20(%rsp), %rax
movzbl 0x73a4(%rax), %eax
cmpl $0x5, %eax
jne 0x7658
movq 0x20(%rsp), %rdi
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movq 0x348(%rax), %rsi
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movq 0x370(%rax), %rdx
movq 0x90e0(%rdi), %rax
movslq 0x74(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
xorl %ecx, %ecx
movzbl 0x32f(%rax), %r8d
callq 0x22920
jmp 0x765a
movq 0x20(%rsp), %rax
movq 0x90e0(%rax), %rcx
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movzbl 0x32f(%rcx), %ecx
movq 0x72e8(%rax,%rcx,8), %rdx
addq $0x1, %rdx
movq %rdx, 0x72e8(%rax,%rcx,8)
movq 0x90e0(%rax), %rcx
movslq 0x74(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movzbl 0x32f(%rcx), %ecx
movq 0x72a8(%rax,%rcx,8), %rdx
addq $0x1, %rdx
movq %rdx, 0x72a8(%rax,%rcx,8)
movq %rax, %rdi
addq $0x9048, %rdi           # imm = 0x9048
movq 0x90e0(%rax), %rsi
movslq 0x74(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
callq 0x150e0
jmp 0x76e8
jmp 0x76ea
jmp 0x76ec
movl 0x78(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x78(%rsp)
jmp 0x6531
addq $0x88, %rsp
retq
nopw %cs:(%rax,%rax)