/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_COMPILER_UTILS_ARM64_MANAGED_REGISTER_ARM64_H_
#define ART_COMPILER_UTILS_ARM64_MANAGED_REGISTER_ARM64_H_

#include "base/logging.h"
#include "constants_arm64.h"
#include "dwarf/register.h"
#include "utils/managed_register.h"

namespace art {
namespace arm64 {

const int kNumberOfXRegIds = kNumberOfXRegisters;
const int kNumberOfWRegIds = kNumberOfWRegisters;
const int kNumberOfDRegIds = kNumberOfDRegisters;
const int kNumberOfSRegIds = kNumberOfSRegisters;

const int kNumberOfRegIds = kNumberOfXRegIds + kNumberOfWRegIds +
  kNumberOfDRegIds + kNumberOfSRegIds;

// Register ids map:
//  [0..X[  core registers 64bit (enum XRegister)
//  [X..W[  core registers 32bit (enum WRegister)
//  [W..D[  double precision VFP registers (enum DRegister)
//  [D..S[  single precision VFP registers (enum SRegister)
//
// where:
//  X = kNumberOfXRegIds
//  W = X + kNumberOfWRegIds
//  D = W + kNumberOfDRegIds
//  S = D + kNumberOfSRegIds
//
// An instance of class 'ManagedRegister' represents a single Arm64
// register. A register can be one of the following:
//  * core register 64bit context (enum XRegister)
//  * core register 32bit context (enum WRegister)
//  * VFP double precision register (enum DRegister)
//  * VFP single precision register (enum SRegister)
//
// There is a one to one mapping between ManagedRegister and register id.

class Arm64ManagedRegister : public ManagedRegister {
 public:
  XRegister AsXRegister() const {
    CHECK(IsXRegister());
    return static_cast<XRegister>(id_);
  }

  WRegister AsWRegister() const {
    CHECK(IsWRegister());
    return static_cast<WRegister>(id_ - kNumberOfXRegIds);
  }

  DRegister AsDRegister() const {
    CHECK(IsDRegister());
    return static_cast<DRegister>(id_ - kNumberOfXRegIds - kNumberOfWRegIds);
  }

  SRegister AsSRegister() const {
    CHECK(IsSRegister());
    return static_cast<SRegister>(id_ - kNumberOfXRegIds - kNumberOfWRegIds -
                                  kNumberOfDRegIds);
  }

  WRegister AsOverlappingWRegister() const {
    CHECK(IsValidManagedRegister());
    if (IsZeroRegister()) return WZR;
    return static_cast<WRegister>(AsXRegister());
  }

  XRegister AsOverlappingXRegister() const {
    CHECK(IsValidManagedRegister());
    return static_cast<XRegister>(AsWRegister());
  }

  SRegister AsOverlappingSRegister() const {
    CHECK(IsValidManagedRegister());
    return static_cast<SRegister>(AsDRegister());
  }

  DRegister AsOverlappingDRegister() const {
    CHECK(IsValidManagedRegister());
    return static_cast<DRegister>(AsSRegister());
  }

  bool IsXRegister() const {
    CHECK(IsValidManagedRegister());
    return (0 <= id_) && (id_ < kNumberOfXRegIds);
  }

  bool IsWRegister() const {
    CHECK(IsValidManagedRegister());
    const int test = id_ - kNumberOfXRegIds;
    return (0 <= test) && (test < kNumberOfWRegIds);
  }

  bool IsDRegister() const {
    CHECK(IsValidManagedRegister());
    const int test = id_ - (kNumberOfXRegIds + kNumberOfWRegIds);
    return (0 <= test) && (test < kNumberOfDRegIds);
  }

  bool IsSRegister() const {
    CHECK(IsValidManagedRegister());
    const int test = id_ - (kNumberOfXRegIds + kNumberOfWRegIds +
                            kNumberOfDRegIds);
    return (0 <= test) && (test < kNumberOfSRegIds);
  }

  bool IsGPRegister() const {
    return IsXRegister() || IsWRegister();
  }

  bool IsFPRegister() const {
    return IsDRegister() || IsSRegister();
  }

  bool IsSameType(Arm64ManagedRegister test) const {
    CHECK(IsValidManagedRegister() && test.IsValidManagedRegister());
    return
      (IsXRegister() && test.IsXRegister()) ||
      (IsWRegister() && test.IsWRegister()) ||
      (IsDRegister() && test.IsDRegister()) ||
      (IsSRegister() && test.IsSRegister());
  }

  // Returns true if the two managed-registers ('this' and 'other') overlap.
  // Either managed-register may be the NoRegister. If both are the NoRegister
  // then false is returned.
  bool Overlaps(const Arm64ManagedRegister& other) const;

  void Print(std::ostream& os) const;

  static Arm64ManagedRegister FromXRegister(XRegister r) {
    CHECK_NE(r, kNoRegister);
    return FromRegId(r);
  }

  static Arm64ManagedRegister FromWRegister(WRegister r) {
    CHECK_NE(r, kNoWRegister);
    return FromRegId(r + kNumberOfXRegIds);
  }

  static Arm64ManagedRegister FromDRegister(DRegister r) {
    CHECK_NE(r, kNoDRegister);
    return FromRegId(r + (kNumberOfXRegIds + kNumberOfWRegIds));
  }

  static Arm64ManagedRegister FromSRegister(SRegister r) {
    CHECK_NE(r, kNoSRegister);
    return FromRegId(r + (kNumberOfXRegIds + kNumberOfWRegIds +
                          kNumberOfDRegIds));
  }

  // Returns the X register overlapping W register r.
  static Arm64ManagedRegister FromWRegisterX(WRegister r) {
    CHECK_NE(r, kNoWRegister);
    return FromRegId(r);
  }

  // Return the D register overlapping S register r.
  static Arm64ManagedRegister FromSRegisterD(SRegister r) {
    CHECK_NE(r, kNoSRegister);
    return FromRegId(r + (kNumberOfXRegIds + kNumberOfWRegIds));
  }

 private:
  bool IsValidManagedRegister() const {
    return (0 <= id_) && (id_ < kNumberOfRegIds);
  }

  bool IsStackPointer() const {
    return IsXRegister() && (id_ == SP);
  }

  bool IsZeroRegister() const {
    return IsXRegister() && (id_ == XZR);
  }

  int RegId() const {
    CHECK(!IsNoRegister());
    return id_;
  }

  int RegNo() const;
  int RegIdLow() const;
  int RegIdHigh() const;

  friend class ManagedRegister;

  explicit Arm64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}

  static Arm64ManagedRegister FromRegId(int reg_id) {
    Arm64ManagedRegister reg(reg_id);
    CHECK(reg.IsValidManagedRegister());
    return reg;
  }
};

std::ostream& operator<<(std::ostream& os, const Arm64ManagedRegister& reg);

}  // namespace arm64

inline arm64::Arm64ManagedRegister ManagedRegister::AsArm64() const {
  arm64::Arm64ManagedRegister reg(id_);
  CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
  return reg;
}

}  // namespace art

#endif  // ART_COMPILER_UTILS_ARM64_MANAGED_REGISTER_ARM64_H_
