abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,

                       abi_ulong new_size, unsigned long flags,

                       abi_ulong new_addr)

{

    int prot;

    void *host_addr;



    mmap_lock();



    if (flags & MREMAP_FIXED) {

        host_addr = (void *) syscall(__NR_mremap, g2h(old_addr),

                                     old_size, new_size,

                                     flags,

                                     g2h(new_addr));



        if (RESERVED_VA && host_addr != MAP_FAILED) {

            /* If new and old addresses overlap then the above mremap will

               already have failed with EINVAL.  */

            mmap_reserve(old_addr, old_size);

        }

    } else if (flags & MREMAP_MAYMOVE) {

        abi_ulong mmap_start;



        mmap_start = mmap_find_vma(0, new_size);



        if (mmap_start == -1) {

            errno = ENOMEM;

            host_addr = MAP_FAILED;

        } else {

            host_addr = (void *) syscall(__NR_mremap, g2h(old_addr),

                                         old_size, new_size,

                                         flags | MREMAP_FIXED,

                                         g2h(mmap_start));

            mmap_reserve(old_addr, old_size);

        }

    } else {

        int prot = 0;

        if (RESERVED_VA && old_size < new_size) {

            abi_ulong addr;

            for (addr = old_addr + old_size;

                 addr < old_addr + new_size;

                 addr++) {

                prot |= page_get_flags(addr);

            }

        }

        if (prot == 0) {

            host_addr = mremap(g2h(old_addr), old_size, new_size, flags);

            if (host_addr != MAP_FAILED && RESERVED_VA && old_size > new_size) {

                mmap_reserve(old_addr + old_size, new_size - old_size);

            }

        } else {

            errno = ENOMEM;

            host_addr = MAP_FAILED;

        }

        /* Check if address fits target address space */

        if ((unsigned long)host_addr + new_size > (abi_ulong)-1) {

            /* Revert mremap() changes */

            host_addr = mremap(g2h(old_addr), new_size, old_size, flags);

            errno = ENOMEM;

            host_addr = MAP_FAILED;

        }

    }



    if (host_addr == MAP_FAILED) {

        new_addr = -1;

    } else {

        new_addr = h2g(host_addr);

        prot = page_get_flags(old_addr);

        page_set_flags(old_addr, old_addr + old_size, 0);

        page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);

    }

    mmap_unlock();

    return new_addr;

}

abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,

                       abi_ulong new_size, unsigned long flags,

                       abi_ulong new_addr)

{

    int prot;

    void *host_addr;



    mmap_lock();



    if (flags & MREMAP_FIXED) {

        host_addr = (void *) syscall(__NR_mremap, g2h(old_addr),

                                     old_size, new_size,

                                     flags,

                                     g2h(new_addr));



        if (RESERVED_VA && host_addr != MAP_FAILED) {

            



            mmap_reserve(old_addr, old_size);

        }

    } else if (flags & MREMAP_MAYMOVE) {

        abi_ulong mmap_start;



        mmap_start = mmap_find_vma(0, new_size);



        if (mmap_start == -1) {

            errno = ENOMEM;

            host_addr = MAP_FAILED;

        } else {

            host_addr = (void *) syscall(__NR_mremap, g2h(old_addr),

                                         old_size, new_size,

                                         flags | MREMAP_FIXED,

                                         g2h(mmap_start));

            mmap_reserve(old_addr, old_size);

        }

    } else {

        int prot = 0;

        if (RESERVED_VA && old_size < new_size) {

            abi_ulong addr;

            for (addr = old_addr + old_size;

                 addr < old_addr + new_size;

                 addr++) {

                prot |= page_get_flags(addr);

            }

        }

        if (prot == 0) {

            host_addr = mremap(g2h(old_addr), old_size, new_size, flags);

            if (host_addr != MAP_FAILED && RESERVED_VA && old_size > new_size) {

                mmap_reserve(old_addr + old_size, new_size - old_size);

            }

        } else {

            errno = ENOMEM;

            host_addr = MAP_FAILED;

        }

        

        if ((unsigned long)host_addr + new_size > (abi_ulong)-1) {

            

            host_addr = mremap(g2h(old_addr), new_size, old_size, flags);

            errno = ENOMEM;

            host_addr = MAP_FAILED;

        }

    }



    if (host_addr == MAP_FAILED) {

        new_addr = -1;

    } else {

        new_addr = h2g(host_addr);

        prot = page_get_flags(old_addr);

        page_set_flags(old_addr, old_addr + old_size, 0);

        page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);

    }

    mmap_unlock();

    return new_addr;

}

