// File: /workspace/github_cpp_makefile_star2_O3/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
pushq %rax
movq %rdi, %rbx
movq 0xa28(%rdi), %rax
movl %edx, %ecx
leaq (%rcx,%rcx,4), %r8
shlq $0x6, %r8
movb $0x2, 0x3d(%rax,%r8)
movl (%rdi), %ecx
leaq 0x724e6(%rip), %rdx     # 0x80ec0
movq (%rdx,%rcx,8), %rdx
movq %rdx, 0x28(%rax,%r8)
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, (%rsp)
movq %rdx, 0x40(%rax,%rdi)
testl %esi, %esi
jle 0xecd0
testl %ecx, %ecx
jne 0xea19
incl 0x924(%rbx)
movq (%rsp), %rcx
cmpb $0x0, 0x56(%rax,%rcx)
je 0xeba7
xorl %r13d, %r13d
xorl %r15d, %r15d
movq 0x9b8(%rbx), %rax
addq (%rsp), %rax
cmpb $0x0, 0x628(%r15,%rax)
je 0xeb78
xorl %ebp, %ebp
movq 0x9b8(%rbx), %rax
leaq (%rax,%r13), %rcx
movq 0x5c8(%rcx,%rbp,8), %rsi
testq %rsi, %rsi
je 0xeb6b
cmpb $0x0, 0x4e(%rbp,%rcx)
je 0xeb6b
movq 0xa28(%rbx), %rdx
cmpq 0x10(%rdx,%r8), %rsi
jne 0xeb6b
movl 0x728(%rcx,%rbp,4), %r14d
cmpl 0x9e0(%rbx), %r14d
jae 0xec03
addq %r8, %rdx
movq 0x9f0(%rbx), %rcx
leaq (%r14,%r14,4), %r12
shlq $0x6, %r12
movq 0x8(%rcx,%r12), %rsi
cmpq (%rdx), %rsi
jne 0xec22
leaq (%rcx,%r12), %rdi
movq 0x18(%rdx), %rdx
andq $-0x40, %rdx
movq 0x10(%rdi), %rsi
andl $0x3f, %esi
orq %rdx, %rsi
movq %rsi, 0x18(%rdi)
movw $0x202, 0x3c(%rcx,%r12) # imm = 0x202
movl (%rbx), %edx
leaq 0x723dd(%rip), %rsi     # 0x80ec0
movq (%rsi,%rdx,8), %rdx
movq %rdx, 0x28(%rcx,%r12)
movl 0x30(%rcx,%r12), %ecx
imulq $0x758, %rcx, %r14      # imm = 0x758
movl 0x70(%rax,%r14), %esi
leal -0x1(%rsi), %ecx
movl %ecx, 0x70(%rax,%r14)
movq %rdx, 0x40(%rax,%r14)
testl %esi, %esi
jle 0xebb6
movq %r8, %r14
testl %ecx, %ecx
jne 0xeb1f
incl 0x924(%rbx)
leaq 0x10(%rdi), %rax
xorl %ecx, %ecx
movq %rcx, (%rdi)
movq $-0x1, 0x8(%rdi)
movq %rcx, 0x20(%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rax)
movups %xmm0, (%rax)
movabsq $-0xffff00000001, %rax  # imm = 0xFFFF0000FFFFFFFF
movq %rax, 0x38(%rdi)
addq $0x40, %rdi
movl $0x100, %edx            # imm = 0x100
xorl %esi, %esi
callq 0x3130
decl 0x9e4(%rbx)
cmpq $0x3, %rbp
movq %r14, %r8
je 0xeb91
incq %rbp
cmpq $0x4, %rbp
jne 0xea4a
incq %r15
addq $0x758, %r13            # imm = 0x758
cmpq $0x100, %r15            # imm = 0x100
jne 0xea2e
jmp 0xeba7
movq 0x9b8(%rbx), %rax
addq (%rsp), %rax
movb $0x0, 0x628(%r15,%rax)
jmp 0xeb78
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0xb433(%rip), %rdi      # 0x19ff0
leaq 0x638d(%rip), %rsi      # 0x14f51
callq 0x3250
movq 0x9b8(%rbx), %rcx
movq (%rcx,%r14), %rsi
movq %rax, %rdi
callq 0x3090
movq %rax, %rdi
callq 0x3110
leaq 0x547c(%rip), %rdi      # 0x14067
leaq 0x60f4(%rip), %rsi      # 0x14ce6
leaq 0x62de(%rip), %rcx      # 0x14ed7
movl $0x52a, %edx            # imm = 0x52A
callq 0x3160
leaq 0x545d(%rip), %rdi      # 0x14067
leaq 0x60d5(%rip), %rsi      # 0x14ce6
leaq 0x62bf(%rip), %rcx      # 0x14ed7
movl $0x516, %edx            # imm = 0x516
callq 0x3160
movq 0xb3c7(%rip), %r15      # 0x19ff0
leaq 0x62e0(%rip), %rsi      # 0x14f10
movq %r15, %rdi
movq %r8, %r13
callq 0x3250
leaq 0x62d5(%rip), %rsi      # 0x14f17
movq %rax, %rdi
callq 0x3250
leaq 0x5a5f(%rip), %rsi      # 0x146b0
movq %rax, %rdi
callq 0x3250
movq %rax, %rdi
movl %r14d, %esi
callq 0x32d0
leaq 0x62ba(%rip), %rsi      # 0x14f25
movq %rax, %rdi
callq 0x3250
movq 0x9f0(%rbx), %rcx
movq 0x8(%rcx,%r12), %rsi
movq %rax, %rdi
callq 0x3090
leaq 0x62a6(%rip), %rsi      # 0x14f34
movq %r15, %rdi
callq 0x3250
movq 0xa28(%rbx), %rcx
movq (%rcx,%r13), %rsi
movq %rax, %rdi
callq 0x3090
movq %rax, %rdi
callq 0x3110
leaq 0x53af(%rip), %rdi      # 0x14067
leaq 0x6027(%rip), %rsi      # 0x14ce6
leaq 0x6211(%rip), %rcx      # 0x14ed7
movl $0x51a, %edx            # imm = 0x51A
callq 0x3160
movq 0xb319(%rip), %rdi      # 0x19ff0
leaq 0x6273(%rip), %rsi      # 0x14f51
callq 0x3250
movq 0x9b8(%rbx), %rcx
movq (%rsp), %rdx
movq (%rcx,%rdx), %rsi
movq %rax, %rdi
callq 0x3090
movq %rax, %rdi
callq 0x3110
leaq 0x535e(%rip), %rdi      # 0x14067
leaq 0x5fd6(%rip), %rsi      # 0x14ce6
leaq 0x61c0(%rip), %rcx      # 0x14ed7
movl $0x4fc, %edx            # imm = 0x4FC
callq 0x3160
nop