12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
16b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
17166db04e259ca51838c311891598664deeed85adIan Rogers#ifndef ART_COMPILER_UTILS_ARM_MANAGED_REGISTER_ARM_H_
18166db04e259ca51838c311891598664deeed85adIan Rogers#define ART_COMPILER_UTILS_ARM_MANAGED_REGISTER_ARM_H_
19b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
2057943810cfc789da890d73621741729da5feaaf8Andreas Gampe#include <android-base/logging.h>
2157943810cfc789da890d73621741729da5feaaf8Andreas Gampe
220f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes#include "constants_arm.h"
234fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#include "debug/dwarf/register.h"
24166db04e259ca51838c311891598664deeed85adIan Rogers#include "utils/managed_register.h"
25b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
2612e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov// TODO(VIXL): Make VIXL compile with -Wshadow.
2712e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov#pragma GCC diagnostic push
2812e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov#pragma GCC diagnostic ignored "-Wshadow"
2912e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov#include "aarch32/macro-assembler-aarch32.h"
3012e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov#pragma GCC diagnostic pop
3112e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov
32b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersnamespace art {
332c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogersnamespace arm {
34b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
35b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Values for register pairs.
36b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersenum RegisterPair {
37b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  R0_R1 = 0,
38b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  R2_R3 = 1,
39b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  R4_R5 = 2,
40b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  R6_R7 = 3,
417a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers  R1_R2 = 4,  // Dalvik style passing
427a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers  kNumberOfRegisterPairs = 5,
43b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  kNoRegisterPair = -1,
44b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers};
45b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
46b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstd::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
47b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
48b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersconst int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
49b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersconst int kNumberOfCoreAllocIds = kNumberOfCoreRegisters;
50b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
51b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersconst int kNumberOfSRegIds = kNumberOfSRegisters;
52b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersconst int kNumberOfSAllocIds = kNumberOfSRegisters;
53b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
54b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersconst int kNumberOfDRegIds = kNumberOfDRegisters;
55b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersconst int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters;
56b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersconst int kNumberOfDAllocIds = kNumberOfDRegIds - kNumberOfOverlappingDRegIds;
57b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
58b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersconst int kNumberOfPairRegIds = kNumberOfRegisterPairs;
59b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
60b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersconst int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfSRegIds +
61b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    kNumberOfDRegIds + kNumberOfPairRegIds;
62b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersconst int kNumberOfAllocIds =
63b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    kNumberOfCoreAllocIds + kNumberOfSAllocIds + kNumberOfDAllocIds;
64b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
65b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Register ids map:
66b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//   [0..R[  core registers (enum Register)
67b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//   [R..S[  single precision VFP registers (enum SRegister)
68b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//   [S..D[  double precision VFP registers (enum DRegister)
69b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//   [D..P[  core register pairs (enum RegisterPair)
70b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// where
71b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//   R = kNumberOfCoreRegIds
72b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//   S = R + kNumberOfSRegIds
73b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//   D = S + kNumberOfDRegIds
74b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//   P = D + kNumberOfRegisterPairs
75b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
76b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Allocation ids map:
77b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//   [0..R[  core registers (enum Register)
78b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//   [R..S[  single precision VFP registers (enum SRegister)
79b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//   [S..N[  non-overlapping double precision VFP registers (16-31 in enum
80b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//           DRegister, VFPv3-D32 only)
81b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// where
82b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//   R = kNumberOfCoreAllocIds
83b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//   S = R + kNumberOfSAllocIds
84b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers//   N = S + kNumberOfDAllocIds
85b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
86b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
87b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// An instance of class 'ManagedRegister' represents a single ARM register or a
88b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// pair of core ARM registers (enum RegisterPair). A single register is either a
89b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// core register (enum Register), a VFP single precision register
90b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// (enum SRegister), or a VFP double precision register (enum DRegister).
91b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// 'ManagedRegister::NoRegister()' returns an invalid ManagedRegister.
92b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// There is a one-to-one mapping between ManagedRegister and register id.
932c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogersclass ArmManagedRegister : public ManagedRegister {
94b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public:
953224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr Register AsCoreRegister() const {
96b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsCoreRegister());
97b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return static_cast<Register>(id_);
98b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
99b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
10012e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov  vixl::aarch32::Register AsVIXLRegister() const {
10112e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov    CHECK(IsCoreRegister());
10212e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov    return vixl::aarch32::Register(id_);
10312e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov  }
10412e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov
1053224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr SRegister AsSRegister() const {
106b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsSRegister());
107b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return static_cast<SRegister>(id_ - kNumberOfCoreRegIds);
108b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
109b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
11012e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov  vixl::aarch32::SRegister AsVIXLSRegister() const {
11112e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov    CHECK(IsSRegister());
11212e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov    return vixl::aarch32::SRegister(id_ - kNumberOfCoreRegIds);
11312e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov  }
11412e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov
1153224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr DRegister AsDRegister() const {
116b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsDRegister());
117b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfSRegIds);
118b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
119b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
12012e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov  vixl::aarch32::DRegister AsVIXLDRegister() const {
12112e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov    CHECK(IsDRegister());
12212e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov    return vixl::aarch32::DRegister(id_ - kNumberOfCoreRegIds - kNumberOfSRegIds);
12312e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov  }
12412e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov
1253224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr SRegister AsOverlappingDRegisterLow() const {
126b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsOverlappingDRegister());
127b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    DRegister d_reg = AsDRegister();
128b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return static_cast<SRegister>(d_reg * 2);
129b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
130b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
1313224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr SRegister AsOverlappingDRegisterHigh() const {
132b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsOverlappingDRegister());
133b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    DRegister d_reg = AsDRegister();
134b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return static_cast<SRegister>(d_reg * 2 + 1);
135b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
136b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
1373224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr RegisterPair AsRegisterPair() const {
138b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsRegisterPair());
139b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    Register reg_low = AsRegisterPairLow();
1407a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers    if (reg_low == R1) {
1417a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers      return R1_R2;
1427a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers    } else {
1437a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers      return static_cast<RegisterPair>(reg_low / 2);
1447a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers    }
145b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
146b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
1473224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr Register AsRegisterPairLow() const {
148b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsRegisterPair());
149b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    // Appropriate mapping of register ids allows to use AllocIdLow().
150b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return FromRegId(AllocIdLow()).AsCoreRegister();
151b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
152b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
15312e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov  vixl::aarch32::Register AsVIXLRegisterPairLow() const {
15412e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov    return vixl::aarch32::Register(AsRegisterPairLow());
15512e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov  }
15612e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov
1573224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr Register AsRegisterPairHigh() const {
158b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsRegisterPair());
159b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    // Appropriate mapping of register ids allows to use AllocIdHigh().
160b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return FromRegId(AllocIdHigh()).AsCoreRegister();
161b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
162b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
16312e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov  vixl::aarch32::Register AsVIXLRegisterPairHigh() const {
16412e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov    return vixl::aarch32::Register(AsRegisterPairHigh());
16512e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov  }
16612e097c84cef710fa4f254b1811ff70b876e9e9aArtem Serov
1673224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr bool IsCoreRegister() const {
168b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsValidManagedRegister());
169b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
170b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
171b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
1723224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr bool IsSRegister() const {
173b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsValidManagedRegister());
174b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    const int test = id_ - kNumberOfCoreRegIds;
175b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return (0 <= test) && (test < kNumberOfSRegIds);
176b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
177b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
1783224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr bool IsDRegister() const {
179b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsValidManagedRegister());
180b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
181b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return (0 <= test) && (test < kNumberOfDRegIds);
182b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
183b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
184b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Returns true if this DRegister overlaps SRegisters.
1853224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr bool IsOverlappingDRegister() const {
186b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsValidManagedRegister());
187b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
188b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
189b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
190b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
1913224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr bool IsRegisterPair() const {
192b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsValidManagedRegister());
193b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    const int test =
194b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers        id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds + kNumberOfDRegIds);
195b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return (0 <= test) && (test < kNumberOfPairRegIds);
196b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
197b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
1983224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr bool IsSameType(ArmManagedRegister test) const {
199b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsValidManagedRegister() && test.IsValidManagedRegister());
200b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return
201b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers      (IsCoreRegister() && test.IsCoreRegister()) ||
202b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers      (IsSRegister() && test.IsSRegister()) ||
203b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers      (IsDRegister() && test.IsDRegister()) ||
204b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers      (IsRegisterPair() && test.IsRegisterPair());
205b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
206b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
207b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
208b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Returns true if the two managed-registers ('this' and 'other') overlap.
209b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Either managed-register may be the NoRegister. If both are the NoRegister
210b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // then false is returned.
2112c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  bool Overlaps(const ArmManagedRegister& other) const;
212b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
213b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  void Print(std::ostream& os) const;
214b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
2153224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  static constexpr ArmManagedRegister FromCoreRegister(Register r) {
216b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK_NE(r, kNoRegister);
217b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return FromRegId(r);
218b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
219b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
2203224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  static constexpr ArmManagedRegister FromSRegister(SRegister r) {
221b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK_NE(r, kNoSRegister);
222b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return FromRegId(r + kNumberOfCoreRegIds);
223b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
224b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
2253224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  static constexpr ArmManagedRegister FromDRegister(DRegister r) {
226b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK_NE(r, kNoDRegister);
227b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfSRegIds));
228b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
229b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
2303224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  static constexpr ArmManagedRegister FromRegisterPair(RegisterPair r) {
231b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK_NE(r, kNoRegisterPair);
232b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return FromRegId(r + (kNumberOfCoreRegIds +
233b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers                          kNumberOfSRegIds + kNumberOfDRegIds));
234b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
235b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
236b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Return a RegisterPair consisting of Register r_low and r_low + 1.
2373224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  static constexpr ArmManagedRegister FromCoreRegisterPair(Register r_low) {
2387a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers    if (r_low != R1) {  // not the dalvik special case
2397a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers      CHECK_NE(r_low, kNoRegister);
2407a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers      CHECK_EQ(0, (r_low % 2));
2417a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers      const int r = r_low / 2;
2427a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers      CHECK_LT(r, kNumberOfPairRegIds);
2437a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers      return FromRegisterPair(static_cast<RegisterPair>(r));
2447a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers    } else {
2457a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers      return FromRegisterPair(R1_R2);
2467a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers    }
247b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
248b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
249b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Return a DRegister overlapping SRegister r_low and r_low + 1.
2503224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  static constexpr ArmManagedRegister FromSRegisterPair(SRegister r_low) {
251b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK_NE(r_low, kNoSRegister);
252b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK_EQ(0, (r_low % 2));
253b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    const int r = r_low / 2;
254b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK_LT(r, kNumberOfOverlappingDRegIds);
255b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return FromDRegister(static_cast<DRegister>(r));
256b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
257b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
258b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers private:
2593224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  constexpr bool IsValidManagedRegister() const {
260b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return (0 <= id_) && (id_ < kNumberOfRegIds);
261b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
262b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
263b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  int RegId() const {
264b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(!IsNoRegister());
265b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return id_;
266b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
267b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
268b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  int AllocId() const {
269b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(IsValidManagedRegister() &&
270b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers           !IsOverlappingDRegister() && !IsRegisterPair());
271b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    int r = id_;
272b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    if ((kNumberOfDAllocIds > 0) && IsDRegister()) {  // VFPv3-D32 only.
273b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers      r -= kNumberOfOverlappingDRegIds;
274b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    }
275b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK_LT(r, kNumberOfAllocIds);
276b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return r;
277b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
278b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
279b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  int AllocIdLow() const;
280b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  int AllocIdHigh() const;
281b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
2822c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  friend class ManagedRegister;
2832c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
2843224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  explicit constexpr ArmManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
2852c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
2863224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Marko  static constexpr ArmManagedRegister FromRegId(int reg_id) {
2872c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers    ArmManagedRegister reg(reg_id);
288b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    CHECK(reg.IsValidManagedRegister());
289b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return reg;
290b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
291b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers};
292b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
2932c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogersstd::ostream& operator<<(std::ostream& os, const ArmManagedRegister& reg);
2942c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
2952c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers}  // namespace arm
2962c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
2973224838dfe9c95330ad963286f2c47e9546d3b5cVladimir Markoconstexpr inline arm::ArmManagedRegister ManagedRegister::AsArm() const {
2982c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  arm::ArmManagedRegister reg(id_);
2992c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
3002c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  return reg;
3012c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers}
302b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
303b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}  // namespace art
304b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
305166db04e259ca51838c311891598664deeed85adIan Rogers#endif  // ART_COMPILER_UTILS_ARM_MANAGED_REGISTER_ARM_H_
306