// File: 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:
subq $0x748, %rsp            # imm = 0x748
movq %rdi, 0x740(%rsp)
movq 0x740(%rsp), %rax
movq %rax, 0x8(%rsp)
movl $0x0, 0x73c(%rsp)
movl $0x0, 0x738(%rsp)
cmpl $0x1, 0x73c(%rsp)
jae 0x17c5d
movq 0x8(%rsp), %rax
movl 0x3580(%rax), %ecx
cmpl $0x38, 0x34a0(%rax,%rcx,4)
jae 0x17c39
movq 0x8(%rsp), %rcx
movl 0x3580(%rcx), %eax
movl 0x34a0(%rcx,%rax,4), %eax
movl %eax, 0x734(%rsp)
movq 0xa28(%rcx), %rax
movl 0x734(%rsp), %edx
imulq $0x140, %rdx, %rdx      # imm = 0x140
addq %rdx, %rax
movq 0x28(%rax), %rax
movl (%rcx), %ecx
movl %ecx, %edx
leaq 0x78517(%rip), %rcx     # 0x8fec0
cmpq (%rcx,%rdx,8), %rax
ja 0x17c37
leaq 0x3b0(%rsp), %rdi
callq 0x9750
movq 0x8(%rsp), %rax
movb $0x1, 0x3b1(%rsp)
movl $0x1, 0x3b8(%rsp)
movl (%rax), %ecx
movl %ecx, 0x6e0(%rsp)
movq 0xa28(%rax), %rax
movl 0x734(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movl 0x34(%rax), %eax
movl %eax, 0x6e4(%rsp)
movl 0x734(%rsp), %eax
movl %eax, 0x6ec(%rsp)
leaq 0x1192d(%rip), %rax     # 0x29345
cmpb $0x0, (%rax)
je 0x17a6f
movq 0x8(%rsp), %rcx
movq 0xa28(%rcx), %rax
movl 0x734(%rsp), %edx
imulq $0x140, %rdx, %rdx      # imm = 0x140
addq %rdx, %rax
movq 0x10(%rax), %rax
shrq $0xc, %rax
shlq $0x9, %rax
movq 0xa28(%rcx), %rcx
movl 0x734(%rsp), %edx
imulq $0x140, %rdx, %rdx      # imm = 0x140
addq %rdx, %rcx
movzbl 0x3f(%rcx), %ecx
orq %rcx, %rax
movq %rax, 0x6f0(%rsp)
jmp 0x17a9c
movq 0x8(%rsp), %rax
movq 0xa28(%rax), %rax
movl 0x734(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movq 0x10(%rax), %rax
shrq $0xc, %rax
movq %rax, 0x6f0(%rsp)
movq 0x8(%rsp), %rdi
movq 0xa28(%rdi), %rax
movl 0x734(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movq 0x10(%rax), %rax
movq %rax, 0x6f8(%rsp)
movq 0xa28(%rdi), %rax
movl 0x734(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movq (%rax), %rax
movq %rax, 0x718(%rsp)
movq 0xa28(%rdi), %rax
movl 0x734(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movl 0x30(%rax), %eax
movl %eax, 0x3c0(%rsp)
movq 0xa28(%rdi), %rax
movl 0x734(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movq 0x20(%rax), %rax
movq %rax, 0x720(%rsp)
movb $0x1, 0x6df(%rsp)
movq 0xa28(%rdi), %rax
movl 0x734(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movb 0x3e(%rax), %al
movb %al, 0x6dd(%rsp)
movq 0xa28(%rdi), %rax
movl 0x734(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movb 0x3f(%rax), %al
movb %al, 0x6de(%rsp)
movq 0xa28(%rdi), %rax
movl 0x734(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movq 0x28(%rax), %rax
movq %rax, 0x728(%rsp)
addq $0x13a38, %rdi          # imm = 0x13A38
leaq 0x3b0(%rsp), %rsi
callq 0x81e0
movl %eax, 0x3ac(%rsp)
cmpl $-0x2, 0x3ac(%rsp)
jne 0x17bc8
jmp 0x17c5d
movq 0x8(%rsp), %rax
movq 0xa28(%rax), %rax
movl 0x734(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movb $0x1, 0x3c(%rax)
movq 0x8(%rsp), %rax
movl 0x3580(%rax), %ecx
movl $0x38, 0x34a0(%rax,%rcx,4)
movl 0x3580(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x3580(%rax)
cmpl $0x38, 0x3580(%rax)
jne 0x17c26
movq 0x8(%rsp), %rax
movl $0x0, 0x3580(%rax)
movl 0x73c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x73c(%rsp)
jmp 0x17c3b
jmp 0x17c5d
movl 0x738(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x738(%rsp)
cmpl $0x37, 0x738(%rsp)
jne 0x17c58
jmp 0x17c5d
jmp 0x17942
movl $0x0, 0x738(%rsp)
cmpl $0x1, 0x73c(%rsp)
jae 0x17d94
movq 0x8(%rsp), %rax
movl 0x3668(%rax), %ecx
cmpl $0x38, 0x3588(%rax,%rcx,4)
jae 0x17d70
movq 0x8(%rsp), %rcx
movl 0x3668(%rcx), %eax
movl 0x3588(%rcx,%rax,4), %eax
movl %eax, 0x3a8(%rsp)
movq 0xa28(%rcx), %rax
movl 0x3a8(%rsp), %edx
imulq $0x140, %rdx, %rdx      # imm = 0x140
addq %rdx, %rax
movq 0x28(%rax), %rax
movl (%rcx), %ecx
movl %ecx, %edx
leaq 0x781f1(%rip), %rcx     # 0x8fec0
cmpq (%rcx,%rdx,8), %rax
ja 0x17d6e
movq 0x8(%rsp), %rdi
movq 0xa28(%rdi), %rax
movl 0x3a8(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movl 0x30(%rax), %esi
movl 0x3a8(%rsp), %edx
movq 0xa28(%rdi), %rax
movl 0x3a8(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movl 0x34(%rax), %ecx
callq 0x19240
movq 0x8(%rsp), %rax
movl 0x3668(%rax), %ecx
movl $0x38, 0x3588(%rax,%rcx,4)
movl 0x3668(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x3668(%rax)
cmpl $0x38, 0x3668(%rax)
jne 0x17d5d
movq 0x8(%rsp), %rax
movl $0x0, 0x3668(%rax)
movl 0x73c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x73c(%rsp)
jmp 0x17d72
jmp 0x17d94
movl 0x738(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x738(%rsp)
cmpl $0x37, 0x738(%rsp)
jne 0x17d8f
jmp 0x17d94
jmp 0x17c68
movl $0x0, 0x3a4(%rsp)
movl $0x0, 0x738(%rsp)
cmpl $0x2, 0x3a4(%rsp)
jae 0x180ab
movq 0x8(%rsp), %rax
movl 0x3370(%rax), %ecx
cmpl $0x48, 0x3250(%rax,%rcx,4)
jae 0x18087
movq 0x8(%rsp), %rcx
movl 0x3370(%rcx), %eax
movl 0x3250(%rcx,%rax,4), %eax
movl %eax, 0x3a0(%rsp)
movq 0x9f0(%rcx), %rax
movl 0x3a0(%rsp), %edx
imulq $0x140, %rdx, %rdx      # imm = 0x140
addq %rdx, %rax
movq 0x28(%rax), %rax
movl (%rcx), %ecx
movl %ecx, %edx
leaq 0x780af(%rip), %rcx     # 0x8fec0
cmpq (%rcx,%rdx,8), %rax
ja 0x18085
leaq 0x20(%rsp), %rdi
callq 0x9750
movq 0x8(%rsp), %rax
movl $0x1, 0x28(%rsp)
movl (%rax), %ecx
movl %ecx, 0x350(%rsp)
movq 0x9f0(%rax), %rax
movl 0x3a0(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movl 0x34(%rax), %eax
movl %eax, 0x354(%rsp)
movl 0x3a0(%rsp), %eax
movl %eax, 0x358(%rsp)
leaq 0x114d3(%rip), %rax     # 0x29345
cmpb $0x0, (%rax)
je 0x17ec9
movq 0x8(%rsp), %rcx
movq 0x9f0(%rcx), %rax
movl 0x3a0(%rsp), %edx
imulq $0x140, %rdx, %rdx      # imm = 0x140
addq %rdx, %rax
movq 0x10(%rax), %rax
shrq $0xc, %rax
shlq $0x9, %rax
movq 0x9f0(%rcx), %rcx
movl 0x3a0(%rsp), %edx
imulq $0x140, %rdx, %rdx      # imm = 0x140
addq %rdx, %rcx
movzbl 0x3f(%rcx), %ecx
orq %rcx, %rax
movq %rax, 0x360(%rsp)
jmp 0x17ef6
movq 0x8(%rsp), %rax
movq 0x9f0(%rax), %rax
movl 0x3a0(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movq 0x10(%rax), %rax
shrq $0xc, %rax
movq %rax, 0x360(%rsp)
movq 0x8(%rsp), %rdi
movq 0x9f0(%rdi), %rax
movl 0x3a0(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movq 0x10(%rax), %rax
movq %rax, 0x368(%rsp)
movq 0x9f0(%rdi), %rax
movl 0x3a0(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movq (%rax), %rax
movq %rax, 0x388(%rsp)
movq 0x9f0(%rdi), %rax
movl 0x3a0(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movl 0x30(%rax), %eax
movl %eax, 0x30(%rsp)
movq 0x9f0(%rdi), %rax
movl 0x3a0(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movq 0x20(%rax), %rax
movq %rax, 0x390(%rsp)
movb $0x0, 0x34f(%rsp)
movq 0x9f0(%rdi), %rax
movl 0x3a0(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movb 0x3e(%rax), %al
movb %al, 0x34d(%rsp)
movq 0x9f0(%rdi), %rax
movl 0x3a0(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movb 0x3f(%rax), %al
movb %al, 0x34e(%rsp)
movq 0x9f0(%rdi), %rax
movl 0x3a0(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movq 0x28(%rax), %rax
movq %rax, 0x398(%rsp)
addq $0x13a38, %rdi          # imm = 0x13A38
leaq 0x20(%rsp), %rsi
callq 0x81e0
movl %eax, 0x1c(%rsp)
cmpl $-0x2, 0x1c(%rsp)
jne 0x18016
jmp 0x180ab
movq 0x8(%rsp), %rax
movq 0x9f0(%rax), %rax
movl 0x3a0(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movb $0x1, 0x3c(%rax)
movq 0x8(%rsp), %rax
movl 0x3370(%rax), %ecx
movl $0x48, 0x3250(%rax,%rcx,4)
movl 0x3370(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x3370(%rax)
cmpl $0x48, 0x3370(%rax)
jne 0x18074
movq 0x8(%rsp), %rax
movl $0x0, 0x3370(%rax)
movl 0x3a4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3a4(%rsp)
jmp 0x18089
jmp 0x180ab
movl 0x738(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x738(%rsp)
cmpl $0x47, 0x738(%rsp)
jne 0x180a6
jmp 0x180ab
jmp 0x17daa
movl $0x0, 0x738(%rsp)
cmpl $0x2, 0x3a4(%rsp)
jae 0x181e0
movq 0x8(%rsp), %rax
movl 0x3498(%rax), %ecx
cmpl $0x48, 0x3378(%rax,%rcx,4)
jae 0x181bc
movq 0x8(%rsp), %rcx
movl 0x3498(%rcx), %eax
movl 0x3378(%rcx,%rax,4), %eax
movl %eax, 0x18(%rsp)
movq 0x9f0(%rcx), %rax
movl 0x18(%rsp), %edx
imulq $0x140, %rdx, %rdx      # imm = 0x140
addq %rdx, %rax
movq 0x28(%rax), %rax
movl (%rcx), %ecx
movl %ecx, %edx
leaq 0x77da9(%rip), %rcx     # 0x8fec0
cmpq (%rcx,%rdx,8), %rax
ja 0x181ba
movq 0x8(%rsp), %rdi
movq 0x9f0(%rdi), %rax
movl 0x18(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movl 0x30(%rax), %esi
movl 0x18(%rsp), %edx
movq 0x9f0(%rdi), %rax
movl 0x18(%rsp), %ecx
imulq $0x140, %rcx, %rcx      # imm = 0x140
addq %rcx, %rax
movl 0x34(%rax), %ecx
callq 0x19850
movl %eax, 0x14(%rsp)
cmpl $-0x2, 0x14(%rsp)
je 0x181b8
movq 0x8(%rsp), %rax
movl 0x3498(%rax), %ecx
movl $0x48, 0x3378(%rax,%rcx,4)
movl 0x3498(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x3498(%rax)
cmpl $0x48, 0x3498(%rax)
jne 0x181a7
movq 0x8(%rsp), %rax
movl $0x0, 0x3498(%rax)
movl 0x3a4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3a4(%rsp)
jmp 0x181ba
jmp 0x181be
jmp 0x181e0
movl 0x738(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x738(%rsp)
cmpl $0x47, 0x738(%rsp)
jne 0x181db
jmp 0x181e0
jmp 0x180b6
addq $0x748, %rsp            # imm = 0x748
retq
nopl (%rax,%rax)