// File: /workspace/github_cpp_makefile_star2_O1/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 0x6cd8
testb %al, %al
je 0x580c
movzwl %bp, %r12d
movq %r15, %rdi
movl %r12d, %esi
callq 0x6d56
movzwl (%rax), %r15d
movq 0x10(%rbx), %rdx
leaq 0x8(%rbx), %rax
movq %rax, %rcx
testq %rdx, %rdx
je 0x56c2
movq %rax, %rcx
xorl %esi, %esi
cmpw %r15w, 0x20(%rdx)
setb %sil
cmovaeq %rdx, %rcx
movq 0x10(%rdx,%rsi,8), %rdx
testq %rdx, %rdx
jne 0x56a9
movq %rax, %rdx
cmpq %rax, %rcx
je 0x56d6
cmpw %r15w, 0x20(%rcx)
cmovaq %rax, %rcx
movq %rcx, %rdx
cmpq %rax, %rdx
je 0x5966
leaq 0xc8(%rsp), %r13
movq %r13, -0x10(%r13)
leaq 0x2ad1(%rip), %rsi      # 0x81c3
leaq 0x2acb(%rip), %rdx      # 0x81c4
leaq 0xb8(%rsp), %rdi
callq 0x43a8
movq %rsp, %rdi
leaq 0xb8(%rsp), %rsi
callq 0x36e0
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
movq 0x68a2(%rip), %rdi      # 0xbfc8
callq 0x2200
movq %rax, %rbx
leaq 0x2a90(%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 0x2a74(%rip), %rsi      # 0x81cf
movl $0x7, %edx
movq %rax, %rdi
callq 0x2200
movq %rbx, %rdi
movq %r12, %rsi
callq 0x2130
movq %rax, %rbx
leaq 0x2a5a(%rip), %rsi      # 0x81d7
movl $0xb, %edx
movq %rax, %rdi
callq 0x2200
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2130
movq %rax, %rbx
leaq 0x2a44(%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 0x57ee
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0xb8(%rsp), %rdi
cmpq %r13, %rdi
je 0x5d0e
movq 0xc8(%rsp), %rsi
jmp 0x5d06
leaq 0x48(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x2a13(%rip), %rsi      # 0x822f
leaq 0x2a1a(%rip), %rdx      # 0x823d
leaq 0x38(%rsp), %rdi
callq 0x43a8
movq %rsp, %rdi
leaq 0x38(%rsp), %rsi
callq 0x619c
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
movq 0x677e(%rip), %r13      # 0xbfc8
movq %r13, %rdi
callq 0x2200
movq %rax, %r12
leaq 0x2a1f(%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 0x29bc(%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 0x58b8
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x38(%rsp), %rdi
leaq 0x48(%rsp), %rax
cmpq %rax, %rdi
je 0x58d4
movq 0x48(%rsp), %rsi
incq %rsi
callq 0x21d0
movq %r14, %rdi
callq 0x6870
movl $0x0, 0x22(%rsp)
movb $0x1, 0x26(%rsp)
cmpq $0x0, 0x58(%rbx)
je 0x59e8
movq %rbx, %rdi
callq 0x5f8e
leaq 0x22(%rsp), %r12
movw %ax, (%r12)
movw $0x1, 0x2(%r12)
movq %r15, %rdi
movl %ebp, %esi
movq %r12, %rdx
callq 0x6d16
movzwl (%r12), %esi
movq %rbx, %rdi
callq 0x60a6
movq %r14, 0x28(%rsp)
movw %bp, 0x30(%rsp)
movzwl (%r12), %eax
movw %ax, 0x32(%rsp)
movq 0xa0(%rbx), %rax
cmpq 0xa8(%rbx), %rax
je 0x5c10
movups 0x28(%rsp), %xmm0
movups %xmm0, -0x10(%rax)
addq $-0x10, 0xa0(%rbx)
jmp 0x5c24
movq 0x70(%rbx), %rcx
addq $0x68, %rbx
movq %rbx, %rax
testq %rcx, %rcx
je 0x5991
movq %rbx, %rax
xorl %edx, %edx
cmpw %r15w, 0x20(%rcx)
setb %dl
cmovaeq %rcx, %rax
movq 0x10(%rcx,%rdx,8), %rcx
testq %rcx, %rcx
jne 0x5979
movq %rbx, %rcx
cmpq %rbx, %rax
je 0x59a5
cmpw %r15w, 0x20(%rax)
cmovaq %rbx, %rax
movq %rax, %rcx
cmpq %rbx, %rcx
je 0x5d20
movq 0x6613(%rip), %rbx      # 0xbfc8
leaq 0x2838(%rip), %rsi      # 0x81f4
movl $0x6, %edx
movq %rbx, %rdi
callq 0x2200
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2130
movq %rax, %rbx
leaq 0x281d(%rip), %rsi      # 0x81fb
movl $0x13, %edx
jmp 0x5d55
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 0x2833(%rip), %rsi      # 0x8256
leaq 0x2839(%rip), %rdx      # 0x8263
leaq 0x78(%rsp), %rdi
callq 0x43a8
movq %rsp, %rdi
leaq 0x78(%rsp), %rsi
callq 0x6284
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
movq 0x6577(%rip), %rdi      # 0xbfc8
callq 0x2200
movq %rax, %r12
leaq 0x2804(%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 0x27b8(%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 0x5ab9
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x78(%rsp), %rdi
cmpq %r13, %rdi
je 0x5ad3
movq 0x88(%rsp), %rsi
incq %rsi
callq 0x21d0
movq %rbx, %rdi
callq 0x6148
movw %ax, 0x22(%rsp)
movw $0x1, 0x24(%rsp)
movq 0x64da(%rip), %rdi      # 0xbfc8
leaq 0x2750(%rip), %rsi      # 0x8245
movl $0xb, %edx
callq 0x2200
leaq 0x68(%rsp), %r13
movq %r13, -0x10(%r13)
leaq 0x277a(%rip), %rsi      # 0x8289
leaq 0x2779(%rip), %rdx      # 0x828f
leaq 0x58(%rsp), %rdi
callq 0x43a8
movq %rsp, %rdi
leaq 0x58(%rsp), %rsi
callq 0x6284
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
movq 0x648b(%rip), %rdi      # 0xbfc8
callq 0x2200
movq %rax, %r12
leaq 0x268f(%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 0x5bab
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x58(%rsp), %rdi
cmpq %r13, %rdi
je 0x5bc2
movq 0x68(%rsp), %rsi
incq %rsi
callq 0x21d0
leaq 0x22(%rsp), %r12
movq %r15, %rdi
movl %ebp, %esi
movq %r12, %rdx
callq 0x6d16
movq %r14, (%rsp)
movw %bp, 0x8(%rsp)
movzwl (%r12), %eax
movw %ax, 0xa(%rsp)
movq 0xa0(%rbx), %rax
cmpq 0xa8(%rbx), %rax
je 0x5d95
movups (%rsp), %xmm0
movups %xmm0, -0x10(%rax)
addq $-0x10, 0xa0(%rbx)
jmp 0x5d0e
addq $0x90, %rbx
leaq 0x28(%rsp), %rsi
movq %rbx, %rdi
callq 0x63b8
movq 0x639d(%rip), %rdi      # 0xbfc8
leaq 0x2613(%rip), %rsi      # 0x8245
movl $0xb, %edx
callq 0x2200
leaq 0xa8(%rsp), %r14
movq %r14, -0x10(%r14)
leaq 0x2602(%rip), %rsi      # 0x8251
leaq 0x25ff(%rip), %rdx      # 0x8255
leaq 0x98(%rsp), %rdi
callq 0x43a8
movq %rsp, %rdi
leaq 0x98(%rsp), %rsi
callq 0x36e0
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
movq 0x6345(%rip), %rdi      # 0xbfc8
callq 0x2200
movq %rax, %rbx
leaq 0x2549(%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 0x5cf1
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x98(%rsp), %rdi
cmpq %r14, %rdi
je 0x5d0e
movq 0xa8(%rsp), %rsi
incq %rsi
callq 0x21d0
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x62c9(%rip), %rbx      # 0xbff0
leaq 0x24c6(%rip), %rsi      # 0x81f4
movl $0x6, %edx
movq %rbx, %rdi
callq 0x2200
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2130
movq %rax, %rbx
leaq 0x24bf(%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
addq $0x90, %rbx
movq %rsp, %rsi
movq %rbx, %rdi
callq 0x63b8
jmp 0x5d0e
movq %rax, %rbx
jmp 0x5e38
jmp 0x5dd9
movq %rax, %rbx
jmp 0x5dff
jmp 0x5dd9
movq %rax, %rbx
jmp 0x5e6e
jmp 0x5dd9
movq %rax, %rbx
jmp 0x5ed7
jmp 0x5dd9
movq %rax, %rbx
jmp 0x5ea3
movq %rax, %rbx
jmp 0x5ef4
movq %rax, %rbx
movq (%rsp), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0x5dff
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x78(%rsp), %rdi
cmpq %r13, %rdi
je 0x5ef4
movq 0x88(%rsp), %rsi
jmp 0x5eec
movq %rax, %rbx
movq (%rsp), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0x5e38
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x58(%rsp), %rdi
cmpq %r13, %rdi
je 0x5ef4
movq 0x68(%rsp), %rsi
jmp 0x5eec
movq %rax, %rbx
movq (%rsp), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0x5e6e
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x98(%rsp), %rdi
cmpq %r14, %rdi
je 0x5ef4
movq 0xa8(%rsp), %rsi
jmp 0x5eec
movq %rax, %rbx
leaq 0x10(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x5ea3
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x38(%rsp), %rdi
leaq 0x48(%rsp), %rax
cmpq %rax, %rdi
je 0x5ef4
movq 0x48(%rsp), %rsi
jmp 0x5eec
movq %rax, %rbx
leaq 0x10(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x5ed7
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0xb8(%rsp), %rdi
cmpq %r13, %rdi
je 0x5ef4
movq 0xc8(%rsp), %rsi
incq %rsi
callq 0x21d0
movq %rbx, %rdi
callq 0x22f0