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

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

    // update ROB entry
    if (is_it_tlb) {
        ROB.entry[rob_index].translated = COMPLETED;
        ROB.entry[rob_index].instruction_pa = (queue->entry[index].instruction_pa << PAGE_SHIFT) | (ROB.entry[rob_index].ip & ((1 << PAGE_SHIFT) - 1)); // translated address
    }
    else
        ROB.entry[rob_index].fetched = COMPLETED;
    ROB.entry[rob_index].event_cycle = current_core_cycle[cpu];
    num_fetched++;

    DP ( if (warmup_complete[cpu]) {
    cout << "[" << queue->NAME << "] " << __func__ << " cpu: " << cpu <<  " instr_id: " << ROB.entry[rob_index].instr_id;
    cout << " ip: " << hex << ROB.entry[rob_index].ip << " address: " << ROB.entry[rob_index].instruction_pa << dec;
    cout << " translated: " << +ROB.entry[rob_index].translated << " fetched: " << +ROB.entry[rob_index].fetched;
    cout << " event_cycle: " << ROB.entry[rob_index].event_cycle << endl; });

    // check if other instructions were merged
    if (queue->entry[index].instr_merged) {
        for (uint32_t i=0; i<ROB_SIZE; i++) {
            if (queue->entry[index].rob_index_depend_on_me[i]) {

                // update ROB entry
                if (is_it_tlb) {
                    ROB.entry[i].translated = COMPLETED;
                    ROB.entry[i].instruction_pa = (queue->entry[index].instruction_pa << PAGE_SHIFT) | (ROB.entry[i].ip & ((1 << PAGE_SHIFT) - 1)); // translated address
                }
                else
                    ROB.entry[i].fetched = COMPLETED;
                ROB.entry[i].event_cycle = current_core_cycle[cpu] + (num_fetched / FETCH_WIDTH);
                num_fetched++;

                DP ( if (warmup_complete[cpu]) {
                cout << "[" << queue->NAME << "] " << __func__ << " cpu: " << cpu <<  " instr_id: " << ROB.entry[i].instr_id;
                cout << " ip: " << hex << ROB.entry[i].ip << " address: " << ROB.entry[i].instruction_pa << dec;
                cout << " translated: " << +ROB.entry[i].translated << " fetched: " << +ROB.entry[i].fetched << " provider: " << ROB.entry[rob_index].instr_id;
                cout << " event_cycle: " << ROB.entry[i].event_cycle << endl; });
            }
        }
    }

    // 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), %rdi
movq %rdi, 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)
movl $0x0, 0x18(%rsp)
movl 0x1c(%rsp), %eax
movl %eax, 0x10(%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 0x10(%rsp), %eax
cmpl %ecx, %eax
je 0x1a1ea
leaq 0x8e32(%rip), %rdi      # 0x23004
leaq 0x99dc(%rip), %rsi      # 0x23bb5
movl $0x5e2, %edx            # imm = 0x5E2
leaq 0x9c6d(%rip), %rcx      # 0x23e52
callq 0x3160
cmpb $0x0, 0x27(%rsp)
je 0x1a279
movq 0x8(%rsp), %rax
movq 0x9b8(%rax), %rcx
movl 0x1c(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rcx
movb $0x2, 0x4c(%rcx)
movq 0x28(%rsp), %rcx
movq 0x98(%rcx), %rcx
movl 0x20(%rsp), %edx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movq 0x350(%rcx), %rcx
shlq $0xc, %rcx
movq 0x9b8(%rax), %rdx
movl 0x1c(%rsp), %esi
imulq $0x758, %rsi, %rsi      # imm = 0x758
addq %rsi, %rdx
movq 0x8(%rdx), %rdx
andq $0xfff, %rdx            # imm = 0xFFF
orq %rdx, %rcx
movq 0x9b8(%rax), %rax
movl 0x1c(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rax
movq %rcx, 0x588(%rax)
jmp 0x1a29a
movq 0x8(%rsp), %rax
movq 0x9b8(%rax), %rax
movl 0x1c(%rsp), %ecx
imulq $0x758, %rcx, %rcx      # imm = 0x758
addq %rcx, %rax
movl $0x2, 0x64(%rax)
movq 0x8(%rsp), %rax
movl (%rax), %ecx
movl %ecx, %edx
leaq 0x75c16(%rip), %rcx     # 0x8fec0
movq (%rcx,%rdx,8), %rcx
movq 0x9b8(%rax), %rax
movl 0x1c(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rax
movq %rcx, 0x40(%rax)
movl 0x18(%rsp), %eax
addl $0x1, %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
cmpb $0x0, 0x329(%rax)
je 0x1a440
movl $0x0, 0x14(%rsp)
cmpl $0x100, 0x14(%rsp)      # imm = 0x100
jae 0x1a43e
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rax
movl 0x20(%rsp), %ecx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movl 0x14(%rsp), %ecx
cmpb $0x0, 0x29(%rax,%rcx)
je 0x1a42c
cmpb $0x0, 0x27(%rsp)
je 0x1a3c7
movq 0x8(%rsp), %rax
movq 0x9b8(%rax), %rcx
movl 0x14(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rcx
movb $0x2, 0x4c(%rcx)
movq 0x28(%rsp), %rcx
movq 0x98(%rcx), %rcx
movl 0x20(%rsp), %edx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movq 0x350(%rcx), %rcx
shlq $0xc, %rcx
movq 0x9b8(%rax), %rdx
movl 0x14(%rsp), %esi
imulq $0x758, %rsi, %rsi      # imm = 0x758
addq %rsi, %rdx
movq 0x8(%rdx), %rdx
andq $0xfff, %rdx            # imm = 0xFFF
orq %rdx, %rcx
movq 0x9b8(%rax), %rax
movl 0x14(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rax
movq %rcx, 0x588(%rax)
jmp 0x1a3e8
movq 0x8(%rsp), %rax
movq 0x9b8(%rax), %rax
movl 0x14(%rsp), %ecx
imulq $0x758, %rcx, %rcx      # imm = 0x758
addq %rcx, %rax
movl $0x2, 0x64(%rax)
movq 0x8(%rsp), %rax
movl (%rax), %ecx
movl %ecx, %edx
leaq 0x75ac8(%rip), %rcx     # 0x8fec0
movq (%rcx,%rdx,8), %rcx
movl 0x18(%rsp), %edx
shrl $0x2, %edx
movl %edx, %edx
addq %rdx, %rcx
movq 0x9b8(%rax), %rax
movl 0x14(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rax
movq %rcx, 0x40(%rax)
movl 0x18(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x18(%rsp)
jmp 0x1a42e
movl 0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14(%rsp)
jmp 0x1a301
jmp 0x1a440
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)