// File: /workspace/github_cpp_makefile_star2_O2/CMU-SAFARI[P]ramulator/src/Memory.h
// Function: ramulator::Memory<ramulator::DDR3, ramulator::Controller>::page_allocator(long, int)
long page_allocator(long addr, int coreid) {
        long virtual_page_number = addr >> 12;

        switch(int(translation)) {
            case int(Translation::None): {
              return addr;
            }
            case int(Translation::Random): {
                auto target = make_pair(coreid, virtual_page_number);
                if(page_translation.find(target) == page_translation.end()) {
                    // page doesn't exist, so assign a new page
                    // make sure there are physical pages left to be assigned

                    // if physical page doesn't remain, replace a previous assigned
                    // physical page.
                    if (!free_physical_pages_remaining) {
                      physical_page_replacement++;
                      long phys_page_to_read = lrand() % free_physical_pages.size();
                      assert(free_physical_pages[phys_page_to_read] != -1);
                      page_translation[target] = phys_page_to_read;
                    } else {
                        // assign a new page
                        long phys_page_to_read = lrand() % free_physical_pages.size();
                        // if the randomly-selected page was already assigned
                        if(free_physical_pages[phys_page_to_read] != -1) {
                            long starting_page_of_search = phys_page_to_read;

                            do {
                                // iterate through the list until we find a free page
                                // TODO: does this introduce serious non-randomness?
                                ++phys_page_to_read;
                                phys_page_to_read %= free_physical_pages.size();
                            }
                            while((phys_page_to_read != starting_page_of_search) && free_physical_pages[phys_page_to_read] != -1);
                        }

                        assert(free_physical_pages[phys_page_to_read] == -1);

                        page_translation[target] = phys_page_to_read;
                        free_physical_pages[phys_page_to_read] = coreid;
                        --free_physical_pages_remaining;
                    }
                }

                // SAUGATA TODO: page size should not always be fixed to 4KB
                return (page_translation[target] << 12) | (addr & ((1 << 12) - 1));
            }
            default:
                assert(false);
        }

    }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x10, %rsp
movq %rsi, %rbx
movl 0xb84(%rdi), %eax
testl %eax, %eax
je 0x1db2a
cmpl $0x1, %eax
jne 0x1db59
movl %edx, %ebp
movq %rdi, %r15
movq %rbx, %rax
sarq $0xc, %rax
movq %rsp, %rsi
movl %edx, (%rsi)
movq %rax, 0x8(%rsi)
leaq 0xbd8(%rdi), %r14
movq %r14, %rdi
callq 0x21a54
leaq 0xbe0(%r15), %rcx
cmpq %rcx, %rax
jne 0x1db0f
cmpq $0x0, 0xbd0(%r15)
je 0x1da93
movq %r15, %rdi
callq 0x219d6
movq 0xbb8(%r15), %rcx
movq 0xbc0(%r15), %rsi
subq %rcx, %rsi
sarq $0x2, %rsi
xorl %edx, %edx
divq %rsi
cmpl $-0x1, (%rcx,%rdx,4)
je 0x1daec
xorl %eax, %eax
movq %rdx, %r12
incq %r12
cmpq %rsi, %r12
cmoveq %rax, %r12
cmpq %rdx, %r12
je 0x1db3a
cmpl $-0x1, (%rcx,%r12,4)
jne 0x1da77
jmp 0x1daef
movsd 0x598(%r15), %xmm0
addsd 0xb35d4(%rip), %xmm0    # 0xd1078
movsd %xmm0, 0x598(%r15)
movq %r15, %rdi
callq 0x219d6
movq 0xbb8(%r15), %rcx
movq 0xbc0(%r15), %rsi
subq %rcx, %rsi
sarq $0x2, %rsi
xorl %edx, %edx
divq %rsi
cmpl $-0x1, (%rcx,%rdx,4)
je 0x1db78
movq %rdx, %r15
movq %rsp, %rsi
movq %r14, %rdi
callq 0x219ee
movq %r15, (%rax)
jmp 0x1db0f
movq %rdx, %r12
movq %rsp, %rsi
movq %r14, %rdi
callq 0x219ee
movq %r12, (%rax)
movq 0xbb8(%r15), %rax
movl %ebp, (%rax,%r12,4)
decq 0xbd0(%r15)
movq %rsp, %rsi
movq %r14, %rdi
callq 0x219ee
movq (%rax), %rax
shlq $0xc, %rax
andl $0xfff, %ebx            # imm = 0xFFF
orq %rax, %rbx
movq %rbx, %rax
addq $0x10, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0xb53a6(%rip), %rdi     # 0xd2ee7
leaq 0xb4669(%rip), %rsi     # 0xd21b1
leaq 0xb5313(%rip), %rcx     # 0xd2e62
movl $0x22f, %edx            # imm = 0x22F
callq 0xb210
leaq 0xb37f9(%rip), %rdi     # 0xd1359
leaq 0xb464a(%rip), %rsi     # 0xd21b1
leaq 0xb52f4(%rip), %rcx     # 0xd2e62
movl $0x23b, %edx            # imm = 0x23B
callq 0xb210
leaq 0xb52b6(%rip), %rdi     # 0xd2e35
leaq 0xb462b(%rip), %rsi     # 0xd21b1
leaq 0xb52d5(%rip), %rcx     # 0xd2e62
movl $0x21d, %edx            # imm = 0x21D
callq 0xb210
nop