// File: /workspace/github_cpp_makefile_star2_O2/NishadSaraf[P]Championship-Simulator/src/ooo_cpu.cc
// Function: O3_CPU::operate_lsq()
void O3_CPU::operate_lsq()
{
    // handle store
    uint32_t store_issued = 0, num_iteration = 0;

    while (store_issued < SQ_WIDTH) {
        if (RTS0[RTS0_head] < SQ_SIZE) {
            uint32_t sq_index = RTS0[RTS0_head];
            if (SQ.entry[sq_index].event_cycle <= current_core_cycle[cpu]) {

                // add it to DTLB
                PACKET data_packet;

                data_packet.tlb_access = 1;
                data_packet.fill_level = FILL_L1;
                data_packet.cpu = cpu;
                data_packet.data_index = SQ.entry[sq_index].data_index;
                data_packet.sq_index = sq_index;
                if (knob_cloudsuite)
                    data_packet.address = ((SQ.entry[sq_index].virtual_address >> LOG2_PAGE_SIZE) << 9) | SQ.entry[sq_index].asid[1];
                else
                    data_packet.address = SQ.entry[sq_index].virtual_address >> LOG2_PAGE_SIZE;
                data_packet.full_addr = SQ.entry[sq_index].virtual_address;
                data_packet.instr_id = SQ.entry[sq_index].instr_id;
                data_packet.rob_index = SQ.entry[sq_index].rob_index;
                data_packet.ip = SQ.entry[sq_index].ip;
                data_packet.type = RFO;
                data_packet.asid[0] = SQ.entry[sq_index].asid[0];
                data_packet.asid[1] = SQ.entry[sq_index].asid[1];
                data_packet.event_cycle = SQ.entry[sq_index].event_cycle;

                DP (if (warmup_complete[cpu]) {
                cout << "[RTS0] " << __func__ << " instr_id: " << SQ.entry[sq_index].instr_id << " rob_index: " << SQ.entry[sq_index].rob_index << " is popped from to RTS0";
                cout << " head: " << RTS0_head << " tail: " << RTS0_tail << endl; }); 

                int rq_index = DTLB.add_rq(&data_packet);

                if (rq_index == -2)
                    break; 
                else 
                    SQ.entry[sq_index].translated = INFLIGHT;

                RTS0[RTS0_head] = SQ_SIZE;
                RTS0_head++;
                if (RTS0_head == SQ_SIZE)
                    RTS0_head = 0;

                store_issued++;
            }
        }
        else {
            //DP (if (warmup_complete[cpu]) {
            //cout << "[RTS0] is empty head: " << RTS0_head << " tail: " << RTS0_tail << endl; });
            break;
        }

        num_iteration++;
        if (num_iteration == (SQ_SIZE-1))
            break;
    }

    num_iteration = 0;
    while (store_issued < SQ_WIDTH) {
        if (RTS1[RTS1_head] < SQ_SIZE) {
            uint32_t sq_index = RTS1[RTS1_head];
            if (SQ.entry[sq_index].event_cycle <= current_core_cycle[cpu]) {
                execute_store(SQ.entry[sq_index].rob_index, sq_index, SQ.entry[sq_index].data_index);

                RTS1[RTS1_head] = SQ_SIZE;
                RTS1_head++;
                if (RTS1_head == SQ_SIZE)
                    RTS1_head = 0;

                store_issued++;
            }
        }
        else {
            //DP (if (warmup_complete[cpu]) {
            //cout << "[RTS1] is empty head: " << RTS1_head << " tail: " << RTS1_tail << endl; });
            break;
        }

        num_iteration++;
        if (num_iteration == (SQ_SIZE-1))
            break;
    }

    unsigned load_issued = 0;
    num_iteration = 0;
    while (load_issued < LQ_WIDTH) {
        if (RTL0[RTL0_head] < LQ_SIZE) {
            uint32_t lq_index = RTL0[RTL0_head];
            if (LQ.entry[lq_index].event_cycle <= current_core_cycle[cpu]) {

                // add it to DTLB
                PACKET data_packet;
                data_packet.fill_level = FILL_L1;
                data_packet.cpu = cpu;
                data_packet.data_index = LQ.entry[lq_index].data_index;
                data_packet.lq_index = lq_index;
                if (knob_cloudsuite)
                    data_packet.address = ((LQ.entry[lq_index].virtual_address >> LOG2_PAGE_SIZE) << 9) | LQ.entry[lq_index].asid[1];
                else
                    data_packet.address = LQ.entry[lq_index].virtual_address >> LOG2_PAGE_SIZE;
                data_packet.full_addr = LQ.entry[lq_index].virtual_address;
                data_packet.instr_id = LQ.entry[lq_index].instr_id;
                data_packet.rob_index = LQ.entry[lq_index].rob_index;
                data_packet.ip = LQ.entry[lq_index].ip;
                data_packet.type = LOAD;
                data_packet.asid[0] = LQ.entry[lq_index].asid[0];
                data_packet.asid[1] = LQ.entry[lq_index].asid[1];
                data_packet.event_cycle = LQ.entry[lq_index].event_cycle;

                DP (if (warmup_complete[cpu]) {
                cout << "[RTL0] " << __func__ << " instr_id: " << LQ.entry[lq_index].instr_id << " rob_index: " << LQ.entry[lq_index].rob_index << " is popped to RTL0";
                cout << " head: " << RTL0_head << " tail: " << RTL0_tail << endl; }); 

                int rq_index = DTLB.add_rq(&data_packet);

                if (rq_index == -2)
                    break; // break here
                else  
                    LQ.entry[lq_index].translated = INFLIGHT;

                RTL0[RTL0_head] = LQ_SIZE;
                RTL0_head++;
                if (RTL0_head == LQ_SIZE)
                    RTL0_head = 0;

                load_issued++;
            }
        }
        else {
            //DP (if (warmup_complete[cpu]) {
            //cout << "[RTL0] is empty head: " << RTL0_head << " tail: " << RTL0_tail << endl; });
            break;
        }

        num_iteration++;
        if (num_iteration == (LQ_SIZE-1))
            break;
    }

    num_iteration = 0;
    while (load_issued < LQ_WIDTH) {
        if (RTL1[RTL1_head] < LQ_SIZE) {
            uint32_t lq_index = RTL1[RTL1_head];
            if (LQ.entry[lq_index].event_cycle <= current_core_cycle[cpu]) {
                int rq_index = execute_load(LQ.entry[lq_index].rob_index, lq_index, LQ.entry[lq_index].data_index);

                if (rq_index != -2) {
                    RTL1[RTL1_head] = LQ_SIZE;
                    RTL1_head++;
                    if (RTL1_head == LQ_SIZE)
                        RTL1_head = 0;

                    load_issued++;
                }
            }
        }
        else {
            //DP (if (warmup_complete[cpu]) {
            //cout << "[RTL1] is empty head: " << RTL1_head << " tail: " << RTL1_tail << endl; });
            break;
        }

        num_iteration++;
        if (num_iteration == (LQ_SIZE-1))
            break;
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x388, %rsp            # imm = 0x388
movq %rdi, %rbx
leaq 0x13a38(%rdi), %rax
movq %rax, (%rsp)
movl 0x3580(%rdi), %eax
movl 0x34a0(%rdi,%rax,4), %r14d
movq 0xa28(%rdi), %rax
imulq $0x140, %r14, %r13      # imm = 0x140
addq %r13, %rax
addq $0x28, %rax
movl (%rdi), %ecx
pushq $0x36
popq %rdx
leaq 0x71d60(%rip), %r12     # 0x7ceb0
cmpl $0x37, %r14d
ja 0xb25b
movq (%rax), %rsi
movq (%r12,%rcx,8), %rdi
cmpq %rdi, %rsi
jbe 0xb179
addl $-0x1, %edx
jae 0xb25b
cmpq %rdi, %rsi
ja 0xb150
jmp 0xb25b
leaq 0x8(%rsp), %r15
movq %r15, %rdi
callq 0x53f4
movb $0x1, 0x1(%r15)
movl $0x1, 0x8(%r15)
movl (%rbx), %eax
movl %eax, 0x330(%r15)
movq 0xa28(%rbx), %rax
movl 0x34(%rax,%r13), %ecx
movl %ecx, 0x334(%r15)
movl %r14d, 0x33c(%r15)
leaq 0xb178(%rip), %rcx      # 0x16335
cmpb $0x0, (%rcx)
je 0xb1e6
movq 0x10(%rax,%r13), %rcx
movq %rcx, %rsi
shrq $0x3, %rsi
movabsq $0x1ffffffffffffe00, %rdx # imm = 0x1FFFFFFFFFFFFE00
andq %rdx, %rsi
movzbl 0x3f(%rax,%r13), %edx
orq %rsi, %rdx
jmp 0xb1f2
movq 0x10(%rax,%r13), %rcx
movq %rcx, %rdx
shrq $0xc, %rdx
leaq 0x8(%rsp), %rsi
movq %rdx, 0x340(%rsi)
movq %rcx, 0x348(%rsi)
movq (%rax,%r13), %rcx
movq %rcx, 0x368(%rsi)
movl 0x30(%rax,%r13), %ecx
movl %ecx, 0x10(%rsi)
movq 0x20(%rax,%r13), %rcx
movq %rcx, 0x370(%rsi)
movb $0x1, 0x32f(%rsi)
movb 0x3e(%rax,%r13), %cl
movb %cl, 0x32d(%rsi)
movb 0x3f(%rax,%r13), %cl
movb %cl, 0x32e(%rsi)
movq 0x28(%rax,%r13), %rax
movq %rax, 0x378(%rsi)
movq (%rsp), %rdi
callq 0x477a
cmpl $-0x2, %eax
jne 0xb2c4
movl 0x3668(%rbx), %eax
movl 0x3588(%rbx,%rax,4), %edx
cmpq $0x37, %rdx
ja 0xb2f8
movl (%rbx), %esi
movq 0xa28(%rbx), %rax
imulq $0x140, %rdx, %rcx      # imm = 0x140
movq 0x28(%rax,%rcx), %rdi
cmpq (%r12,%rsi,8), %rdi
ja 0xb2f8
addq %rcx, %rax
movl 0x30(%rax), %esi
movq %rbx, %rdi
callq 0xbc84
movl 0x3668(%rbx), %eax
movl $0x38, 0x3588(%rbx,%rax,4)
movl 0x3668(%rbx), %eax
incl %eax
xorl %ecx, %ecx
cmpl $0x38, %eax
cmovnel %eax, %ecx
movl %ecx, 0x3668(%rbx)
jmp 0xb2f8
movq 0xa28(%rbx), %rax
movb $0x1, 0x3c(%rax,%r13)
movl 0x3580(%rbx), %eax
movl $0x38, 0x34a0(%rbx,%rax,4)
movl 0x3580(%rbx), %eax
incl %eax
xorl %ecx, %ecx
cmpl $0x38, %eax
cmovnel %eax, %ecx
movl %ecx, 0x3580(%rbx)
movl 0x3370(%rbx), %eax
pushq $0x46
popq %r13
xorl %ebp, %ebp
movl %eax, %ecx
movl 0x3250(%rbx,%rcx,4), %r15d
cmpq $0x47, %r15
ja 0xb468
movq 0x9f0(%rbx), %rcx
imulq $0x140, %r15, %r14      # imm = 0x140
movq 0x28(%rcx,%r14), %rcx
movl (%rbx), %edx
cmpq (%r12,%rdx,8), %rcx
ja 0xb454
leaq 0x8(%rsp), %rdi
callq 0x53f4
movl $0x1, 0x10(%rsp)
movl (%rbx), %eax
movl %eax, 0x338(%rsp)
movq 0x9f0(%rbx), %rax
movl 0x34(%rax,%r14), %ecx
movl %ecx, 0x33c(%rsp)
movl %r15d, 0x340(%rsp)
leaq 0xafc1(%rip), %rcx      # 0x16335
cmpb $0x0, (%rcx)
je 0xb39d
movq 0x10(%rax,%r14), %rcx
movq %rcx, %rsi
shrq $0x3, %rsi
movabsq $0x1ffffffffffffe00, %rdx # imm = 0x1FFFFFFFFFFFFE00
andq %rdx, %rsi
movzbl 0x3f(%rax,%r14), %edx
orq %rsi, %rdx
jmp 0xb3a9
movq 0x10(%rax,%r14), %rcx
movq %rcx, %rdx
shrq $0xc, %rdx
movq %rdx, 0x348(%rsp)
movq %rcx, 0x350(%rsp)
movq (%rax,%r14), %rcx
movq %rcx, 0x370(%rsp)
movl 0x30(%rax,%r14), %ecx
movl %ecx, 0x18(%rsp)
movq 0x20(%rax,%r14), %rcx
movq %rcx, 0x378(%rsp)
movb $0x0, 0x337(%rsp)
movb 0x3e(%rax,%r14), %cl
movb %cl, 0x335(%rsp)
movb 0x3f(%rax,%r14), %cl
movb %cl, 0x336(%rsp)
movq 0x28(%rax,%r14), %rax
movq %rax, 0x380(%rsp)
movq (%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x477a
cmpl $-0x2, %eax
je 0xb468
movq 0x9f0(%rbx), %rax
movb $0x1, 0x3c(%rax,%r14)
movl 0x3370(%rbx), %eax
movl $0x48, 0x3250(%rbx,%rax,4)
movl 0x3370(%rbx), %eax
incl %eax
cmpl $0x48, %eax
movl $0x0, %ecx
cmovel %ecx, %eax
movl %eax, 0x3370(%rbx)
incl %ebp
addl $-0x1, %r13d
jae 0xb463
cmpl $0x2, %ebp
jb 0xb304
cmpl $0x1, %ebp
ja 0xb4dd
pushq $0x46
popq %r14
xorl %r15d, %r15d
movl 0x3498(%rbx), %eax
movl 0x3378(%rbx,%rax,4), %edx
cmpq $0x47, %rdx
ja 0xb4dd
movq 0x9f0(%rbx), %rax
imulq $0x140, %rdx, %rcx      # imm = 0x140
movq 0x28(%rax,%rcx), %rax
movl (%rbx), %ecx
cmpq (%r12,%rcx,8), %rax
ja 0xb4d2
movq %rbx, %rdi
callq 0xbfce
cmpl $-0x2, %eax
je 0xb4d2
movl 0x3498(%rbx), %eax
movl $0x48, 0x3378(%rbx,%rax,4)
movl 0x3498(%rbx), %eax
incl %eax
cmpl $0x48, %eax
cmovel %r15d, %eax
movl %eax, 0x3498(%rbx)
incl %ebp
addl $-0x1, %r14d
jae 0xb4dd
cmpl $0x2, %ebp
jb 0xb46f
addq $0x388, %rsp            # imm = 0x388
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop