// File: /workspace/github_cpp_makefile_star2_O2/NishadSaraf[P]Championship-Simulator/src/ooo_cpu.cc
// Function: O3_CPU::execute_store(unsigned int, unsigned int, unsigned int)
void O3_CPU::execute_store(uint32_t rob_index, uint32_t sq_index, uint32_t data_index)
{
    SQ.entry[sq_index].fetched = COMPLETED;
    SQ.entry[sq_index].event_cycle = current_core_cycle[cpu];

    ROB.entry[rob_index].num_mem_ops--;
    ROB.entry[rob_index].event_cycle = current_core_cycle[cpu];
    if (ROB.entry[rob_index].num_mem_ops < 0) {
        cerr << "instr_id: " << ROB.entry[rob_index].instr_id << endl;
        assert(0);
    }
    if (ROB.entry[rob_index].num_mem_ops == 0)
        inflight_mem_executions++;

    DP (if (warmup_complete[cpu]) {
    cout << "[SQ1] " << __func__ << " instr_id: " << SQ.entry[sq_index].instr_id << hex;
    cout << " full_address: " << SQ.entry[sq_index].physical_address << dec << " remain_mem_ops: " << ROB.entry[rob_index].num_mem_ops;
    cout << " event_cycle: " << SQ.entry[sq_index].event_cycle << endl; });

    // resolve RAW dependency after DTLB access
    // check if this store has dependent loads
    if (ROB.entry[rob_index].is_producer) {

        for (uint32_t dependent=0; dependent<ROB_SIZE; dependent++) {
            if (ROB.entry[rob_index].memory_instrs_depend_on_me[dependent]) {

                // check if dependent loads are already added in the load queue
                for (uint32_t j=0; j<NUM_INSTR_SOURCES; j++) { // which one is dependent?
                    if (ROB.entry[dependent].source_memory[j] && ROB.entry[dependent].source_added[j]) {
                        if (ROB.entry[dependent].source_memory[j] == SQ.entry[sq_index].virtual_address) { // this is required since a single instruction can issue multiple loads

                            // now we can resolve RAW dependency
                            uint32_t lq_index = ROB.entry[dependent].lq_index[j];
#ifdef SANITY_CHECK
                            if (lq_index >= LQ.SIZE)
                                assert(0);
                            if (LQ.entry[lq_index].producer_id != SQ.entry[sq_index].instr_id) {
                                cerr << "[SQ2] " << __func__ << " lq_index: " << lq_index << " producer_id: " << LQ.entry[lq_index].producer_id;
                                cerr << " does not match to the store instr_id: " << SQ.entry[sq_index].instr_id << endl;
                                assert(0);
                            }
#endif

                            // update correspodning LQ entry
                            LQ.entry[lq_index].physical_address = (SQ.entry[sq_index].physical_address & ~(uint64_t) ((1 << LOG2_BLOCK_SIZE) - 1)) | (LQ.entry[lq_index].virtual_address & ((1 << LOG2_BLOCK_SIZE) - 1));
                            LQ.entry[lq_index].translated = COMPLETED;
                            LQ.entry[lq_index].fetched = COMPLETED;
                            LQ.entry[lq_index].event_cycle = current_core_cycle[cpu];

                            uint32_t fwr_rob_index = LQ.entry[lq_index].rob_index;
                            ROB.entry[fwr_rob_index].num_mem_ops--;
                            ROB.entry[fwr_rob_index].event_cycle = current_core_cycle[cpu];
#ifdef SANITY_CHECK
                            if (ROB.entry[fwr_rob_index].num_mem_ops < 0) {
                                cerr << "instr_id: " << ROB.entry[fwr_rob_index].instr_id << endl;
                                assert(0);
                            }
#endif
                            if (ROB.entry[fwr_rob_index].num_mem_ops == 0)
                                inflight_mem_executions++;

                            DP(if(warmup_complete[cpu]) {
                            cout << "[LQ3] " << __func__ << " instr_id: " << LQ.entry[lq_index].instr_id << hex;
                            cout << " full_addr: " << LQ.entry[lq_index].physical_address << dec << " is forwarded by store instr_id: ";
                            cout << SQ.entry[sq_index].instr_id << " remain_num_ops: " << ROB.entry[fwr_rob_index].num_mem_ops << " cycle: " << current_core_cycle[cpu] << endl; });

                            release_load_queue(lq_index);

                            // clear dependency bit
                            if (j == (NUM_INSTR_SOURCES-1))
                                ROB.entry[rob_index].memory_instrs_depend_on_me[dependent] = 0;
                        }
                    }
                }
            }
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
movq 0xa28(%rdi), %rax
movl %edx, %ecx
imulq $0x140, %rcx, %r12      # imm = 0x140
movb $0x2, 0x3d(%rax,%r12)
movl (%rdi), %ecx
leaq 0x711fc(%rip), %rdx     # 0x7ceb0
movq (%rdx,%rcx,8), %rdx
movq %rdx, 0x28(%rax,%r12)
movq 0x9b8(%rdi), %rax
movl %esi, %ecx
imulq $0x758, %rcx, %rdi      # imm = 0x758
movl 0x70(%rax,%rdi), %esi
leal -0x1(%rsi), %ecx
movl %ecx, 0x70(%rax,%rdi)
movq %rdi, 0x8(%rsp)
movq %rdx, 0x40(%rax,%rdi)
testl %esi, %esi
jle 0xbf7b
testl %ecx, %ecx
jne 0xbcf4
incl 0x924(%rbx)
movq 0x8(%rsp), %rcx
cmpb $0x0, 0x56(%rax,%rcx)
je 0xbe55
xorl %ebp, %ebp
xorl %ecx, %ecx
cmpq $0x100, %rcx            # imm = 0x100
je 0xbe55
movq 0x9b8(%rbx), %rax
addq 0x8(%rsp), %rax
movq %rcx, 0x10(%rsp)
cmpb $0x0, 0x628(%rcx,%rax)
je 0xbe41
xorl %r15d, %r15d
cmpq $0x4, %r15
je 0xbe41
movq 0x9b8(%rbx), %rax
leaq (%rax,%rbp), %rcx
movq 0x5c8(%rcx,%r15,8), %rsi
testq %rsi, %rsi
je 0xbe39
cmpb $0x0, 0x4e(%r15,%rcx)
je 0xbe39
movq 0xa28(%rbx), %rdx
cmpq 0x10(%rdx,%r12), %rsi
jne 0xbe39
movl 0x728(%rcx,%r15,4), %r14d
cmpl 0x9e0(%rbx), %r14d
jae 0xbe64
addq %r12, %rdx
movq 0x9f0(%rbx), %rcx
imulq $0x140, %r14, %r13      # imm = 0x140
movq 0x8(%rcx,%r13), %rsi
cmpq (%rdx), %rsi
jne 0xbed0
leaq (%rcx,%r13), %rsi
movq 0x18(%rdx), %rdx
andq $-0x40, %rdx
movq 0x10(%rsi), %rdi
andl $0x3f, %edi
orq %rdx, %rdi
movq %rdi, 0x18(%rsi)
movw $0x202, 0x3c(%rcx,%r13) # imm = 0x202
movl (%rbx), %edx
leaq 0x710d6(%rip), %rsi     # 0x7ceb0
movq (%rsi,%rdx,8), %rdx
movq %rdx, 0x28(%rcx,%r13)
movl 0x30(%rcx,%r13), %ecx
imulq $0x758, %rcx, %r13      # imm = 0x758
movl 0x70(%rax,%r13), %esi
leal -0x1(%rsi), %ecx
movl %ecx, 0x70(%rax,%r13)
movq %rdx, 0x40(%rax,%r13)
testl %esi, %esi
jle 0xbe83
testl %ecx, %ecx
jne 0xbe0f
incl 0x924(%rbx)
movq %rbx, %rdi
movl %r14d, %esi
callq 0xbc36
cmpq $0x3, %r15
jne 0xbe39
movq 0x9b8(%rbx), %rax
addq 0x8(%rsp), %rax
movq 0x10(%rsp), %rcx
movb $0x0, 0x628(%rcx,%rax)
incq %r15
jmp 0xbd37
movq 0x10(%rsp), %rcx
incq %rcx
addq $0x758, %rbp            # imm = 0x758
jmp 0xbd08
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x41fc(%rip), %rdi      # 0x10067
leaq 0x4d7c(%rip), %rsi      # 0x10bee
leaq 0x4f66(%rip), %rcx      # 0x10ddf
movl $0x516, %edx            # imm = 0x516
callq 0x2160
movq 0xa166(%rip), %rdi      # 0x15ff0
leaq 0x4fc8(%rip), %rsi      # 0x10e59
callq 0x2230
movq 0x9b8(%rbx), %rcx
movq (%rcx,%r13), %rsi
movq %rax, %rdi
callq 0x2080
movq %rax, %rdi
callq 0x2110
leaq 0x41af(%rip), %rdi      # 0x10067
leaq 0x4d2f(%rip), %rsi      # 0x10bee
leaq 0x4f19(%rip), %rcx      # 0x10ddf
movl $0x52a, %edx            # imm = 0x52A
callq 0x2160
movq 0xa119(%rip), %r15      # 0x15ff0
leaq 0x4f3a(%rip), %rsi      # 0x10e18
movq %r15, %rdi
callq 0x2230
leaq 0x4f32(%rip), %rsi      # 0x10e1f
movq %rax, %rdi
callq 0x2230
leaq 0x4784(%rip), %rsi      # 0x10680
movq %rax, %rdi
callq 0x2230
movq %rax, %rdi
movl %r14d, %esi
callq 0x22a0
leaq 0x4f17(%rip), %rsi      # 0x10e2d
movq %rax, %rdi
callq 0x2230
movq 0x9f0(%rbx), %rcx
movq 0x8(%rcx,%r13), %rsi
movq %rax, %rdi
callq 0x2080
leaq 0x4f03(%rip), %rsi      # 0x10e3c
movq %r15, %rdi
callq 0x2230
movq 0xa28(%rbx), %rcx
movq (%rcx,%r12), %rsi
movq %rax, %rdi
callq 0x2080
movq %rax, %rdi
callq 0x2110
leaq 0x4104(%rip), %rdi      # 0x10067
leaq 0x4c84(%rip), %rsi      # 0x10bee
leaq 0x4e6e(%rip), %rcx      # 0x10ddf
movl $0x51a, %edx            # imm = 0x51A
callq 0x2160
movq 0xa06e(%rip), %rdi      # 0x15ff0
leaq 0x4ed0(%rip), %rsi      # 0x10e59
callq 0x2230
movq 0x9b8(%rbx), %rcx
movq 0x8(%rsp), %rdx
movq (%rcx,%rdx), %rsi
movq %rax, %rdi
callq 0x2080
movq %rax, %rdi
callq 0x2110
leaq 0x40b2(%rip), %rdi      # 0x10067
leaq 0x4c32(%rip), %rsi      # 0x10bee
leaq 0x4e1c(%rip), %rcx      # 0x10ddf
movl $0x4fc, %edx            # imm = 0x4FC
callq 0x2160
nop