/*
* Copyright (C) 2011 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_MIPS_MANAGED_REGISTER_MIPS_H_
#define ART_COMPILER_UTILS_MIPS_MANAGED_REGISTER_MIPS_H_
#include "constants_mips.h"
#include "debug/dwarf/register.h"
#include "utils/managed_register.h"
namespace art {
namespace mips {
// Values for register pairs.
enum RegisterPair {
V0_V1 = 0,
A0_A1 = 1,
A2_A3 = 2,
T0_T1 = 3,
T2_T3 = 4,
T4_T5 = 5,
T6_T7 = 6,
S0_S1 = 7,
S2_S3 = 8,
S4_S5 = 9,
S6_S7 = 10,
A1_A2 = 11, // Dalvik style passing
kNumberOfRegisterPairs = 12,
kNoRegisterPair = -1,
};
std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
const int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
const int kNumberOfCoreAllocIds = kNumberOfCoreRegisters;
const int kNumberOfFRegIds = kNumberOfFRegisters;
const int kNumberOfFAllocIds = kNumberOfFRegisters;
const int kNumberOfDRegIds = kNumberOfDRegisters;
const int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters;
const int kNumberOfDAllocIds = kNumberOfDRegisters;
const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfFRegIds +
kNumberOfDRegIds + kNumberOfPairRegIds;
const int kNumberOfAllocIds =
kNumberOfCoreAllocIds + kNumberOfFAllocIds + kNumberOfDAllocIds;
// Register ids map:
// [0..R[ core registers (enum Register)
// [R..F[ single precision FP registers (enum FRegister)
// [F..D[ double precision FP registers (enum DRegister)
// [D..P[ core register pairs (enum RegisterPair)
// where
// R = kNumberOfCoreRegIds
// F = R + kNumberOfFRegIds
// D = F + kNumberOfDRegIds
// P = D + kNumberOfRegisterPairs
// Allocation ids map:
// [0..R[ core registers (enum Register)
// [R..F[ single precision FP registers (enum FRegister)
// where
// R = kNumberOfCoreRegIds
// F = R + kNumberOfFRegIds
// An instance of class 'ManagedRegister' represents a single core register (enum
// Register), a single precision FP register (enum FRegister), a double precision
// FP register (enum DRegister), or a pair of core registers (enum RegisterPair).
// 'ManagedRegister::NoRegister()' provides an invalid register.
// There is a one-to-one mapping between ManagedRegister and register id.
class MipsManagedRegister : public ManagedRegister {
public:
Register AsCoreRegister() const {
CHECK(IsCoreRegister());
return static_cast<Register>(id_);
}
FRegister AsFRegister() const {
CHECK(IsFRegister());
return static_cast<FRegister>(id_ - kNumberOfCoreRegIds);
}
DRegister AsDRegister() const {
CHECK(IsDRegister());
return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfFRegIds);
}
FRegister AsOverlappingDRegisterLow() const {
CHECK(IsOverlappingDRegister());
DRegister d_reg = AsDRegister();
return static_cast<FRegister>(d_reg * 2);
}
FRegister AsOverlappingDRegisterHigh() const {
CHECK(IsOverlappingDRegister());
DRegister d_reg = AsDRegister();
return static_cast<FRegister>(d_reg * 2 + 1);
}
Register AsRegisterPairLow() const {
CHECK(IsRegisterPair());
// Appropriate mapping of register ids allows to use AllocIdLow().
return FromRegId(AllocIdLow()).AsCoreRegister();
}
Register AsRegisterPairHigh() const {
CHECK(IsRegisterPair());
// Appropriate mapping of register ids allows to use AllocIdHigh().
return FromRegId(AllocIdHigh()).AsCoreRegister();
}
bool IsCoreRegister() const {
CHECK(IsValidManagedRegister());
return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
}
bool IsFRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - kNumberOfCoreRegIds;
return (0 <= test) && (test < kNumberOfFRegIds);
}
bool IsDRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds);
return (0 <= test) && (test < kNumberOfDRegIds);
}
// Returns true if this DRegister overlaps FRegisters.
bool IsOverlappingDRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds);
return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
}
bool IsRegisterPair() const {
CHECK(IsValidManagedRegister());
const int test =
id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds + kNumberOfDRegIds);
return (0 <= test) && (test < kNumberOfPairRegIds);
}
void Print(std::ostream& os) const;
// 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 MipsManagedRegister& other) const;
static MipsManagedRegister FromCoreRegister(Register r) {
CHECK_NE(r, kNoRegister);
return FromRegId(r);
}
static MipsManagedRegister FromFRegister(FRegister r) {
CHECK_NE(r, kNoFRegister);
return FromRegId(r + kNumberOfCoreRegIds);
}
static MipsManagedRegister FromDRegister(DRegister r) {
CHECK_NE(r, kNoDRegister);
return FromRegId(r + kNumberOfCoreRegIds + kNumberOfFRegIds);
}
static MipsManagedRegister FromRegisterPair(RegisterPair r) {
CHECK_NE(r, kNoRegisterPair);
return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfFRegIds + kNumberOfDRegIds));
}
private:
bool IsValidManagedRegister() const {
return (0 <= id_) && (id_ < kNumberOfRegIds);
}
int RegId() const {
CHECK(!IsNoRegister());
return id_;
}
int AllocId() const {
CHECK(IsValidManagedRegister() && !IsOverlappingDRegister() && !IsRegisterPair());
CHECK_LT(id_, kNumberOfAllocIds);
return id_;
}
int AllocIdLow() const;
int AllocIdHigh() const;
friend class ManagedRegister;
explicit MipsManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
static MipsManagedRegister FromRegId(int reg_id) {
MipsManagedRegister reg(reg_id);
CHECK(reg.IsValidManagedRegister());
return reg;
}
};
std::ostream& operator<<(std::ostream& os, const MipsManagedRegister& reg);
} // namespace mips
inline mips::MipsManagedRegister ManagedRegister::AsMips() const {
mips::MipsManagedRegister reg(id_);
CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
return reg;
}
} // namespace art
#endif // ART_COMPILER_UTILS_MIPS_MANAGED_REGISTER_MIPS_H_