// File: /workspace/github_cpp_makefile_star2_O1/NishadSaraf[P]Championship-Simulator/src/ooo_cpu.cc
// Function: O3_CPU::complete_data_fetch(PACKET_QUEUE*, unsigned char)
void O3_CPU::complete_data_fetch(PACKET_QUEUE *queue, uint8_t is_it_tlb)
{
    uint32_t index = queue->head,
             rob_index = queue->entry[index].rob_index,
             sq_index = queue->entry[index].sq_index,
             lq_index = queue->entry[index].lq_index;

#ifdef SANITY_CHECK
    if (queue->entry[index].type != RFO) {
        if (rob_index != check_rob(queue->entry[index].instr_id))
            assert(0);
    }
#endif

    // update ROB entry
    if (is_it_tlb) { // DTLB

        if (queue->entry[index].type == RFO) {
            SQ.entry[sq_index].physical_address = (queue->entry[index].data_pa << PAGE_SHIFT) | (SQ.entry[sq_index].virtual_address & ((1 << PAGE_SHIFT) - 1)); // translated address
            SQ.entry[sq_index].translated = COMPLETED;
            SQ.entry[sq_index].event_cycle = current_core_cycle[cpu];

            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: " << +queue->entry[index].store_merged;
            cout << " load_merged: " << +queue->entry[index].load_merged << endl; }); 

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

            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: " << +queue->entry[index].store_merged;
            cout << " load_merged: " << +queue->entry[index].load_merged << endl; }); 

            handle_merged_translation(&queue->entry[index]);
        }

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

        if (queue->entry[index].type == RFO)
            handle_merged_load(&queue->entry[index]);
        else { 
#ifdef SANITY_CHECK
            if (queue->entry[index].store_merged)
                assert(0);
#endif
            LQ.entry[lq_index].fetched = COMPLETED;
            LQ.entry[lq_index].event_cycle = current_core_cycle[cpu];
            ROB.entry[rob_index].num_mem_ops--;
            ROB.entry[rob_index].event_cycle = queue->entry[index].event_cycle;

#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: " << +queue->entry[index].load_merged << " inflight_mem: " << inflight_mem_executions << endl; }); 

            release_load_queue(lq_index);
            handle_merged_load(&queue->entry[index]);
        }
    }

    // remove this entry
    queue->remove_queue(&queue->entry[index]);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %rbp
