// File: /workspace/github_cpp_makefile_star2_O3/gibsjose[P]VirtualMemorySimulation/Memory.cpp
// Function: Memory::Reference(Process&, unsigned short)
void Memory::Reference(Process & process, uint16_t page) {

    //Check to see if the process already has an entry in it's page table
    if(process.GetPageTable().EntryExists(page)) {
        //Get frame number
        uint16_t frame = process.GetPageTable().GetEntry(page).frame;

        //Check to see if it is already in RAM or if it is in the free frame list
        if(InRAM(frame)) {
            //...nothing to do...
            std::cout << Color::Green("*") << " Process " << process.GetName() << " (page " << page << " --> frame " << frame << ") already in RAM" << std::endl;
            return;
        }

        else if(InFreeFrameList(frame)) {
            std::cout << "Frame " << frame << " in free frame list" << std::endl;
            return;
        }

        //Bad... if the entry exists it should always either be in the free frame list or in RAM
        else {
            std::cerr << "Frame " << frame << ": something bad has happened..." << std::endl;
            return;
        }
    }

    //Process does NOT have an entry for this page: PAGE FAULT
    else {
        std::cout << Color::Red("! [PAGE FAULT]") << " for process " << process.GetName() << " page " << page;
        process.PageFault();

        //Add an entry
        PageTableEntry entry;

        //Check if there are any free frames
        if(AreFreeFrames()) {
            entry.frame = GetFreeFrame();
            entry.ref = true;
            entry.dirty = false;

            process.GetPageTable().AddEntry(page, entry);

            //Move the frame from the available set to RAM
            AvailableToRAM(entry.frame);

            LRUEntry lruEntry;
            lruEntry.process = &process;
            lruEntry.page = page;
            lruEntry.frame = entry.frame;

            //Push the process, page, and frame to the LRU deque
            lru.push_front(lruEntry);

            std::cout << ": Assigned " << Color::Green("free") << " frame " << entry.frame << std::endl;
        }

        //No free frames!
        //Must implement LRU to select a victim...
        else {
            std::cout << std::endl;
            std::cout << Color::Cyan("- [COLLISION]") << " LRU Replacement Needed for process " << process.GetName() << " page " << page;

            //Find a victim, remove it's entry from the page table (set entry.valid = false)
            entry.frame = SelectVictim();
            entry.ref = true;
            entry.dirty = false;

            std::cout << ": Assigned " << Color::Cyan("victim") << " frame " << entry.frame << std::endl;

            process.GetPageTable().AddEntry(page, entry);

            LRUEntry lruEntry;
            lruEntry.process = &process;
            lruEntry.page = page;
            lruEntry.frame = entry.frame;

            //Push back onto the LRU
            lru.push_front(lruEntry);
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xd8, %rsp
movl %edx, %ebp
movq %rsi, %r14
movq %rdi, %rbx
leaq 0x28(%rsi), %r15
movq %r15, %rdi
movl %edx, %esi
callq 0x6d14
testb %al, %al
je 0x5790
movzwl %bp, %r12d
movq %r15, %rdi
movl %r12d, %esi
callq 0x6d92
movzwl (%rax), %r15d
movq 0x10(%rbx), %rax
testq %rax, %rax
je 0x56e3
leaq 0x8(%rbx), %rdx
movq %rdx, %rcx
xorl %esi, %esi
cmpw %r15w, 0x20(%rax)
setb %sil
cmovaeq %rax, %rcx
movq 0x10(%rax,%rsi,8), %rax
testq %rax, %rax
jne 0x56ba
cmpq %rdx, %rcx
je 0x56e3
cmpw %r15w, 0x20(%rcx)
jbe 0x5c0d
movq 0x70(%rbx), %rax
testq %rax, %rax
je 0x571b
addq $0x68, %rbx
movq %rbx, %rcx
xorl %edx, %edx
cmpw %r15w, 0x20(%rax)
setb %dl
cmovaeq %rax, %rcx
movq 0x10(%rax,%rdx,8), %rax
testq %rax, %rax
jne 0x56f3
cmpq %rbx, %rcx
je 0x571b
cmpw %r15w, 0x20(%rcx)
jbe 0x5d3b
movq 0x68ce(%rip), %rbx      # 0xbff0
leaq 0x2acb(%rip), %rsi      # 0x81f4
movl $0x6, %edx
movq %rbx, %rdi
callq 0x2200
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2130
movq %rax, %rbx
leaq 0x2ac4(%rip), %rsi      # 0x820f
movl $0x1f, %edx
movq %rax, %rdi
callq 0x2200
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x21b0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2140
leaq 0x48(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x2a8f(%rip), %rsi      # 0x822f
leaq 0x2a96(%rip), %rdx      # 0x823d
leaq 0x38(%rsp), %rdi
callq 0x43f0
movq %rsp, %rdi
leaq 0x38(%rsp), %rsi
callq 0x6174
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
movq 0x67fa(%rip), %r13      # 0xbfc8
movq %r13, %rdi
callq 0x2200
movq %rax, %r12
leaq 0x2a9b(%rip), %rsi      # 0x827b
movl $0xd, %edx
movq %rax, %rdi
callq 0x2200
movq (%r14), %rsi
movq 0x8(%r14), %rdx
movq %r12, %rdi
callq 0x2200
movq %rax, %r12
leaq 0x2a38(%rip), %rsi      # 0x823e
movl $0x6, %edx
movq %rax, %rdi
callq 0x2200
movzwl %bp, %ebp
movq %r12, %rdi
movq %rbp, %rsi
callq 0x2130
leaq 0x10(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x583c
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x38(%rsp), %rdi
leaq 0x48(%rsp), %rax
cmpq %rax, %rdi
je 0x5858
movq 0x48(%rsp), %rsi
incq %rsi
callq 0x21d0
movq %r14, %rdi
callq 0x68a0
movl $0x0, 0x22(%rsp)
movb $0x1, 0x26(%rsp)
cmpq $0x0, 0x58(%rbx)
je 0x58e6
movq %rbx, %rdi
callq 0x5f7c
leaq 0x22(%rsp), %r12
movw %ax, (%r12)
movw $0x1, 0x2(%r12)
movq %r15, %rdi
movl %ebp, %esi
movq %r12, %rdx
callq 0x6d52
movzwl (%r12), %esi
movq %rbx, %rdi
callq 0x6094
movq %r14, 0x28(%rsp)
movw %bp, 0x30(%rsp)
movzwl (%r12), %eax
movw %ax, 0x32(%rsp)
movq 0xa0(%rbx), %rax
cmpq 0xa8(%rbx), %rax
je 0x5b0e
movups 0x28(%rsp), %xmm0
movups %xmm0, -0x10(%rax)
addq $-0x10, 0xa0(%rbx)
jmp 0x5b22
movq (%r13), %rax
movq -0x18(%rax), %rdi
addq %r13, %rdi
movl $0xa, %esi
callq 0x21b0
movsbl %al, %esi
movq %r13, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2140
leaq 0x88(%rsp), %r13
movq %r13, -0x10(%r13)
leaq 0x2935(%rip), %rsi      # 0x8256
leaq 0x293b(%rip), %rdx      # 0x8263
leaq 0x78(%rsp), %rdi
callq 0x43f0
movq %rsp, %rdi
leaq 0x78(%rsp), %rsi
callq 0x6288
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
movq 0x6679(%rip), %rdi      # 0xbfc8
callq 0x2200
movq %rax, %r12
leaq 0x2906(%rip), %rsi      # 0x8264
movl $0x24, %edx
movq %rax, %rdi
callq 0x2200
movq (%r14), %rsi
movq 0x8(%r14), %rdx
movq %r12, %rdi
callq 0x2200
movq %rax, %r12
leaq 0x28ba(%rip), %rsi      # 0x823e
movl $0x6, %edx
movq %rax, %rdi
callq 0x2200
movq %r12, %rdi
movq %rbp, %rsi
callq 0x2130
movq (%rsp), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0x59b7
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x78(%rsp), %rdi
cmpq %r13, %rdi
je 0x59d1
movq 0x88(%rsp), %rsi
incq %rsi
callq 0x21d0
movq %rbx, %rdi
callq 0x6120
movw %ax, 0x22(%rsp)
movw $0x1, 0x24(%rsp)
movq 0x65dc(%rip), %rdi      # 0xbfc8
leaq 0x2852(%rip), %rsi      # 0x8245
movl $0xb, %edx
callq 0x2200
leaq 0x68(%rsp), %r13
movq %r13, -0x10(%r13)
leaq 0x287c(%rip), %rsi      # 0x8289
leaq 0x287b(%rip), %rdx      # 0x828f
leaq 0x58(%rsp), %rdi
callq 0x43f0
movq %rsp, %rdi
leaq 0x58(%rsp), %rsi
callq 0x6288
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
movq 0x658d(%rip), %rdi      # 0xbfc8
callq 0x2200
movq %rax, %r12
leaq 0x2791(%rip), %rsi      # 0x81db
movl $0x7, %edx
movq %rax, %rdi
callq 0x2200
movzwl 0x22(%rsp), %esi
movq %r12, %rdi
callq 0x2130
movq %rax, %r12
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x21b0
movsbl %al, %esi
movq %r12, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2140
movq (%rsp), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0x5aa9
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x58(%rsp), %rdi
cmpq %r13, %rdi
je 0x5ac0
movq 0x68(%rsp), %rsi
incq %rsi
callq 0x21d0
leaq 0x22(%rsp), %r12
movq %r15, %rdi
movl %ebp, %esi
movq %r12, %rdx
callq 0x6d52
movq %r14, (%rsp)
movw %bp, 0x8(%rsp)
movzwl (%r12), %eax
movw %ax, 0xa(%rsp)
movq 0xa0(%rbx), %rax
cmpq 0xa8(%rbx), %rax
je 0x5d75
movups (%rsp), %xmm0
movups %xmm0, -0x10(%rax)
addq $-0x10, 0xa0(%rbx)
jmp 0x5d87
addq $0x90, %rbx
leaq 0x28(%rsp), %rsi
movq %rbx, %rdi
callq 0x63e8
movq 0x649f(%rip), %rdi      # 0xbfc8
leaq 0x2715(%rip), %rsi      # 0x8245
movl $0xb, %edx
callq 0x2200
leaq 0xa8(%rsp), %r14
movq %r14, -0x10(%r14)
leaq 0x2704(%rip), %rsi      # 0x8251
leaq 0x2701(%rip), %rdx      # 0x8255
leaq 0x98(%rsp), %rdi
callq 0x43f0
movq %rsp, %rdi
leaq 0x98(%rsp), %rsi
callq 0x36d8
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
movq 0x6447(%rip), %rdi      # 0xbfc8
callq 0x2200
movq %rax, %rbx
leaq 0x264b(%rip), %rsi      # 0x81db
movl $0x7, %edx
movq %rax, %rdi
callq 0x2200
movzwl 0x22(%rsp), %esi
movq %rbx, %rdi
callq 0x2130
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x21b0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2140
movq (%rsp), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0x5bef
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x98(%rsp), %rdi
cmpq %r14, %rdi
je 0x5d87
movq 0xa8(%rsp), %rsi
jmp 0x5d31
leaq 0xc8(%rsp), %r13
movq %r13, -0x10(%r13)
leaq 0x25a3(%rip), %rsi      # 0x81c3
leaq 0x259d(%rip), %rdx      # 0x81c4
leaq 0xb8(%rsp), %rdi
callq 0x43f0
movq %rsp, %rdi
leaq 0xb8(%rsp), %rsi
callq 0x36d8
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
movq 0x6374(%rip), %rdi      # 0xbfc8
callq 0x2200
movq %rax, %rbx
leaq 0x2562(%rip), %rsi      # 0x81c5
movl $0x9, %edx
movq %rax, %rdi
callq 0x2200
movq (%r14), %rsi
movq 0x8(%r14), %rdx
movq %rbx, %rdi
callq 0x2200
movq %rax, %rbx
leaq 0x2546(%rip), %rsi      # 0x81cf
movl $0x7, %edx
movq %rax, %rdi
callq 0x2200
movq %rbx, %rdi
movq %r12, %rsi
callq 0x2130
movq %rax, %rbx
leaq 0x252c(%rip), %rsi      # 0x81d7
movl $0xb, %edx
movq %rax, %rdi
callq 0x2200
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2130
movq %rax, %rbx
leaq 0x2516(%rip), %rsi      # 0x81e3
movl $0x10, %edx
movq %rax, %rdi
callq 0x2200
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x21b0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2140
leaq 0x10(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x5d1c
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0xb8(%rsp), %rdi
cmpq %r13, %rdi
je 0x5d87
movq 0xc8(%rsp), %rsi
incq %rsi
callq 0x21d0
jmp 0x5d87
movq 0x6286(%rip), %rbx      # 0xbfc8
leaq 0x24ab(%rip), %rsi      # 0x81f4
movl $0x6, %edx
movq %rbx, %rdi
callq 0x2200
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2130
movq %rax, %rbx
leaq 0x2490(%rip), %rsi      # 0x81fb
movl $0x13, %edx
jmp 0x5750
addq $0x90, %rbx
movq %rsp, %rsi
movq %rbx, %rdi
callq 0x63e8
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
jmp 0x5e25
jmp 0x5dc6
movq %rax, %rbx
jmp 0x5e61
jmp 0x5dc6
movq %rax, %rbx
jmp 0x5dec
jmp 0x5dc6
movq %rax, %rbx
jmp 0x5e90
jmp 0x5dc6
movq %rax, %rbx
jmp 0x5ec5
movq %rax, %rbx
jmp 0x5ee1
movq %rax, %rbx
movq (%rsp), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0x5dec
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x78(%rsp), %rdi
cmpq %r13, %rdi
je 0x5ee1
movq 0x88(%rsp), %rsi
jmp 0x5ed9
movq %rax, %rbx
leaq 0x10(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x5e25
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0xb8(%rsp), %rdi
cmpq %r13, %rdi
je 0x5ee1
movq 0xc8(%rsp), %rsi
jmp 0x5ed9
movq %rax, %rbx
movq (%rsp), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0x5e61
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x58(%rsp), %rdi
cmpq %r13, %rdi
je 0x5ee1
movq 0x68(%rsp), %rsi
jmp 0x5ed9
movq %rax, %rbx
movq (%rsp), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0x5e90
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x98(%rsp), %rdi
cmpq %r14, %rdi
je 0x5ee1
movq 0xa8(%rsp), %rsi
jmp 0x5ed9
movq %rax, %rbx
leaq 0x10(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x5ec5
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x38(%rsp), %rdi
leaq 0x48(%rsp), %rax
cmpq %rax, %rdi
je 0x5ee1
movq 0x48(%rsp), %rsi
incq %rsi
callq 0x21d0
movq %rbx, %rdi
callq 0x22f0
nop