100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee/*
200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee * Copyright (C) 2014 The Android Open Source Project
300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee * Licensed under the Apache License, Version 2.0 (the "License");
500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee * you may not use this file except in compliance with the License.
600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee * You may obtain a copy of the License at
700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *      http://www.apache.org/licenses/LICENSE-2.0
900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
1000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee * Unless required by applicable law or agreed to in writing, software
1100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee * distributed under the License is distributed on an "AS IS" BASIS,
1200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee * See the License for the specific language governing permissions and
1400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee * limitations under the License.
1500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee */
1600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
1700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee#ifndef ART_COMPILER_DEX_REG_STORAGE_H_
1800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee#define ART_COMPILER_DEX_REG_STORAGE_H_
1900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
20836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko#include "base/logging.h"
216a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers#include "base/value_object.h"
22ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe#include "compiler_enums.h"  // For WideKind
2300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
2400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbeenamespace art {
2500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
2600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee/*
27091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * 16-bit representation of the physical register container holding a Dalvik value.
28d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee * The encoding allows up to 64 physical elements per storage class, and supports eight
29091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * register container shapes.
3000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
31d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee * [V] [HHHHH] [SSS] [F] [LLLLLL]
3200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
33d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee * [LLLLLL]
34091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *  Physical register number for the low or solo register.
35d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee *    0..63
3600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
37091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * [F]
38091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *  Describes type of the [LLLLL] register.
39091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    0: Core
40091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    1: Floating point
4100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
42091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * [SSS]
43091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *  Shape of the register container.
44091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    000: Invalid
45091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    001: 32-bit solo register
46091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    010: 64-bit solo register
47091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    011: 64-bit pair consisting of two 32-bit solo registers
48091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    100: 128-bit solo register
49091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    101: 256-bit solo register
50091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    110: 512-bit solo register
51091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    111: 1024-bit solo register
5200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
53091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * [HHHHH]
54091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *  Physical register number of the high register (valid only for register pair).
55091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    0..31
5600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
57091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * [V]
58091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    0 -> Invalid
59091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    1 -> Valid
60091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *
61091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * Note that in all non-invalid cases, we can determine if the storage is floating point
62d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee * by testing bit 7.  Note also that a register pair is effectively limited to a pair of
63d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee * physical register numbers in the 0..31 range.
64091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *
65091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * On some target architectures, the same underlying physical register container can be given
66091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * different views.  For example, Arm's 32-bit single-precision floating point registers
67091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * s2 and s3 map to the low and high halves of double-precision d1.  Similarly, X86's xmm3
68091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * vector register can be viewed as 32-bit, 64-bit, 128-bit, etc.  In these cases the use of
69091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * one view will affect the other views.  The RegStorage class does not concern itself
70091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * with potential aliasing.  That will be done using the associated RegisterInfo struct.
71091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * Distinct RegStorage elements should be created for each view of a physical register
72091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * container.  The management of the aliased physical elements will be handled via RegisterInfo
73091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * records.
7400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee */
7500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
766a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersclass RegStorage : public ValueObject {
7700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee public:
7800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  enum RegStorageKind {
79091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    kValidMask     = 0x8000,
80091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    kValid         = 0x8000,
81091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    kInvalid       = 0x0000,
82d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    kShapeMask     = 0x0380,
83d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k32BitSolo     = 0x0080,
84d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k64BitSolo     = 0x0100,
85d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k64BitPair     = 0x0180,
86d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k128BitSolo    = 0x0200,
87d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k256BitSolo    = 0x0280,
88d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k512BitSolo    = 0x0300,
89d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k1024BitSolo   = 0x0380,
90d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k64BitMask     = 0x0300,
91d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k64Bits        = 0x0100,
92d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    kShapeTypeMask = 0x03c0,
93d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    kFloatingPoint = 0x0040,
94091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    kCoreRegister  = 0x0000,
9500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  };
9600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
97d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  static const uint16_t kRegValMask  = 0x03ff;     // Num, type and shape.
98d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  static const uint16_t kRegTypeMask = 0x007f;     // Num and type.
99d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  static const uint16_t kRegNumMask  = 0x003f;     // Num only.
100d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  static const uint16_t kHighRegNumMask = 0x001f;  // 0..31 for high reg
101091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  static const uint16_t kMaxRegs     = kRegValMask + 1;
102d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  // TODO: deprecate use of kInvalidRegVal and speed up GetReg().  Rely on valid bit instead.
103d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  static const uint16_t kInvalidRegVal = 0x03ff;
104d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  static const uint16_t kHighRegShift = 10;
105d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  static const uint16_t kHighRegMask = (kHighRegNumMask << kHighRegShift);
10600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
107091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Reg is [F][LLLLL], will override any existing shape and use rs_kind.
108836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr RegStorage(RegStorageKind rs_kind, int reg)
109836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko      : reg_(
110836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko          DCHECK_CONSTEXPR(rs_kind != k64BitPair, , 0u)
111836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko          DCHECK_CONSTEXPR((rs_kind & ~kShapeMask) == 0, , 0u)
112836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko          kValid | rs_kind | (reg & kRegTypeMask)) {
113836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  }
114836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr RegStorage(RegStorageKind rs_kind, int low_reg, int high_reg)
115836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko      : reg_(
1166a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers          DCHECK_CONSTEXPR(rs_kind == k64BitPair, << static_cast<int>(rs_kind), 0u)
117836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko          DCHECK_CONSTEXPR((low_reg & kFloatingPoint) == (high_reg & kFloatingPoint),
118836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko                           << low_reg << ", " << high_reg, 0u)
119836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko          DCHECK_CONSTEXPR((high_reg & kRegNumMask) <= kHighRegNumMask,
120836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko                           << "High reg must be in 0..31: " << high_reg, false)
121836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko          kValid | rs_kind | ((high_reg & kHighRegNumMask) << kHighRegShift) |
122836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko                  (low_reg & kRegTypeMask)) {
12300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
124091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  constexpr explicit RegStorage(uint16_t val) : reg_(val) {}
12500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  RegStorage() : reg_(kInvalid) {}
12600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
127b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  // We do not provide a general operator overload for equality of reg storage, as this is
128b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  // dangerous in the case of architectures with multiple views, and the naming ExactEquals
129b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  // expresses the exact match expressed here. It is more likely that a comparison between the views
130b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  // is intended in most cases. Such code can be found in, for example, Mir2Lir::IsSameReg.
131b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  //
132b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  // If you know what you are doing, include reg_storage_eq.h, which defines == and != for brevity.
133b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee
134b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  bool ExactlyEquals(const RegStorage& rhs) const {
1352700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return (reg_ == rhs.GetRawBits());
1362700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
1372700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
138b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  bool NotExactlyEquals(const RegStorage& rhs) const {
1392700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return (reg_ != rhs.GetRawBits());
1402700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
1412700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
142836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool Valid() const {
143091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return ((reg_ & kValidMask) == kValid);
14400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
14500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
146836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool Is32Bit() const {
147091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return ((reg_ & kShapeMask) == k32BitSolo);
14800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
14900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
150836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool Is64Bit() const {
151091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return ((reg_ & k64BitMask) == k64Bits);
15200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
15300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
154ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe  constexpr WideKind GetWideKind() const {
155ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe    return Is64Bit() ? kWide : kNotWide;
156ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe  }
157ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe
158836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool Is64BitSolo() const {
1599ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    return ((reg_ & kShapeMask) == k64BitSolo);
1609ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  }
1619ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko
162836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool IsPair() const {
163091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return ((reg_ & kShapeMask) == k64BitPair);
16400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
16500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
166836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool IsFloat() const {
167836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko    return
168836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko        DCHECK_CONSTEXPR(Valid(), , false)
169836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko        ((reg_ & kFloatingPoint) == kFloatingPoint);
17000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
17100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
172836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool IsDouble() const {
173836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko    return
174836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko        DCHECK_CONSTEXPR(Valid(), , false)
175836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko        (reg_ & (kFloatingPoint | k64BitMask)) == (kFloatingPoint | k64Bits);
176091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
177091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
178836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool IsSingle() const {
179836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko    return
180836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko        DCHECK_CONSTEXPR(Valid(), , false)
181836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko        (reg_ & (kFloatingPoint | k64BitMask)) == kFloatingPoint;
182091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
183091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
184836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr bool IsFloat(uint16_t reg) {
185091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return ((reg & kFloatingPoint) == kFloatingPoint);
186091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
187091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
188836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr bool IsDouble(uint16_t reg) {
189091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return (reg & (kFloatingPoint | k64BitMask)) == (kFloatingPoint | k64Bits);
190091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
191091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
192836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr bool IsSingle(uint16_t reg) {
193091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return (reg & (kFloatingPoint | k64BitMask)) == kFloatingPoint;
19400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
19500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
19663999683329612292d534e6be09dbde9480f1250Serban Constantinescu  static constexpr bool Is32Bit(uint16_t reg) {
19763999683329612292d534e6be09dbde9480f1250Serban Constantinescu    return ((reg & kShapeMask) == k32BitSolo);
19863999683329612292d534e6be09dbde9480f1250Serban Constantinescu  }
19963999683329612292d534e6be09dbde9480f1250Serban Constantinescu
20063999683329612292d534e6be09dbde9480f1250Serban Constantinescu  static constexpr bool Is64Bit(uint16_t reg) {
20163999683329612292d534e6be09dbde9480f1250Serban Constantinescu    return ((reg & k64BitMask) == k64Bits);
20263999683329612292d534e6be09dbde9480f1250Serban Constantinescu  }
20363999683329612292d534e6be09dbde9480f1250Serban Constantinescu
20463999683329612292d534e6be09dbde9480f1250Serban Constantinescu  static constexpr bool Is64BitSolo(uint16_t reg) {
20563999683329612292d534e6be09dbde9480f1250Serban Constantinescu    return ((reg & kShapeMask) == k64BitSolo);
20663999683329612292d534e6be09dbde9480f1250Serban Constantinescu  }
20763999683329612292d534e6be09dbde9480f1250Serban Constantinescu
20800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  // Used to retrieve either the low register of a pair, or the only register.
20900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  int GetReg() const {
210091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    DCHECK(!IsPair()) << "reg_ = 0x" << std::hex << reg_;
2112700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return Valid() ? (reg_ & kRegValMask) : kInvalidRegVal;
21200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
21300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
214091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Sets shape, type and num of solo.
21500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  void SetReg(int reg) {
2162700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(Valid());
217091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    DCHECK(!IsPair());
2182700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    reg_ = (reg_ & ~kRegValMask) | reg;
2192700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
2202700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
221091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Set the reg number and type only, target remain 64-bit pair.
2222700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  void SetLowReg(int reg) {
2232700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(IsPair());
224091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    reg_ = (reg_ & ~kRegTypeMask) | (reg & kRegTypeMask);
2252700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
2262700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
227091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Retrieve the least significant register of a pair and return as 32-bit solo.
2282700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  int GetLowReg() const {
2292700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(IsPair());
230091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return ((reg_ & kRegTypeMask) | k32BitSolo);
2312700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
2322700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
2332700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  // Create a stand-alone RegStorage from the low reg of a pair.
2342700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  RegStorage GetLow() const {
2352700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(IsPair());
236091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return RegStorage(k32BitSolo, reg_ & kRegTypeMask);
23700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
23800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
23900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  // Retrieve the most significant register of a pair.
24000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  int GetHighReg() const {
24100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    DCHECK(IsPair());
242d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    return k32BitSolo | ((reg_ & kHighRegMask) >> kHighRegShift) | (reg_ & kFloatingPoint);
24300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
24400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
2452700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  // Create a stand-alone RegStorage from the high reg of a pair.
2462700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  RegStorage GetHigh() const {
2472700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(IsPair());
248091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return RegStorage(kValid | GetHighReg());
2492700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
2502700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
25100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  void SetHighReg(int reg) {
25200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    DCHECK(IsPair());
253d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    reg_ = (reg_ & ~kHighRegMask) | ((reg & kHighRegNumMask) << kHighRegShift);
254091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
255091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
256091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Return the register number of low or solo.
257836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr int GetRegNum() const {
258091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return reg_ & kRegNumMask;
259091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
260091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
261091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Is register number in 0..7?
262836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool Low8() const {
263091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return GetRegNum() < 8;
264091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
265091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
266091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Is register number in 0..3?
267836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool Low4() const {
268091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return GetRegNum() < 4;
26900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
27000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
2712700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  // Combine 2 32-bit solo regs into a pair.
2722700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  static RegStorage MakeRegPair(RegStorage low, RegStorage high) {
2732700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(!low.IsPair());
2742700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(low.Is32Bit());
2752700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(!high.IsPair());
2762700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(high.Is32Bit());
2772700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return RegStorage(k64BitPair, low.GetReg(), high.GetReg());
2782700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
2792700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
280836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr bool SameRegType(RegStorage reg1, RegStorage reg2) {
28163999683329612292d534e6be09dbde9480f1250Serban Constantinescu    return ((reg1.reg_ & kShapeTypeMask) == (reg2.reg_ & kShapeTypeMask));
282091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
283091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
284836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr bool SameRegType(int reg1, int reg2) {
28563999683329612292d534e6be09dbde9480f1250Serban Constantinescu    return ((reg1 & kShapeTypeMask) == (reg2 & kShapeTypeMask));
286091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
287091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
2882700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  // Create a 32-bit solo.
2892700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  static RegStorage Solo32(int reg_num) {
290091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return RegStorage(k32BitSolo, reg_num & kRegTypeMask);
291091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
292091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
293091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Create a floating point 32-bit solo.
294836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr RegStorage FloatSolo32(int reg_num) {
295091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return RegStorage(k32BitSolo, (reg_num & kRegNumMask) | kFloatingPoint);
2962700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
2972700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
298fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // Create a 128-bit solo.
299836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr RegStorage Solo128(int reg_num) {
300fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    return RegStorage(k128BitSolo, reg_num & kRegTypeMask);
301fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
302fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
3032700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  // Create a 64-bit solo.
304836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr RegStorage Solo64(int reg_num) {
305091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return RegStorage(k64BitSolo, reg_num & kRegTypeMask);
306091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
307091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
308091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Create a floating point 64-bit solo.
309091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  static RegStorage FloatSolo64(int reg_num) {
310091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return RegStorage(k64BitSolo, (reg_num & kRegNumMask) | kFloatingPoint);
3112700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
3122700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
313836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr RegStorage InvalidReg() {
3142700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return RegStorage(kInvalid);
3152700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
3162700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
317836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr uint16_t RegNum(int raw_reg_bits) {
318091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return raw_reg_bits & kRegNumMask;
319091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
320091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
321836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr int GetRawBits() const {
32200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    return reg_;
32300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
32400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
325836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  size_t StorageSize() const {
326091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    switch (reg_ & kShapeMask) {
327091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case kInvalid: return 0;
328091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case k32BitSolo: return 4;
329091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case k64BitSolo: return 8;
330091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case k64BitPair: return 8;  // Is this useful?  Might want to disallow taking size of pair.
331091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case k128BitSolo: return 16;
332091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case k256BitSolo: return 32;
333091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case k512BitSolo: return 64;
334091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case k1024BitSolo: return 128;
3356a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers      default: LOG(FATAL) << "Unexpected shape"; UNREACHABLE();
336091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    }
337091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
338091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
33900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee private:
34000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  uint16_t reg_;
34100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee};
342b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogersstatic inline std::ostream& operator<<(std::ostream& o, const RegStorage& rhs) {
343b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers  return o << rhs.GetRawBits();  // TODO: better output.
344b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers}
34500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
34600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee}  // namespace art
34700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
34800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee#endif  // ART_COMPILER_DEX_REG_STORAGE_H_
349