abi_long FUNC_0(abi_ulong old_addr, abi_ulong old_size,

                       abi_ulong new_size, unsigned long flags,

                       abi_ulong new_addr)

{

    int VAR_2;

    void *VAR_1;



    mmap_lock();



    if (flags & MREMAP_FIXED) {

        VAR_1 = (void *) syscall(__NR_mremap, g2h(old_addr),

                                     old_size, new_size,

                                     flags,

                                     g2h(new_addr));



        if (RESERVED_VA && VAR_1 != MAP_FAILED) {

            



            mmap_reserve(old_addr, old_size);

        }

    } else if (flags & MREMAP_MAYMOVE) {

        abi_ulong mmap_start;



        mmap_start = mmap_find_vma(0, new_size);



        if (mmap_start == -1) {

            errno = ENOMEM;

            VAR_1 = MAP_FAILED;

        } else {

            VAR_1 = (void *) syscall(__NR_mremap, g2h(old_addr),

                                         old_size, new_size,

                                         flags | MREMAP_FIXED,

                                         g2h(mmap_start));

            mmap_reserve(old_addr, old_size);

        }

    } else {

        int VAR_2 = 0;

        if (RESERVED_VA && old_size < new_size) {

            abi_ulong addr;

            for (addr = old_addr + old_size;

                 addr < old_addr + new_size;

                 addr++) {

                VAR_2 |= page_get_flags(addr);

            }

        }

        if (VAR_2 == 0) {

            VAR_1 = mremap(g2h(old_addr), old_size, new_size, flags);

            if (VAR_1 != MAP_FAILED && RESERVED_VA && old_size > new_size) {

                mmap_reserve(old_addr + old_size, new_size - old_size);

            }

        } else {

            errno = ENOMEM;

            VAR_1 = MAP_FAILED;

        }

        

        if ((unsigned long)VAR_1 + new_size > (abi_ulong)-1) {

            

            VAR_1 = mremap(g2h(old_addr), new_size, old_size, flags);

            errno = ENOMEM;

            VAR_1 = MAP_FAILED;

        }

    }



    if (VAR_1 == MAP_FAILED) {

        new_addr = -1;

    } else {

        new_addr = h2g(VAR_1);

        VAR_2 = page_get_flags(old_addr);

        page_set_flags(old_addr, old_addr + old_size, 0);

        page_set_flags(new_addr, new_addr + new_size, VAR_2 | PAGE_VALID);

    }

    mmap_unlock();

    return new_addr;

}

abi_long FUNC_0(abi_ulong old_addr, abi_ulong old_size,
abi_ulong new_size, unsigned long flags,
abi_ulong new_addr)
{ int VAR_2; void *VAR_1; mmap_lock(); if (flags & MREMAP_FIXED) { VAR_1 = (void *) syscall(__NR_mremap, g2h(old_addr),
old_size, new_size,
flags,
g2h(new_addr)); if (RESERVED_VA && VAR_1 != MAP_FAILED) { mmap_reserve(old_addr, old_size); } } else if (flags & MREMAP_MAYMOVE) { abi_ulong mmap_start; mmap_start = mmap_find_vma(0, new_size); if (mmap_start == -1) { errno = ENOMEM; VAR_1 = MAP_FAILED; } else { VAR_1 = (void *) syscall(__NR_mremap, g2h(old_addr),
old_size, new_size,
flags | MREMAP_FIXED,
g2h(mmap_start)); mmap_reserve(old_addr, old_size); } } else { int VAR_2 = 0; if (RESERVED_VA && old_size < new_size) { abi_ulong addr; for (addr = old_addr + old_size; addr < old_addr + new_size; addr++) { VAR_2 |= page_get_flags(addr); } } if (VAR_2 == 0) { VAR_1 = mremap(g2h(old_addr), old_size, new_size, flags); if (VAR_1 != MAP_FAILED && RESERVED_VA && old_size > new_size) { mmap_reserve(old_addr + old_size, new_size - old_size); } } else { errno = ENOMEM; VAR_1 = MAP_FAILED; } if ((unsigned long)VAR_1 + new_size > (abi_ulong)-1) { VAR_1 = mremap(g2h(old_addr), new_size, old_size, flags); errno = ENOMEM; VAR_1 = MAP_FAILED; } } if (VAR_1 == MAP_FAILED) { new_addr = -1; } else { new_addr = h2g(VAR_1); VAR_2 = page_get_flags(old_addr); page_set_flags(old_addr, old_addr + old_size, 0); page_set_flags(new_addr, new_addr + new_size, VAR_2 | PAGE_VALID); } mmap_unlock(); return new_addr; }