// File: /workspace/github_cpp_makefile_star2_O3/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 0x26ff2
cmpl $0x1, %eax
jne 0x27021
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 0x2b654
leaq 0xbe0(%r15), %rcx
cmpq %rcx, %rax
jne 0x26fd7
cmpq $0x0, 0xbd0(%r15)
je 0x26f4d
callq 0xb0e0
movl %eax, %r12d
shlq $0x20, %r12
callq 0xb0e0
cltq
orq %r12, %rax
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 0x26fb4
xorl %eax, %eax
movq %rdx, %r12
incq %r12
cmpq %rsi, %r12
cmoveq %rax, %r12
cmpq %rdx, %r12
je 0x27002
cmpl $-0x1, (%rcx,%r12,4)
jne 0x26f31
jmp 0x26fb7
movsd 0x598(%r15), %xmm0
addsd 0x12315a(%rip), %xmm0   # 0x14a0b8
movsd %xmm0, 0x598(%r15)
callq 0xb0e0
movl %eax, %r12d
shlq $0x20, %r12
callq 0xb0e0
cltq
orq %r12, %rax
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 0x27040
movq %rdx, %r15
movq %rsp, %rsi
movq %r14, %rdi
callq 0x2b5c8
movq %r15, (%rax)
jmp 0x26fd7
movq %rdx, %r12
movq %rsp, %rsi
movq %r14, %rdi
callq 0x2b5c8
movq %r12, (%rax)
movq 0xbb8(%r15), %rax
movl %ebp, (%rax,%r12,4)
decq 0xbd0(%r15)
movq %rsp, %rsi
movq %r14, %rdi
callq 0x2b5c8
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 0x124f62(%rip), %rdi    # 0x14bf6b
leaq 0x1241e1(%rip), %rsi    # 0x14b1f1
leaq 0x124ecf(%rip), %rcx    # 0x14bee6
movl $0x22f, %edx            # imm = 0x22F
callq 0xb200
leaq 0x123371(%rip), %rdi    # 0x14a399
leaq 0x1241c2(%rip), %rsi    # 0x14b1f1
leaq 0x124eb0(%rip), %rcx    # 0x14bee6
movl $0x23b, %edx            # imm = 0x23B
callq 0xb200
leaq 0x124e72(%rip), %rdi    # 0x14beb9
leaq 0x1241a3(%rip), %rsi    # 0x14b1f1
leaq 0x124e91(%rip), %rcx    # 0x14bee6
movl $0x21d, %edx            # imm = 0x21D
callq 0xb200
nop