movq %rdi, %r15
movl 0x2c(%rsi), %ecx
movq 0x98(%rsi), %rax
imulq $0x380, %rcx, %r14      # imm = 0x380
movl 0x10(%rax,%r14), %r12d
movl 0x33c(%rax,%r14), %r13d
movl 0x338(%rax,%r14), %r10d
cmpb $0x1, 0x32f(%rax,%r14)
je 0xf57b
addq %r14, %rax
movq 0x368(%rax), %rsi
movq %r15, %rdi
movq %r10, %rbx
movq %r15, (%rsp)
movl %edx, %r15d
callq 0xce2c
movl %r15d, %edx
movq (%rsp), %r15
movq %rbx, %r10
cmpl %eax, %r12d
jne 0xf78a
movq 0x98(%rbp), %rax
leaq (%rax,%r14), %rsi
movb 0x32f(%rax,%r14), %cl
testb %dl, %dl
je 0xf607
movq 0x358(%rsi), %rax
shlq $0xc, %rax
cmpb $0x1, %cl
jne 0xf6de
movq 0xa28(%r15), %rcx
leaq (,%r13,4), %rdx
addq %r13, %rdx
shlq $0x6, %rdx
movq 0x10(%rcx,%rdx), %rdi
andl $0xfff, %edi            # imm = 0xFFF
orq %rax, %rdi
movq %rdi, 0x18(%rcx,%rdx)
movb $0x2, 0x3c(%rcx,%rdx)
movl (%r15), %eax
leaq 0x718e2(%rip), %rdi     # 0x80ec0
movq (%rdi,%rax,8), %rax
movq %rax, 0x28(%rcx,%rdx)
leaq 0x366c(%r15), %rax
movl 0x366c(%r15), %ecx
movl %r13d, 0x3588(%r15,%rcx,4)
movl $0x38, %ecx
jmp 0xf733
cmpb $0x1, %cl
je 0xf6d1
cmpb $0x0, 0x32b(%rsi)
jne 0xf7a9
movq 0x9f0(%r15), %rcx
leaq (%r10,%r10,4), %rdx
shlq $0x6, %rdx
movb $0x2, 0x3d(%rcx,%rdx)
movl (%r15), %esi
leaq 0x71885(%rip), %rdi     # 0x80ec0
movq (%rdi,%rsi,8), %rsi
movq %rsi, 0x28(%rcx,%rdx)
movq 0x9b8(%r15), %rdi
imulq $0x758, %r12, %r12      # imm = 0x758
movl 0x70(%rdi,%r12), %r8d
leal -0x1(%r8), %esi
movl %esi, 0x70(%rdi,%r12)
movq 0x378(%rax,%r14), %rax
movq %rax, 0x40(%rdi,%r12)
testl %r8d, %r8d
jle 0xf7c8
testl %esi, %esi
jne 0xf681
incl 0x924(%r15)
xorl %eax, %eax
leaq (%rcx,%rdx), %rdi
addq $0x40, %rdi
movq %rax, -0x40(%rdi)
movq $-0x1, -0x38(%rdi)
xorps %xmm0, %xmm0
movups %xmm0, -0x30(%rdi)
movups %xmm0, -0x20(%rdi)
movq %rax, -0x10(%rdi)
movabsq $-0xffff00000001, %rax  # imm = 0xFFFF0000FFFFFFFF
movq %rax, -0x8(%rdi)
movl $0x100, %edx            # imm = 0x100
xorl %esi, %esi
callq 0x3130
decl 0x9e4(%r15)
movq 0x98(%rbp), %rsi
addq %r14, %rsi
movq %r15, %rdi
callq 0xf958
jmp 0xf76a
movq 0x9f0(%r15), %rcx
leaq (%r10,%r10,4), %rdx
shlq $0x6, %rdx
movq 0x10(%rcx,%rdx), %rdi
andl $0xfff, %edi            # imm = 0xFFF
orq %rax, %rdi
movq %rdi, 0x18(%rcx,%rdx)
movb $0x2, 0x3c(%rcx,%rdx)
movl (%r15), %eax
leaq 0x717b1(%rip), %rdi     # 0x80ec0
movq (%rdi,%rax,8), %rax
movq %rax, 0x28(%rcx,%rdx)
leaq 0x349c(%r15), %rax
movl 0x349c(%r15), %ecx
movl %r10d, 0x3378(%r15,%rcx,4)
movl $0x48, %ecx
movl (%rax), %edx
incl %edx
xorl %edi, %edi
cmpl %ecx, %edx
cmovnel %edx, %edi
movl %edi, (%rax)
movq %r15, %rdi
callq 0xf816
movq 0x98(%rbp), %rax
movq 0x378(%rax,%r14), %rax
movq 0x9b8(%r15), %rcx
imulq $0x758, %r12, %rdx      # imm = 0x758
movq %rax, 0x40(%rcx,%rdx)
addq 0x98(%rbp), %r14
movq %rbp, %rdi
movq %r14, %rsi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xc3e6
leaq 0x48d6(%rip), %rdi      # 0x14067
leaq 0x551e(%rip), %rsi      # 0x14cb6
leaq 0x57ef(%rip), %rcx      # 0x14f8e
movl $0x61b, %edx            # imm = 0x61B
callq 0x3160
leaq 0x48b7(%rip), %rdi      # 0x14067
leaq 0x54ff(%rip), %rsi      # 0x14cb6
leaq 0x57d0(%rip), %rcx      # 0x14f8e
movl $0x654, %edx            # imm = 0x654
callq 0x3160
movq 0xa821(%rip), %rdi      # 0x19ff0
leaq 0x574b(%rip), %rsi      # 0x14f21
callq 0x3250
movq 0x9b8(%r15), %rcx
movq (%rcx,%r12), %rsi
movq %rax, %rdi
callq 0x3090
movq %rax, %rdi
callq 0x3110
leaq 0x486a(%rip), %rdi      # 0x14067
leaq 0x54b2(%rip), %rsi      # 0x14cb6
leaq 0x5783(%rip), %rcx      # 0x14f8e
movl $0x65e, %edx            # imm = 0x65E
callq 0x3160
nop