// File: 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:
subq $0x38, %rsp
movb %dl, %al
movq %rdi, 0x30(%rsp)
movq %rsi, 0x28(%rsp)
movb %al, 0x27(%rsp)
movq 0x30(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x28(%rsp), %rax
movl 0x2c(%rax), %eax
movl %eax, 0x20(%rsp)
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rax
movl 0x20(%rsp), %ecx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x10(%rax), %eax
movl %eax, 0x1c(%rsp)
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rax
movl 0x20(%rsp), %ecx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x33c(%rax), %eax
movl %eax, 0x18(%rsp)
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rax
movl 0x20(%rsp), %ecx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x338(%rax), %eax
movl %eax, 0x14(%rsp)
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rax
movl 0x20(%rsp), %ecx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movzbl 0x32f(%rax), %eax
cmpl $0x1, %eax
je 0x1a587
movq 0x8(%rsp), %rdi
movl 0x1c(%rsp), %eax
movl %eax, 0x4(%rsp)
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rax
movl 0x20(%rsp), %ecx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movq 0x368(%rax), %rsi
callq 0x15e60
movl %eax, %ecx
movl 0x4(%rsp), %eax
cmpl %ecx, %eax
je 0x1a585
leaq 0x8a97(%rip), %rdi      # 0x23004
leaq 0x9641(%rip), %rsi      # 0x23bb5
movl $0x61b, %edx            # imm = 0x61B
leaq 0x990d(%rip), %rcx      # 0x23e8d
callq 0x3160
jmp 0x1a587
cmpb $0x0, 0x27(%rsp)
je 0x1a80b
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rax
movl 0x20(%rsp), %ecx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movzbl 0x32f(%rax), %eax
cmpl $0x1, %eax
jne 0x1a6c4
movq 0x8(%rsp), %rax
movq 0x28(%rsp), %rcx
movq 0x98(%rcx), %rcx
movl 0x20(%rsp), %edx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movq 0x358(%rcx), %rdx
shlq $0xc, %rdx
movq 0xa28(%rax), %rcx
movl 0x18(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rcx
movq 0x10(%rcx), %rcx
andq $0xfff, %rcx            # imm = 0xFFF
orq %rcx, %rdx
movq 0xa28(%rax), %rcx
movl 0x18(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rcx
movq %rdx, 0x18(%rcx)
movq 0xa28(%rax), %rcx
movl 0x18(%rsp), %edx
imulq $0x140, %rdx, %rdx      # imm = 0x140
addq %rdx, %rcx
movb $0x2, 0x3c(%rcx)
movl (%rax), %ecx
movl %ecx, %edx
leaq 0x7587a(%rip), %rcx     # 0x8fec0
movq (%rcx,%rdx,8), %rdx
movq 0xa28(%rax), %rcx
movl 0x18(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rcx
movq %rdx, 0x28(%rcx)
movl 0x18(%rsp), %edx
movl 0x366c(%rax), %ecx
movl %edx, 0x3588(%rax,%rcx,4)
movl 0x366c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x366c(%rax)
cmpl $0x38, 0x366c(%rax)
jne 0x1a69b
movq 0x8(%rsp), %rax
movl $0x0, 0x366c(%rax)
movq 0x8(%rsp), %rdi
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rsi
movl 0x20(%rsp), %eax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
callq 0x1aa50
jmp 0x1a7c7
movq 0x8(%rsp), %rax
movq 0x28(%rsp), %rcx
movq 0x98(%rcx), %rcx
movl 0x20(%rsp), %edx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movq 0x358(%rcx), %rdx
shlq $0xc, %rdx
movq 0x9f0(%rax), %rcx
movl 0x14(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rcx
movq 0x10(%rcx), %rcx
andq $0xfff, %rcx            # imm = 0xFFF
orq %rcx, %rdx
movq 0x9f0(%rax), %rcx
movl 0x14(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rcx
movq %rdx, 0x18(%rcx)
movq 0x9f0(%rax), %rcx
movl 0x14(%rsp), %edx
imulq $0x140, %rdx, %rdx      # imm = 0x140
addq %rdx, %rcx
movb $0x2, 0x3c(%rcx)
movl (%rax), %ecx
movl %ecx, %edx
leaq 0x75772(%rip), %rcx     # 0x8fec0
movq (%rcx,%rdx,8), %rdx
movq 0x9f0(%rax), %rcx
movl 0x14(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rcx
movq %rdx, 0x28(%rcx)
movl 0x14(%rsp), %edx
movl 0x349c(%rax), %ecx
movl %edx, 0x3378(%rax,%rcx,4)
movl 0x349c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x349c(%rax)
cmpl $0x48, 0x349c(%rax)
jne 0x1a7a3
movq 0x8(%rsp), %rax
movl $0x0, 0x349c(%rax)
movq 0x8(%rsp), %rdi
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rsi
movl 0x20(%rsp), %eax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
callq 0x1aa50
movq 0x8(%rsp), %rax
movq 0x28(%rsp), %rcx
movq 0x98(%rcx), %rcx
movl 0x20(%rsp), %edx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movq 0x378(%rcx), %rcx
movq 0x9b8(%rax), %rax
movl 0x1c(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rax
movq %rcx, 0x40(%rax)
jmp 0x1aa23
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rax
movl 0x20(%rsp), %ecx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movzbl 0x32f(%rax), %eax
cmpl $0x1, %eax
jne 0x1a85a
movq 0x8(%rsp), %rdi
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rsi
movl 0x20(%rsp), %eax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
callq 0x1acc0
jmp 0x1aa21
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rax
movl 0x20(%rsp), %ecx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
cmpb $0x0, 0x32b(%rax)
je 0x1a89c
leaq 0x8780(%rip), %rdi      # 0x23004
leaq 0x932a(%rip), %rsi      # 0x23bb5
movl $0x654, %edx            # imm = 0x654
leaq 0x95f6(%rip), %rcx      # 0x23e8d
callq 0x3160
movq 0x8(%rsp), %rax
movq 0x9f0(%rax), %rcx
movl 0x14(%rsp), %edx
imulq $0x140, %rdx, %rdx      # imm = 0x140
addq %rdx, %rcx
movb $0x2, 0x3d(%rcx)
movl (%rax), %ecx
movl %ecx, %edx
leaq 0x755fb(%rip), %rcx     # 0x8fec0
movq (%rcx,%rdx,8), %rdx
movq 0x9f0(%rax), %rcx
movl 0x14(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rcx
movq %rdx, 0x28(%rcx)
movq 0x9b8(%rax), %rcx
movl 0x1c(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rcx
movl 0x70(%rcx), %edx
addl $-0x1, %edx
movl %edx, 0x70(%rcx)
movq 0x28(%rsp), %rcx
movq 0x98(%rcx), %rcx
movl 0x20(%rsp), %edx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movq 0x378(%rcx), %rdx
movq 0x9b8(%rax), %rcx
movl 0x1c(%rsp), %esi
imulq $0x758, %rsi, %rsi      # imm = 0x758
addq %rsi, %rcx
movq %rdx, 0x40(%rcx)
movq 0x9b8(%rax), %rax
movl 0x1c(%rsp), %ecx
imulq $0x758, %rcx, %rcx      # imm = 0x758
addq %rcx, %rax
cmpl $0x0, 0x70(%rax)
jge 0x1a9bb
movq 0xe694(%rip), %rdi      # 0x28ff0
leaq 0x94bd(%rip), %rsi      # 0x23e20
callq 0x3220
movq %rax, %rdi
movq 0x8(%rsp), %rax
movq 0x9b8(%rax), %rax
movl 0x1c(%rsp), %ecx
imulq $0x758, %rcx, %rcx      # imm = 0x758
addq %rcx, %rax
movq (%rax), %rsi
callq 0x3080
movq %rax, %rdi
movq 0xe621(%rip), %rsi      # 0x28fb8
callq 0x3250
leaq 0x8661(%rip), %rdi      # 0x23004
leaq 0x920b(%rip), %rsi      # 0x23bb5
movl $0x65e, %edx            # imm = 0x65E
leaq 0x94d7(%rip), %rcx      # 0x23e8d
callq 0x3160
movq 0x8(%rsp), %rax
movq 0x9b8(%rax), %rax
movl 0x1c(%rsp), %ecx
imulq $0x758, %rcx, %rcx      # imm = 0x758
addq %rcx, %rax
cmpl $0x0, 0x70(%rax)
jne 0x1a9ef
movq 0x8(%rsp), %rax
movl 0x924(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x924(%rax)
movq 0x8(%rsp), %rdi
movl 0x14(%rsp), %esi
callq 0x191c0
movq 0x8(%rsp), %rdi
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rsi
movl 0x20(%rsp), %eax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
callq 0x1acc0
jmp 0x1aa23
movq 0x28(%rsp), %rdi
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rsi
movl 0x20(%rsp), %eax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rsi
callq 0x150e0
addq $0x38, %rsp
retq
nopl (%rax)