summaryrefslogtreecommitdiffstats
path: root/runtime/oat/utils/arm/managed_register_arm.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/oat/utils/arm/managed_register_arm.h')
-rw-r--r--runtime/oat/utils/arm/managed_register_arm.h274
1 files changed, 274 insertions, 0 deletions
diff --git a/runtime/oat/utils/arm/managed_register_arm.h b/runtime/oat/utils/arm/managed_register_arm.h
new file mode 100644
index 0000000..b069f6d
--- /dev/null
+++ b/runtime/oat/utils/arm/managed_register_arm.h
@@ -0,0 +1,274 @@
+/*
+ * 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_SRC_OAT_UTILS_ARM_MANAGED_REGISTER_ARM_H_
+#define ART_SRC_OAT_UTILS_ARM_MANAGED_REGISTER_ARM_H_
+
+#include "base/logging.h"
+#include "constants_arm.h"
+#include "oat/utils/managed_register.h"
+
+namespace art {
+namespace arm {
+
+// Values for register pairs.
+enum RegisterPair {
+ R0_R1 = 0,
+ R2_R3 = 1,
+ R4_R5 = 2,
+ R6_R7 = 3,
+ R1_R2 = 4, // Dalvik style passing
+ kNumberOfRegisterPairs = 5,
+ kNoRegisterPair = -1,
+};
+
+std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
+
+const int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
+const int kNumberOfCoreAllocIds = kNumberOfCoreRegisters;
+
+const int kNumberOfSRegIds = kNumberOfSRegisters;
+const int kNumberOfSAllocIds = kNumberOfSRegisters;
+
+const int kNumberOfDRegIds = kNumberOfDRegisters;
+const int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters;
+const int kNumberOfDAllocIds = kNumberOfDRegIds - kNumberOfOverlappingDRegIds;
+
+const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
+
+const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfSRegIds +
+ kNumberOfDRegIds + kNumberOfPairRegIds;
+const int kNumberOfAllocIds =
+ kNumberOfCoreAllocIds + kNumberOfSAllocIds + kNumberOfDAllocIds;
+
+// Register ids map:
+// [0..R[ core registers (enum Register)
+// [R..S[ single precision VFP registers (enum SRegister)
+// [S..D[ double precision VFP registers (enum DRegister)
+// [D..P[ core register pairs (enum RegisterPair)
+// where
+// R = kNumberOfCoreRegIds
+// S = R + kNumberOfSRegIds
+// D = S + kNumberOfDRegIds
+// P = D + kNumberOfRegisterPairs
+
+// Allocation ids map:
+// [0..R[ core registers (enum Register)
+// [R..S[ single precision VFP registers (enum SRegister)
+// [S..N[ non-overlapping double precision VFP registers (16-31 in enum
+// DRegister, VFPv3-D32 only)
+// where
+// R = kNumberOfCoreAllocIds
+// S = R + kNumberOfSAllocIds
+// N = S + kNumberOfDAllocIds
+
+
+// An instance of class 'ManagedRegister' represents a single ARM register or a
+// pair of core ARM registers (enum RegisterPair). A single register is either a
+// core register (enum Register), a VFP single precision register
+// (enum SRegister), or a VFP double precision register (enum DRegister).
+// 'ManagedRegister::NoRegister()' returns an invalid ManagedRegister.
+// There is a one-to-one mapping between ManagedRegister and register id.
+class ArmManagedRegister : public ManagedRegister {
+ public:
+ Register AsCoreRegister() const {
+ CHECK(IsCoreRegister());
+ return static_cast<Register>(id_);
+ }
+
+ SRegister AsSRegister() const {
+ CHECK(IsSRegister());
+ return static_cast<SRegister>(id_ - kNumberOfCoreRegIds);
+ }
+
+ DRegister AsDRegister() const {
+ CHECK(IsDRegister());
+ return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfSRegIds);
+ }
+
+ SRegister AsOverlappingDRegisterLow() const {
+ CHECK(IsOverlappingDRegister());
+ DRegister d_reg = AsDRegister();
+ return static_cast<SRegister>(d_reg * 2);
+ }
+
+ SRegister AsOverlappingDRegisterHigh() const {
+ CHECK(IsOverlappingDRegister());
+ DRegister d_reg = AsDRegister();
+ return static_cast<SRegister>(d_reg * 2 + 1);
+ }
+
+ RegisterPair AsRegisterPair() const {
+ CHECK(IsRegisterPair());
+ Register reg_low = AsRegisterPairLow();
+ if (reg_low == R1) {
+ return R1_R2;
+ } else {
+ return static_cast<RegisterPair>(reg_low / 2);
+ }
+ }
+
+ 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 IsSRegister() const {
+ CHECK(IsValidManagedRegister());
+ const int test = id_ - kNumberOfCoreRegIds;
+ return (0 <= test) && (test < kNumberOfSRegIds);
+ }
+
+ bool IsDRegister() const {
+ CHECK(IsValidManagedRegister());
+ const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
+ return (0 <= test) && (test < kNumberOfDRegIds);
+ }
+
+ // Returns true if this DRegister overlaps SRegisters.
+ bool IsOverlappingDRegister() const {
+ CHECK(IsValidManagedRegister());
+ const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
+ return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
+ }
+
+ bool IsRegisterPair() const {
+ CHECK(IsValidManagedRegister());
+ const int test =
+ id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds + kNumberOfDRegIds);
+ return (0 <= test) && (test < kNumberOfPairRegIds);
+ }
+
+ bool IsSameType(ArmManagedRegister test) const {
+ CHECK(IsValidManagedRegister() && test.IsValidManagedRegister());
+ return
+ (IsCoreRegister() && test.IsCoreRegister()) ||
+ (IsSRegister() && test.IsSRegister()) ||
+ (IsDRegister() && test.IsDRegister()) ||
+ (IsRegisterPair() && test.IsRegisterPair());
+ }
+
+
+ // 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 ArmManagedRegister& other) const;
+
+ void Print(std::ostream& os) const;
+
+ static ArmManagedRegister FromCoreRegister(Register r) {
+ CHECK_NE(r, kNoRegister);
+ return FromRegId(r);
+ }
+
+ static ArmManagedRegister FromSRegister(SRegister r) {
+ CHECK_NE(r, kNoSRegister);
+ return FromRegId(r + kNumberOfCoreRegIds);
+ }
+
+ static ArmManagedRegister FromDRegister(DRegister r) {
+ CHECK_NE(r, kNoDRegister);
+ return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfSRegIds));
+ }
+
+ static ArmManagedRegister FromRegisterPair(RegisterPair r) {
+ CHECK_NE(r, kNoRegisterPair);
+ return FromRegId(r + (kNumberOfCoreRegIds +
+ kNumberOfSRegIds + kNumberOfDRegIds));
+ }
+
+ // Return a RegisterPair consisting of Register r_low and r_low + 1.
+ static ArmManagedRegister FromCoreRegisterPair(Register r_low) {
+ if (r_low != R1) { // not the dalvik special case
+ CHECK_NE(r_low, kNoRegister);
+ CHECK_EQ(0, (r_low % 2));
+ const int r = r_low / 2;
+ CHECK_LT(r, kNumberOfPairRegIds);
+ return FromRegisterPair(static_cast<RegisterPair>(r));
+ } else {
+ return FromRegisterPair(R1_R2);
+ }
+ }
+
+ // Return a DRegister overlapping SRegister r_low and r_low + 1.
+ static ArmManagedRegister FromSRegisterPair(SRegister r_low) {
+ CHECK_NE(r_low, kNoSRegister);
+ CHECK_EQ(0, (r_low % 2));
+ const int r = r_low / 2;
+ CHECK_LT(r, kNumberOfOverlappingDRegIds);
+ return FromDRegister(static_cast<DRegister>(r));
+ }
+
+ private:
+ bool IsValidManagedRegister() const {
+ return (0 <= id_) && (id_ < kNumberOfRegIds);
+ }
+
+ int RegId() const {
+ CHECK(!IsNoRegister());
+ return id_;
+ }
+
+ int AllocId() const {
+ CHECK(IsValidManagedRegister() &&
+ !IsOverlappingDRegister() && !IsRegisterPair());
+ int r = id_;
+ if ((kNumberOfDAllocIds > 0) && IsDRegister()) { // VFPv3-D32 only.
+ r -= kNumberOfOverlappingDRegIds;
+ }
+ CHECK_LT(r, kNumberOfAllocIds);
+ return r;
+ }
+
+ int AllocIdLow() const;
+ int AllocIdHigh() const;
+
+ friend class ManagedRegister;
+
+ explicit ArmManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
+
+ static ArmManagedRegister FromRegId(int reg_id) {
+ ArmManagedRegister reg(reg_id);
+ CHECK(reg.IsValidManagedRegister());
+ return reg;
+ }
+};
+
+std::ostream& operator<<(std::ostream& os, const ArmManagedRegister& reg);
+
+} // namespace arm
+
+inline arm::ArmManagedRegister ManagedRegister::AsArm() const {
+ arm::ArmManagedRegister reg(id_);
+ CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
+ return reg;
+}
+
+} // namespace art
+
+#endif // ART_SRC_OAT_UTILS_ARM_MANAGED_REGISTER_ARM_H_