/*
 * 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 <android-base/logging.h>

#include "arch/arm64/registers_arm64.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:
  constexpr XRegister AsXRegister() const {
    CHECK(IsXRegister());
    return static_cast<XRegister>(id_);
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

  constexpr 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 constexpr Arm64ManagedRegister FromXRegister(XRegister r) {
    CHECK_NE(r, kNoRegister);
    return FromRegId(r);
  }

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

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

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

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

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

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

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

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

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

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

  friend class ManagedRegister;

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

  static constexpr 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

constexpr 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_
