// File: NishadSaraf[P]Championship-Simulator/src/ooo_cpu.cc
// Function: O3_CPU::check_and_add_lsq(unsigned int)
uint32_t O3_CPU::check_and_add_lsq(uint32_t rob_index) 
{
    uint32_t num_mem_ops = 0, num_added = 0;

    // load
    for (uint32_t i=0; i<NUM_INSTR_SOURCES; i++) {
        if (ROB.entry[rob_index].source_memory[i]) {
            num_mem_ops++;
            if (ROB.entry[rob_index].source_added[i])
                num_added++;
            else if (LQ.occupancy < LQ.SIZE) {
                add_load_queue(rob_index, i);
                num_added++;
            }
            else {
                DP(if(warmup_complete[cpu]) {
                cout << "[LQ] " << __func__ << " instr_id: " << ROB.entry[rob_index].instr_id;
                cout << " cannot be added in the load queue occupancy: " << LQ.occupancy << " cycle: " << current_core_cycle[cpu] << endl; });
            }
        }
    }

    // store
    for (uint32_t i=0; i<MAX_INSTR_DESTINATIONS; i++) {
        if (ROB.entry[rob_index].destination_memory[i]) {
            num_mem_ops++;
            if (ROB.entry[rob_index].destination_added[i])
                num_added++;
            else if (SQ.occupancy < SQ.SIZE) {
                if (STA[STA_head] == ROB.entry[rob_index].instr_id) {
                    add_store_queue(rob_index, i);
                    num_added++;
                }
                //add_store_queue(rob_index, i);
                //num_added++;
            }
            else {
                DP(if(warmup_complete[cpu]) {
                cout << "[SQ] " << __func__ << " instr_id: " << ROB.entry[rob_index].instr_id;
                cout << " cannot be added in the store queue occupancy: " << SQ.occupancy << " cycle: " << current_core_cycle[cpu] << endl; });
            }
        }
    }

    if (num_added == num_mem_ops)
        return 0;

    uint32_t not_available = num_mem_ops - num_added;
    if (not_available > num_mem_ops) {
        cerr << "instr_id: " << ROB.entry[rob_index].instr_id << endl;
        assert(0);
    }

    return not_available;
}

// Assembly:
subq $0x38, %rsp
movq %rdi, 0x28(%rsp)
movl %esi, 0x24(%rsp)
movq 0x28(%rsp), %rax
movq %rax, 0x8(%rsp)
movl $0x0, 0x20(%rsp)
movl $0x0, 0x1c(%rsp)
movl $0x0, 0x18(%rsp)
cmpl $0x4, 0x18(%rsp)
jae 0x1835a
movq 0x8(%rsp), %rax
movq 0x9b8(%rax), %rax
movl 0x24(%rsp), %ecx
imulq $0x758, %rcx, %rcx      # imm = 0x758
addq %rcx, %rax
movl 0x18(%rsp), %ecx
cmpq $0x0, 0x5c8(%rax,%rcx,8)
je 0x18348
movq 0x8(%rsp), %rax
movl 0x20(%rsp), %ecx
addl $0x1, %ecx
movl %ecx, 0x20(%rsp)
movq 0x9b8(%rax), %rax
movl 0x24(%rsp), %ecx
imulq $0x758, %rcx, %rcx      # imm = 0x758
addq %rcx, %rax
movl 0x18(%rsp), %ecx
cmpb $0x0, 0x4e(%rax,%rcx)
je 0x18310
movl 0x1c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
jmp 0x18346
movq 0x8(%rsp), %rcx
movl 0x9e4(%rcx), %eax
cmpl 0x9e0(%rcx), %eax
jae 0x18342
movq 0x8(%rsp), %rdi
movl 0x24(%rsp), %esi
movl 0x18(%rsp), %edx
callq 0x18500
movl 0x1c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
jmp 0x18344
jmp 0x18344
jmp 0x18346
jmp 0x18348
jmp 0x1834a
movl 0x18(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x18(%rsp)
jmp 0x1829f
movl $0x0, 0x14(%rsp)
movl 0x14(%rsp), %eax
leaq 0x10ea3(%rip), %rcx     # 0x29210
movzbl (%rcx), %ecx
cmpl %ecx, %eax
jae 0x1845a
movq 0x8(%rsp), %rax
movq 0x9b8(%rax), %rax
movl 0x24(%rsp), %ecx
imulq $0x758, %rcx, %rcx      # imm = 0x758
addq %rcx, %rax
movl 0x14(%rsp), %ecx
cmpq $0x0, 0x5a8(%rax,%rcx,8)
je 0x18448
movq 0x8(%rsp), %rax
movl 0x20(%rsp), %ecx
addl $0x1, %ecx
movl %ecx, 0x20(%rsp)
movq 0x9b8(%rax), %rax
movl 0x24(%rsp), %ecx
imulq $0x758, %rcx, %rcx      # imm = 0x758
addq %rcx, %rax
movl 0x14(%rsp), %ecx
cmpb $0x0, 0x52(%rax,%rcx)
je 0x183e2
movl 0x1c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
jmp 0x18446
movq 0x8(%rsp), %rcx
movl 0xa1c(%rcx), %eax
cmpl 0xa18(%rcx), %eax
jae 0x18442
movq 0x8(%rsp), %rcx
movq 0x2a30(%rcx), %rax
movq 0xa30(%rcx,%rax,8), %rax
movq 0x9b8(%rcx), %rcx
movl 0x24(%rsp), %edx
imulq $0x758, %rdx, %rdx      # imm = 0x758
addq %rdx, %rcx
cmpq (%rcx), %rax
jne 0x18440
movq 0x8(%rsp), %rdi
movl 0x24(%rsp), %esi
movl 0x14(%rsp), %edx
callq 0x18d90
movl 0x1c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
jmp 0x18444
jmp 0x18444
jmp 0x18446
jmp 0x18448
jmp 0x1844a
movl 0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14(%rsp)
jmp 0x18362
movl 0x1c(%rsp), %eax
cmpl 0x20(%rsp), %eax
jne 0x18471
movl $0x0, 0x34(%rsp)
jmp 0x184f5
movl 0x20(%rsp), %eax
subl 0x1c(%rsp), %eax
movl %eax, 0x10(%rsp)
movl 0x10(%rsp), %eax
cmpl 0x20(%rsp), %eax
jbe 0x184ed
movq 0x10b62(%rip), %rdi     # 0x28ff0
leaq 0xb98b(%rip), %rsi      # 0x23e20
callq 0x3220
movq %rax, %rdi
movq 0x8(%rsp), %rax
movq 0x9b8(%rax), %rax
movl 0x24(%rsp), %ecx
imulq $0x758, %rcx, %rcx      # imm = 0x758
addq %rcx, %rax
movq (%rax), %rsi
callq 0x3080
movq %rax, %rdi
movq 0x10aef(%rip), %rsi     # 0x28fb8
callq 0x3250
leaq 0xab2f(%rip), %rdi      # 0x23004
leaq 0xb6d9(%rip), %rsi      # 0x23bb5
movl $0x355, %edx            # imm = 0x355
leaq 0xb80c(%rip), %rcx      # 0x23cf4
callq 0x3160
movl 0x10(%rsp), %eax
movl %eax, 0x34(%rsp)
movl 0x34(%rsp), %eax
addq $0x38, %rsp
retq
nop