// File: /workspace/github_cpp_makefile_star2_O2/NishadSaraf[P]Championship-Simulator/src/ooo_cpu.cc
// Function: O3_CPU::handle_o3_fetch(PACKET*, unsigned int)
void O3_CPU::handle_o3_fetch(PACKET *current_packet, uint32_t cache_type)
{
    uint32_t rob_index = current_packet->rob_index,
             sq_index  = current_packet->sq_index,
             lq_index  = current_packet->lq_index;

    // update ROB entry
    if (cache_type == 0) { // DTLB

#ifdef SANITY_CHECK
        if (rob_index != check_rob(current_packet->instr_id))
            assert(0);
#endif
        if (current_packet->type == RFO) {
            SQ.entry[sq_index].physical_address = (current_packet->data_pa << PAGE_SHIFT) | (SQ.entry[sq_index].virtual_address & ((1 << PAGE_SHIFT) - 1)); // translated address
            SQ.entry[sq_index].translated = COMPLETED;

            RTS1[RTS1_tail] = sq_index;
            RTS1_tail++;
            if (RTS1_tail == SQ_SIZE)
                RTS1_tail = 0;

            DP (if (warmup_complete[cpu]) {
            cout << "[ROB] " << __func__ << " RFO instr_id: " << SQ.entry[sq_index].instr_id;
            cout << " DTLB_FETCH_DONE translation: " << +SQ.entry[sq_index].translated << hex << " page: " << (SQ.entry[sq_index].physical_address>>LOG2_PAGE_SIZE);
            cout << " full_addr: " << SQ.entry[sq_index].physical_address << dec << " store_merged: " << +current_packet->store_merged;
            cout << " load_merged: " << +current_packet->load_merged << endl; }); 

            handle_merged_translation(current_packet);
        }
        else { 
            LQ.entry[lq_index].physical_address = (current_packet->data_pa << PAGE_SHIFT) | (LQ.entry[lq_index].virtual_address & ((1 << PAGE_SHIFT) - 1)); // translated address
            LQ.entry[lq_index].translated = COMPLETED;

            RTL1[RTL1_tail] = lq_index;
            RTL1_tail++;
            if (RTL1_tail == LQ_SIZE)
                RTL1_tail = 0;

            DP (if (warmup_complete[cpu]) {
            cout << "[RTL1] " << __func__ << " instr_id: " << LQ.entry[lq_index].instr_id << " rob_index: " << LQ.entry[lq_index].rob_index << " is added to RTL1";
            cout << " head: " << RTL1_head << " tail: " << RTL1_tail << endl; }); 

            DP (if (warmup_complete[cpu]) {
            cout << "[ROB] " << __func__ << " load instr_id: " << LQ.entry[lq_index].instr_id;
            cout << " DTLB_FETCH_DONE translation: " << +LQ.entry[lq_index].translated << hex << " page: " << (LQ.entry[lq_index].physical_address>>LOG2_PAGE_SIZE);
            cout << " full_addr: " << LQ.entry[lq_index].physical_address << dec << " store_merged: " << +current_packet->store_merged;
            cout << " load_merged: " << +current_packet->load_merged << endl; }); 

            handle_merged_translation(current_packet);
        }

        ROB.entry[rob_index].event_cycle = current_packet->event_cycle;
    }
    else { // L1D

        if (current_packet->type == RFO)
            handle_merged_load(current_packet);
        else { // do traditional things
#ifdef SANITY_CHECK
            if (rob_index != check_rob(current_packet->instr_id))
                assert(0);

            if (current_packet->store_merged)
                assert(0);
#endif
            LQ.entry[lq_index].fetched = COMPLETED;
            ROB.entry[rob_index].num_mem_ops--;

#ifdef SANITY_CHECK
            if (ROB.entry[rob_index].num_mem_ops < 0) {
                cerr << "instr_id: " << ROB.entry[rob_index].instr_id << endl;
                assert(0);
            }
#endif
            if (ROB.entry[rob_index].num_mem_ops == 0)
                inflight_mem_executions++;

            DP (if (warmup_complete[cpu]) {
            cout << "[ROB] " << __func__ << " load instr_id: " << LQ.entry[lq_index].instr_id;
            cout << " L1D_FETCH_DONE fetched: " << +LQ.entry[lq_index].fetched << hex << " address: " << (LQ.entry[lq_index].physical_address>>LOG2_BLOCK_SIZE);
            cout << " full_addr: " << LQ.entry[lq_index].physical_address << dec << " remain_mem_ops: " << ROB.entry[rob_index].num_mem_ops;
            cout << " load_merged: " << +current_packet->load_merged << " inflight_mem: " << inflight_mem_executions << endl; }); 

            release_load_queue(lq_index);

            handle_merged_load(current_packet);

            ROB.entry[rob_index].event_cycle = current_packet->event_cycle;
        }
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
movq %rsi, %r14
movq %rdi, %rbx
movl 0x10(%rsi), %r12d
movl 0x338(%rsi), %r15d
testl %edx, %edx
je 0xca76
cmpb $0x1, 0x32f(%r14)
jne 0xcaf0
movq %rbx, %rdi
movq %r14, %rsi
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
jmp 0xc92c
movl 0x33c(%r14), %r13d
movq 0x368(%r14), %rsi
movq %rbx, %rdi
callq 0xa426
cmpl %eax, %r12d
jne 0xcbfb
movq 0x358(%r14), %rax
shlq $0xc, %rax
cmpb $0x1, 0x32f(%r14)
jne 0xcb81
movq 0xa28(%rbx), %rcx
imulq $0x140, %r13, %rdx      # imm = 0x140
movq 0x10(%rcx,%rdx), %rsi
andl $0xfff, %esi            # imm = 0xFFF
orq %rax, %rsi
movq %rsi, 0x18(%rcx,%rdx)
movb $0x2, 0x3c(%rcx,%rdx)
leaq 0x366c(%rbx), %rax
movl 0x366c(%rbx), %ecx
movl %r13d, 0x3588(%rbx,%rcx,4)
pushq $0x38
jmp 0xcbbe
movq 0x368(%r14), %rsi
movq %rbx, %rdi
callq 0xa426
cmpl %eax, %r12d
jne 0xcc1a
cmpb $0x0, 0x32b(%r14)
jne 0xcc39
movq 0x9f0(%rbx), %rax
imulq $0x140, %r15, %rcx      # imm = 0x140
movb $0x2, 0x3d(%rax,%rcx)
movq 0x9b8(%rbx), %rcx
imulq $0x758, %r12, %r12      # imm = 0x758
movl 0x70(%rcx,%r12), %edx
leal -0x1(%rdx), %eax
movl %eax, 0x70(%rcx,%r12)
testl %edx, %edx
jle 0xcc58
testl %eax, %eax
jne 0xcb56
incl 0x924(%rbx)
movq %rbx, %rdi
movl %r15d, %esi
callq 0xbc36
movq %rbx, %rdi
movq %r14, %rsi
callq 0xc92c
movq 0x378(%r14), %rax
movq 0x9b8(%rbx), %rcx
movq %rax, 0x40(%rcx,%r12)
jmp 0xcbf1
movq 0x9f0(%rbx), %rcx
imulq $0x140, %r15, %rdx      # imm = 0x140
movq 0x10(%rcx,%rdx), %rsi
andl $0xfff, %esi            # imm = 0xFFF
orq %rax, %rsi
movq %rsi, 0x18(%rcx,%rdx)
movb $0x2, 0x3c(%rcx,%rdx)
leaq 0x349c(%rbx), %rax
movl 0x349c(%rbx), %ecx
movl %r15d, 0x3378(%rbx,%rcx,4)
pushq $0x48
popq %rcx
movl (%rax), %edx
incl %edx
xorl %esi, %esi
cmpl %ecx, %edx
cmovnel %edx, %esi
movl %esi, (%rax)
movq %rbx, %rdi
movq %r14, %rsi
callq 0xc7f8
movq 0x378(%r14), %rax
movq 0x9b8(%rbx), %rcx
imulq $0x758, %r12, %rdx      # imm = 0x758
movq %rax, 0x40(%rcx,%rdx)
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
leaq 0x3465(%rip), %rdi      # 0x10067
leaq 0x3fe5(%rip), %rsi      # 0x10bee
leaq 0x42f0(%rip), %rcx      # 0x10f00
movl $0x67e, %edx            # imm = 0x67E
callq 0x2160
leaq 0x3446(%rip), %rdi      # 0x10067
leaq 0x3fc6(%rip), %rsi      # 0x10bee
leaq 0x42d1(%rip), %rcx      # 0x10f00
movl $0x6b0, %edx            # imm = 0x6B0
callq 0x2160
leaq 0x3427(%rip), %rdi      # 0x10067
leaq 0x3fa7(%rip), %rsi      # 0x10bee
leaq 0x42b2(%rip), %rcx      # 0x10f00
movl $0x6b3, %edx            # imm = 0x6B3
callq 0x2160
movq 0x9391(%rip), %rdi      # 0x15ff0
leaq 0x41f3(%rip), %rsi      # 0x10e59
callq 0x2230
movq 0x9b8(%rbx), %rcx
movq (%rcx,%r12), %rsi
movq %rax, %rdi
callq 0x2080
movq %rax, %rdi
callq 0x2110
leaq 0x33da(%rip), %rdi      # 0x10067
leaq 0x3f5a(%rip), %rsi      # 0x10bee
leaq 0x4265(%rip), %rcx      # 0x10f00
movl $0x6bb, %edx            # imm = 0x6BB
callq 0x2160
nop