/*
 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
 *
 *  This file is licensed to You under the Eclipse Public License (EPL);
 *  You may not use this file except in compliance with the License. You
 *  may obtain a copy of the License at
 *
 *      http://www.opensource.org/licenses/eclipse-1.0.php
 *
 *  See the COPYRIGHT.txt file distributed with this work for information
 *  regarding copyright ownership.
 */
package org.mmtk.utility;

import org.mmtk.utility.heap.*;

import org.mmtk.vm.VM;

import org.vmmagic.unboxed.*;
import org.vmmagic.pragma.*;

/*
 import org.jikesrvm.Offset;
 * Conversions between different units.
 */
@Uninterruptible public class Conversions implements Constants {

  // public static Address roundDownVM(Address addr) {
  //   return roundDown(addr.toWord(), VMResource.LOG_BYTES_IN_REGION).toAddress();
  // }

  // public static Extent roundDownVM(Extent bytes) {
  //   return roundDown(bytes.toWord(), VMResource.LOG_BYTES_IN_REGION).toExtent();
  // }

  public static Address roundDownMB(Address addr) {
    return roundDown(addr.toWord(), LOG_BYTES_IN_MBYTE).toAddress();
  }

  public static Extent roundDownMB(Extent bytes) {
    return roundDown(bytes.toWord(), LOG_BYTES_IN_MBYTE).toExtent();
  }

  private static Word roundDown(Word value, int logBase) {
    Word mask = Word.one().lsh(logBase).minus(Word.one()).not();
    return value.and(mask);
  }

  public static int roundDown(int value, int alignment) {
    return value & ~(alignment - 1);
  }

  // Round up (if necessary)
  //
  public static int MBToPages(int megs) {
    if (LOG_BYTES_IN_PAGE <= LOG_BYTES_IN_MBYTE)
      return (megs << (LOG_BYTES_IN_MBYTE - LOG_BYTES_IN_PAGE));
    else
      return (megs + ((BYTES_IN_PAGE >>> LOG_BYTES_IN_MBYTE) - 1)) >>> (LOG_BYTES_IN_PAGE - LOG_BYTES_IN_MBYTE);
  }

  public static int bytesToMmapChunksUp(Extent bytes) {
    return bytes.plus(Mmapper.MMAP_CHUNK_BYTES - 1).toWord().rshl(Mmapper.LOG_MMAP_CHUNK_BYTES).toInt();
  }

  public static int pagesToMmapChunksUp(int pages) {
    return bytesToMmapChunksUp(pagesToBytes(pages));
  }

  public static int addressToMmapChunksDown(Address addr) {
    Word chunk = addr.toWord().rshl(Mmapper.LOG_MMAP_CHUNK_BYTES);
    return chunk.toInt();
  }

  public static int addressToPagesDown(Address addr) {
    Word chunk = addr.toWord().rshl(LOG_BYTES_IN_PAGE);
    return chunk.toInt();
  }

  public static int addressToPages(Address addr) {
    int page = addressToPagesDown(addr);
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(pagesToAddress(page).EQ(addr));
    return page;
  }

  public static Address pagesToAddress(int pages) {
    return Word.fromIntZeroExtend(pages).lsh(LOG_BYTES_IN_PAGE).toAddress();
  }

  public static int addressToMmapChunksUp(Address addr) {
    Word chunk = addr.plus(Mmapper.MMAP_CHUNK_BYTES - 1).toWord().rshl(Mmapper.LOG_MMAP_CHUNK_BYTES);
    return chunk.toInt();
  }

  public static Extent pagesToBytes(int pages) {
    return Word.fromIntZeroExtend(pages).lsh(LOG_BYTES_IN_PAGE).toExtent();
  }

  public static int pagesToMBytes(int pages) {
    return pages >> (LOG_BYTES_IN_MBYTE - LOG_BYTES_IN_PAGE);
  }

  public static int pagesToKBytes(int pages) {
    return pages << (LOG_BYTES_IN_PAGE - LOG_BYTES_IN_KBYTE);
  }

  /**
    @deprecated : use int bytesToPagesUp(Extent bytes) if possible
   */
  @Deprecated
  public static int bytesToPagesUp(int bytes) {
    return bytesToPagesUp(Extent.fromIntZeroExtend(bytes));
  }

  /**
    @deprecated : use int bytesToPagesUp(Extent bytes) if possible
   */
  @Deprecated
  public static int bytesToPages(int bytes) {
    return bytesToPages(Extent.fromIntZeroExtend(bytes));
  }

  public static int bytesToPagesUp(Extent bytes) {
    return bytes.plus(BYTES_IN_PAGE-1).toWord().rshl(LOG_BYTES_IN_PAGE).toInt();
  }

  public static int bytesToPages(Extent bytes) {
    int pages = bytesToPagesUp(bytes);
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(pagesToAddress(pages).toWord().toExtent().EQ(bytes));
    return pages;
  }

  public static int bytesToPages(Offset bytes) {
    if (VM.VERIFY_ASSERTIONS) {
      long val = bytes.toLong();
      VM.assertions._assert(val >= MIN_INT && val <= MAX_INT);
    }
    if (bytes.sGE(Offset.zero()))
      return bytesToPagesUp(Extent.fromIntSignExtend(bytes.toInt()));
    else
      return -bytesToPagesUp(Extent.fromIntSignExtend(-bytes.toInt()));
  }

  public static Address mmapChunksToAddress(int chunk) {
    return Word.fromIntZeroExtend(chunk).lsh(Mmapper.LOG_MMAP_CHUNK_BYTES).toAddress();
  }

  public static Address pageAlign(Address address) {
    return address.toWord().rshl(LOG_BYTES_IN_PAGE).lsh(LOG_BYTES_IN_PAGE).toAddress();
  }

  public static int pageAlign(int value) {
    return (value>>LOG_BYTES_IN_PAGE)<<LOG_BYTES_IN_PAGE;
  }

  public static boolean isPageAligned(Address address) {
    return pageAlign(address).EQ(address);
  }

  public static boolean isPageAligned(int value) {
    return pageAlign(value) == value;
  }
}
