// File: /workspace/github_cpp_makefile_star2_O3/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 $0x398, %rsp            # imm = 0x398
movq %rdi, %rbx
movl 0x3580(%rdi), %eax
movl 0x34a0(%rdi,%rax,4), %ebp
leaq 0x731f8(%rip), %r8      # 0x80ec0
cmpq $0x37, %rbp
ja 0xde24
movl (%rbx), %r13d
movq 0xa28(%rbx), %r12
leaq (,%rbp,4), %r15
addq %rbp, %r15
shlq $0x6, %r15
movq 0x28(%r12,%r15), %rax
cmpq (%r8,%r13,8), %rax
ja 0xde24
movq %rax, (%rsp)
leaq 0x30(%rsp), %r14
movb $0x0, 0x314(%r14)
xorl %eax, %eax
movl %eax, -0x18(%r14)
movl %eax, -0x15(%r14)
pcmpeqd %xmm0, %xmm0
movdqu %xmm0, -0x10(%r14)
movl $0x314, %edx            # imm = 0x314
movq %r14, %rdi
xorl %esi, %esi
callq 0x3130
pxor %xmm0, %xmm0
movdqu %xmm0, 0x320(%r14)
movdqu %xmm0, 0x330(%r14)
movq $0x0, 0x348(%r14)
movb $0x1, -0x17(%r14)
movl $0x1, -0x10(%r14)
movl %r13d, 0x318(%r14)
movl 0x34(%r12,%r15), %eax
movl %eax, 0x31c(%r14)
movl %ebp, 0x324(%r14)
leaq 0xc5c8(%rip), %rax      # 0x1a345
cmpb $0x0, (%rax)
je 0xdda6
movq 0x10(%r12,%r15), %rcx
movq %rcx, %rdx
shrq $0x3, %rdx
movabsq $0x1ffffffffffffe00, %rax # imm = 0x1FFFFFFFFFFFFE00
andq %rax, %rdx
movzbl 0x3f(%r12,%r15), %eax
orq %rax, %rdx
jmp 0xddb7
movq 0x10(%r12,%r15), %rcx
movq %rcx, %rdx
shrq $0xc, %rdx
movb 0x3f(%r12,%r15), %al
leaq 0x18(%rsp), %rsi
movq %rdx, 0x340(%rsi)
movq %rcx, 0x348(%rsi)
movq (%r12,%r15), %rcx
movq %rcx, 0x368(%rsi)
movl 0x30(%r12,%r15), %ecx
movl %ecx, 0x10(%rsi)
movq 0x20(%r12,%r15), %rcx
movq %rcx, 0x370(%rsi)
movb $0x1, 0x32f(%rsi)
movb 0x3e(%r12,%r15), %cl
movb %cl, 0x32d(%rsi)
movb %al, 0x32e(%rsi)
movq (%rsp), %rax
movq %rax, 0x378(%rsi)
leaq 0x13a38(%rbx), %rdi
callq 0x5ab4
cmpl $-0x2, %eax
jne 0xde95
leaq 0x7309c(%rip), %r8      # 0x80ec0
movl 0x3668(%rbx), %eax
movl 0x3588(%rbx,%rax,4), %edx
cmpq $0x37, %rdx
ja 0xded0
movl (%rbx), %esi
movq 0xa28(%rbx), %rax
leaq (%rdx,%rdx,4), %rcx
shlq $0x6, %rcx
movq 0x28(%rax,%rcx), %rdi
cmpq (%r8,%rsi,8), %rdi
ja 0xded0
addq %rcx, %rax
movl 0x30(%rax), %esi
movq %rbx, %rdi
callq 0xe9ac
leaq 0x73054(%rip), %r8      # 0x80ec0
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 0xded0
movq 0xa28(%rbx), %rax
movb $0x1, 0x3c(%rax,%r15)
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)
leaq 0x72ff0(%rip), %r8      # 0x80ec0
leaq 0x13a38(%rbx), %rax
movq %rax, 0x8(%rsp)
movl 0x3370(%rbx), %eax
movl $0x46, %r13d
xorl %esi, %esi
movq %rbx, 0x10(%rsp)
movl %eax, %ecx
movl 0x3250(%rbx,%rcx,4), %r14d
cmpq $0x47, %r14
ja 0xe0d0
movq 0x9f0(%rbx), %r12
leaq (%r14,%r14,4), %r15
shlq $0x6, %r15
movq 0x28(%r12,%r15), %rcx
movl (%rbx), %ebp
cmpq (%r8,%rbp,8), %rcx
ja 0xe0ad
movl %esi, (%rsp)
xorl %eax, %eax
movl %eax, 0x1b(%rsp)
movl %eax, 0x18(%rsp)
movl $0xffff00, 0x344(%rsp) # imm = 0xFFFF00
leaq 0x20(%rsp), %rbx
pcmpeqd %xmm0, %xmm0
movdqu %xmm0, (%rbx)
movl $0x314, %edx            # imm = 0x314
leaq 0x30(%rsp), %rdi
xorl %esi, %esi
callq 0x3130
pxor %xmm0, %xmm0
movdqu %xmm0, 0x32c(%rbx)
movdqu %xmm0, 0x33c(%rbx)
xorl %eax, %eax
movl %eax, 0x34c(%rbx)
movdqu %xmm0, 0x358(%rbx)
movq $0x0, 0x368(%rbx)
movq $-0x1, 0x390(%rsp)
movl $0x1, 0x20(%rsp)
movl %ebp, 0x348(%rsp)
movl 0x34(%r12,%r15), %eax
movl %eax, 0x34c(%rsp)
movl %r14d, 0x350(%rsp)
leaq 0xc387(%rip), %rax      # 0x1a345
cmpb $0x0, (%rax)
je 0xdfe7
movq 0x10(%r12,%r15), %rax
movq %rax, %rdx
shrq $0x3, %rdx
movabsq $0x1ffffffffffffe00, %rcx # imm = 0x1FFFFFFFFFFFFE00
andq %rcx, %rdx
movzbl 0x3f(%r12,%r15), %ecx
orq %rdx, %rcx
jmp 0xdff3
movq 0x10(%r12,%r15), %rax
movq %rax, %rcx
shrq $0xc, %rcx
leaq (%r12,%r15), %rdx
addq $0x28, %rdx
movq %rcx, 0x358(%rsp)
movq %rax, 0x360(%rsp)
movq -0x28(%rdx), %rax
movq %rax, 0x380(%rsp)
movl 0x8(%rdx), %eax
movl %eax, 0x28(%rsp)
movq -0x8(%rdx), %rax
movq %rax, 0x388(%rsp)
movb $0x0, 0x347(%rsp)
movb 0x16(%rdx), %al
movb %al, 0x345(%rsp)
movb 0x17(%rdx), %al
movb %al, 0x346(%rsp)
movq (%rdx), %rax
movq %rax, 0x390(%rsp)
movq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x5ab4
cmpl $-0x2, %eax
movq 0x10(%rsp), %rbx
je 0xe0c6
movq 0x9f0(%rbx), %rax
movb $0x1, 0x3c(%rax,%r15)
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)
movl (%rsp), %esi
incl %esi
leaq 0x72e13(%rip), %r8      # 0x80ec0
addl $-0x1, %r13d
jae 0xe0bc
cmpl $0x2, %esi
jb 0xdeef
cmpl $0x1, %esi
jbe 0xe0d0
jmp 0xe162
leaq 0x72df3(%rip), %r8      # 0x80ec0
movl (%rsp), %esi
movl $0x46, %r14d
xorl %r15d, %r15d
movl 0x3498(%rbx), %eax
movl 0x3378(%rbx,%rax,4), %edx
cmpq $0x47, %rdx
ja 0xe162
movq 0x9f0(%rbx), %rax
leaq (%rdx,%rdx,4), %rcx
shlq $0x6, %rcx
movq 0x28(%rax,%rcx), %rax
movl (%rbx), %ecx
cmpq (%r8,%rcx,8), %rax
ja 0xe153
movl %esi, %ebp
movq %rbx, %rdi
callq 0xed22
cmpl $-0x2, %eax
jne 0xe122
leaq 0x72da2(%rip), %r8      # 0x80ec0
movl %ebp, %esi
jmp 0xe153
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)
movl %ebp, %esi
incl %esi
leaq 0x72d6d(%rip), %r8      # 0x80ec0
addl $-0x1, %r14d
jae 0xe162
cmpl $0x2, %esi
jb 0xe0d9
addq $0x398, %rsp            # imm = 0x398
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq