// File: NishadSaraf[P]Championship-Simulator/src/ooo_cpu.cc
// Function: O3_CPU::add_store_queue(unsigned int, unsigned int)
void O3_CPU::add_store_queue(uint32_t rob_index, uint32_t data_index)
{
    uint32_t sq_index = SQ.tail;
#ifdef SANITY_CHECK
    if (SQ.entry[sq_index].virtual_address)
        assert(0);
#endif

    /*
    // search for an empty slot 
    uint32_t sq_index = SQ.SIZE;
    for (uint32_t i=0; i<SQ.SIZE; i++) {
        if (SQ.entry[i].virtual_address == 0) {
            sq_index = i;
            break;
        }
    }

    // sanity check
    if (sq_index == SQ.SIZE) {
        cerr << "instr_id: " << ROB.entry[rob_index].instr_id << " no empty slot in the store queue!!!" << endl;
        assert(0);
    }
    */

    // add it to the store queue
    ROB.entry[rob_index].sq_index[data_index] = sq_index;
    SQ.entry[sq_index].instr_id = ROB.entry[rob_index].instr_id;
    SQ.entry[sq_index].virtual_address = ROB.entry[rob_index].destination_memory[data_index];
    SQ.entry[sq_index].ip = ROB.entry[rob_index].ip;
    SQ.entry[sq_index].data_index = data_index;
    SQ.entry[sq_index].rob_index = rob_index;
    SQ.entry[sq_index].asid[0] = ROB.entry[rob_index].asid[0];
    SQ.entry[sq_index].asid[1] = ROB.entry[rob_index].asid[1];
    SQ.entry[sq_index].event_cycle = current_core_cycle[cpu] + SCHEDULING_LATENCY;

    SQ.occupancy++;
    SQ.tail++;
    if (SQ.tail == SQ.SIZE)
        SQ.tail = 0;

    // succesfully added to the store queue
    ROB.entry[rob_index].destination_added[data_index] = 1;
    
    STA[STA_head] = UINT64_MAX;
    STA_head++;
    if (STA_head == STA_SIZE)
        STA_head = 0;

    RTS0[RTS0_tail] = sq_index;
    RTS0_tail++;
    if (RTS0_tail == SQ_SIZE)
        RTS0_tail = 0;

    DP(if(warmup_complete[cpu]) {
    cout << "[SQ] " << __func__ << " instr_id: " << SQ.entry[sq_index].instr_id;
    cout << " is added in the SQ translated: " << +SQ.entry[sq_index].translated << " fetched: " << +SQ.entry[sq_index].fetched << " is_producer: " << +ROB.entry[rob_index].is_producer;
    cout << " cycle: " << current_core_cycle[cpu] << endl; });
}

// Assembly:
subq $0x28, %rsp
movq %rdi, 0x20(%rsp)
movl %esi, 0x1c(%rsp)
movl %edx, 0x18(%rsp)
movq 0x20(%rsp), %rax
movq %rax, 0x8(%rsp)
movl 0xa24(%rax), %ecx
movl %ecx, 0x14(%rsp)
movq 0xa28(%rax), %rax
movl 0x14(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
cmpq $0x0, 0x10(%rax)
je 0x18df0
leaq 0xa22c(%rip), %rdi      # 0x23004
leaq 0xadd6(%rip), %rsi      # 0x23bb5
movl $0x410, %edx            # imm = 0x410
leaq 0xaf8a(%rip), %rcx      # 0x23d75
callq 0x3160
movq 0x8(%rsp), %rcx
movl 0x14(%rsp), %esi
movq 0x9b8(%rcx), %rax
movl 0x1c(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rax
movl 0x18(%rsp), %edx
movl %esi, 0x738(%rax,%rdx,4)
movq 0x9b8(%rcx), %rax
movl 0x1c(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rax
movq (%rax), %rdx
movq 0xa28(%rcx), %rax
movl 0x14(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rax
movq %rdx, (%rax)
movq 0x9b8(%rcx), %rax
movl 0x1c(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rax
movl 0x18(%rsp), %edx
movq 0x5a8(%rax,%rdx,8), %rdx
movq 0xa28(%rcx), %rax
movl 0x14(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rax
movq %rdx, 0x10(%rax)
movq 0x9b8(%rcx), %rax
movl 0x1c(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rax
movq 0x8(%rax), %rdx
movq 0xa28(%rcx), %rax
movl 0x14(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rax
movq %rdx, 0x20(%rax)
movl 0x18(%rsp), %edx
movq 0xa28(%rcx), %rax
movl 0x14(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rax
movl %edx, 0x34(%rax)
movl 0x1c(%rsp), %edx
movq 0xa28(%rcx), %rax
movl 0x14(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rax
movl %edx, 0x30(%rax)
movq 0x9b8(%rcx), %rax
movl 0x1c(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rax
movb 0x5b(%rax), %dl
movq 0xa28(%rcx), %rax
movl 0x14(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rax
movb %dl, 0x3e(%rax)
movq 0x9b8(%rcx), %rax
movl 0x1c(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rax
movb 0x5c(%rax), %dl
movq 0xa28(%rcx), %rax
movl 0x14(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rax
movb %dl, 0x3f(%rax)
movl (%rcx), %eax
movl %eax, %edx
leaq 0x76f68(%rip), %rax     # 0x8fec0
movq (%rax,%rdx,8), %rdx
movl 0x76f6e(%rip), %eax     # 0x8fed0
addq %rax, %rdx
movq 0xa28(%rcx), %rax
movl 0x14(%rsp), %esi
imulq $0x140, %rsi, %rsi      # imm = 0x140
addq %rsi, %rax
movq %rdx, 0x28(%rax)
movl 0xa1c(%rcx), %eax
addl $0x1, %eax
movl %eax, 0xa1c(%rcx)
movl 0xa24(%rcx), %eax
addl $0x1, %eax
movl %eax, 0xa24(%rcx)
movl 0xa24(%rcx), %eax
cmpl 0xa18(%rcx), %eax
jne 0x18fb9
movq 0x8(%rsp), %rax
movl $0x0, 0xa24(%rax)
movq 0x8(%rsp), %rax
movq 0x9b8(%rax), %rcx
movl 0x1c(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rcx
movl 0x18(%rsp), %edx
movb $0x1, 0x52(%rcx,%rdx)
movq 0x2a30(%rax), %rcx
movq $-0x1, 0xa30(%rax,%rcx,8)
movq 0x2a30(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x2a30(%rax)
cmpq $0x400, 0x2a30(%rax) # imm = 0x400
jne 0x1901e
movq 0x8(%rsp), %rax
movq $0x0, 0x2a30(%rax)
movq 0x8(%rsp), %rax
movl 0x14(%rsp), %edx
movl 0x3584(%rax), %ecx
movl %edx, 0x34a0(%rax,%rcx,4)
movl 0x3584(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x3584(%rax)
cmpl $0x38, 0x3584(%rax)
jne 0x1905b
movq 0x8(%rsp), %rax
movl $0x0, 0x3584(%rax)
addq $0x28, %rsp
retq