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"
21ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe#include "compiler_enums.h"  // For WideKind
2200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
2300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbeenamespace art {
2400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
2500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee/*
26091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * 16-bit representation of the physical register container holding a Dalvik value.
27d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee * The encoding allows up to 64 physical elements per storage class, and supports eight
28091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * register container shapes.
2900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
30d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee * [V] [HHHHH] [SSS] [F] [LLLLLL]
3100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
32d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee * [LLLLLL]
33091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *  Physical register number for the low or solo register.
34d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee *    0..63
3500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
36091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * [F]
37091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *  Describes type of the [LLLLL] register.
38091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    0: Core
39091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    1: Floating point
4000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
41091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * [SSS]
42091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *  Shape of the register container.
43091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    000: Invalid
44091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    001: 32-bit solo register
45091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    010: 64-bit solo register
46091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    011: 64-bit pair consisting of two 32-bit solo registers
47091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    100: 128-bit solo register
48091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    101: 256-bit solo register
49091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    110: 512-bit solo register
50091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    111: 1024-bit solo register
5100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
52091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * [HHHHH]
53091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *  Physical register number of the high register (valid only for register pair).
54091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    0..31
5500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee *
56091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * [V]
57091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    0 -> Invalid
58091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *    1 -> Valid
59091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *
60091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * Note that in all non-invalid cases, we can determine if the storage is floating point
61d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee * by testing bit 7.  Note also that a register pair is effectively limited to a pair of
62d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee * physical register numbers in the 0..31 range.
63091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee *
64091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * On some target architectures, the same underlying physical register container can be given
65091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * different views.  For example, Arm's 32-bit single-precision floating point registers
66091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * s2 and s3 map to the low and high halves of double-precision d1.  Similarly, X86's xmm3
67091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * vector register can be viewed as 32-bit, 64-bit, 128-bit, etc.  In these cases the use of
68091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * one view will affect the other views.  The RegStorage class does not concern itself
69091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * with potential aliasing.  That will be done using the associated RegisterInfo struct.
70091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * Distinct RegStorage elements should be created for each view of a physical register
71091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * container.  The management of the aliased physical elements will be handled via RegisterInfo
72091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee * records.
7300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee */
7400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
7500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbeeclass RegStorage {
7600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee public:
7700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  enum RegStorageKind {
78091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    kValidMask     = 0x8000,
79091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    kValid         = 0x8000,
80091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    kInvalid       = 0x0000,
81d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    kShapeMask     = 0x0380,
82d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k32BitSolo     = 0x0080,
83d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k64BitSolo     = 0x0100,
84d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k64BitPair     = 0x0180,
85d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k128BitSolo    = 0x0200,
86d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k256BitSolo    = 0x0280,
87d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k512BitSolo    = 0x0300,
88d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k1024BitSolo   = 0x0380,
89d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k64BitMask     = 0x0300,
90d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    k64Bits        = 0x0100,
91d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    kShapeTypeMask = 0x03c0,
92d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    kFloatingPoint = 0x0040,
93091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    kCoreRegister  = 0x0000,
9400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  };
9500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
96d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  static const uint16_t kRegValMask  = 0x03ff;     // Num, type and shape.
97d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  static const uint16_t kRegTypeMask = 0x007f;     // Num and type.
98d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  static const uint16_t kRegNumMask  = 0x003f;     // Num only.
99d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  static const uint16_t kHighRegNumMask = 0x001f;  // 0..31 for high reg
100091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  static const uint16_t kMaxRegs     = kRegValMask + 1;
101d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  // TODO: deprecate use of kInvalidRegVal and speed up GetReg().  Rely on valid bit instead.
102d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  static const uint16_t kInvalidRegVal = 0x03ff;
103d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  static const uint16_t kHighRegShift = 10;
104d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee  static const uint16_t kHighRegMask = (kHighRegNumMask << kHighRegShift);
10500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
106091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Reg is [F][LLLLL], will override any existing shape and use rs_kind.
107836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr RegStorage(RegStorageKind rs_kind, int reg)
108836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko      : reg_(
109836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko          DCHECK_CONSTEXPR(rs_kind != k64BitPair, , 0u)
110836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko          DCHECK_CONSTEXPR((rs_kind & ~kShapeMask) == 0, , 0u)
111836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko          kValid | rs_kind | (reg & kRegTypeMask)) {
112836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  }
113836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr RegStorage(RegStorageKind rs_kind, int low_reg, int high_reg)
114836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko      : reg_(
115836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko          DCHECK_CONSTEXPR(rs_kind == k64BitPair, << rs_kind, 0u)
116836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko          DCHECK_CONSTEXPR((low_reg & kFloatingPoint) == (high_reg & kFloatingPoint),
117836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko                           << low_reg << ", " << high_reg, 0u)
118836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko          DCHECK_CONSTEXPR((high_reg & kRegNumMask) <= kHighRegNumMask,
119836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko                           << "High reg must be in 0..31: " << high_reg, false)
120836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko          kValid | rs_kind | ((high_reg & kHighRegNumMask) << kHighRegShift) |
121836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko                  (low_reg & kRegTypeMask)) {
12200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
123091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  constexpr explicit RegStorage(uint16_t val) : reg_(val) {}
12400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  RegStorage() : reg_(kInvalid) {}
12500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
126b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  // We do not provide a general operator overload for equality of reg storage, as this is
127b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  // dangerous in the case of architectures with multiple views, and the naming ExactEquals
128b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  // expresses the exact match expressed here. It is more likely that a comparison between the views
129b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  // is intended in most cases. Such code can be found in, for example, Mir2Lir::IsSameReg.
130b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  //
131b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  // If you know what you are doing, include reg_storage_eq.h, which defines == and != for brevity.
132b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee
133b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  bool ExactlyEquals(const RegStorage& rhs) const {
1342700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return (reg_ == rhs.GetRawBits());
1352700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
1362700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
137b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee  bool NotExactlyEquals(const RegStorage& rhs) const {
1382700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return (reg_ != rhs.GetRawBits());
1392700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
1402700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
141836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool Valid() const {
142091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return ((reg_ & kValidMask) == kValid);
14300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
14400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
145836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool Is32Bit() const {
146091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return ((reg_ & kShapeMask) == k32BitSolo);
14700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
14800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
149836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool Is64Bit() const {
150091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return ((reg_ & k64BitMask) == k64Bits);
15100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
15200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
153ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe  constexpr WideKind GetWideKind() const {
154ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe    return Is64Bit() ? kWide : kNotWide;
155ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe  }
156ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe
157836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool Is64BitSolo() const {
1589ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    return ((reg_ & kShapeMask) == k64BitSolo);
1599ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  }
1609ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko
161836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool IsPair() const {
162091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return ((reg_ & kShapeMask) == k64BitPair);
16300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
16400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
165836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool IsFloat() const {
166836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko    return
167836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko        DCHECK_CONSTEXPR(Valid(), , false)
168836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko        ((reg_ & kFloatingPoint) == kFloatingPoint);
16900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
17000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
171836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool IsDouble() const {
172836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko    return
173836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko        DCHECK_CONSTEXPR(Valid(), , false)
174836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko        (reg_ & (kFloatingPoint | k64BitMask)) == (kFloatingPoint | k64Bits);
175091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
176091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
177836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool IsSingle() const {
178836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko    return
179836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko        DCHECK_CONSTEXPR(Valid(), , false)
180836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko        (reg_ & (kFloatingPoint | k64BitMask)) == kFloatingPoint;
181091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
182091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
183836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr bool IsFloat(uint16_t reg) {
184091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return ((reg & kFloatingPoint) == kFloatingPoint);
185091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
186091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
187836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr bool IsDouble(uint16_t reg) {
188091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return (reg & (kFloatingPoint | k64BitMask)) == (kFloatingPoint | k64Bits);
189091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
190091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
191836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr bool IsSingle(uint16_t reg) {
192091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return (reg & (kFloatingPoint | k64BitMask)) == kFloatingPoint;
19300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
19400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
19563999683329612292d534e6be09dbde9480f1250Serban Constantinescu  static constexpr bool Is32Bit(uint16_t reg) {
19663999683329612292d534e6be09dbde9480f1250Serban Constantinescu    return ((reg & kShapeMask) == k32BitSolo);
19763999683329612292d534e6be09dbde9480f1250Serban Constantinescu  }
19863999683329612292d534e6be09dbde9480f1250Serban Constantinescu
19963999683329612292d534e6be09dbde9480f1250Serban Constantinescu  static constexpr bool Is64Bit(uint16_t reg) {
20063999683329612292d534e6be09dbde9480f1250Serban Constantinescu    return ((reg & k64BitMask) == k64Bits);
20163999683329612292d534e6be09dbde9480f1250Serban Constantinescu  }
20263999683329612292d534e6be09dbde9480f1250Serban Constantinescu
20363999683329612292d534e6be09dbde9480f1250Serban Constantinescu  static constexpr bool Is64BitSolo(uint16_t reg) {
20463999683329612292d534e6be09dbde9480f1250Serban Constantinescu    return ((reg & kShapeMask) == k64BitSolo);
20563999683329612292d534e6be09dbde9480f1250Serban Constantinescu  }
20663999683329612292d534e6be09dbde9480f1250Serban Constantinescu
20700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  // Used to retrieve either the low register of a pair, or the only register.
20800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  int GetReg() const {
209091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    DCHECK(!IsPair()) << "reg_ = 0x" << std::hex << reg_;
2102700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return Valid() ? (reg_ & kRegValMask) : kInvalidRegVal;
21100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
21200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
213091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Sets shape, type and num of solo.
21400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  void SetReg(int reg) {
2152700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(Valid());
216091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    DCHECK(!IsPair());
2172700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    reg_ = (reg_ & ~kRegValMask) | reg;
2182700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
2192700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
220091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Set the reg number and type only, target remain 64-bit pair.
2212700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  void SetLowReg(int reg) {
2222700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(IsPair());
223091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    reg_ = (reg_ & ~kRegTypeMask) | (reg & kRegTypeMask);
2242700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
2252700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
226091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Retrieve the least significant register of a pair and return as 32-bit solo.
2272700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  int GetLowReg() const {
2282700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(IsPair());
229091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return ((reg_ & kRegTypeMask) | k32BitSolo);
2302700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
2312700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
2322700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  // Create a stand-alone RegStorage from the low reg of a pair.
2332700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  RegStorage GetLow() const {
2342700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(IsPair());
235091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return RegStorage(k32BitSolo, reg_ & kRegTypeMask);
23600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
23700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
23800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  // Retrieve the most significant register of a pair.
23900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  int GetHighReg() const {
24000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    DCHECK(IsPair());
241d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    return k32BitSolo | ((reg_ & kHighRegMask) >> kHighRegShift) | (reg_ & kFloatingPoint);
24200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
24300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
2442700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  // Create a stand-alone RegStorage from the high reg of a pair.
2452700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  RegStorage GetHigh() const {
2462700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(IsPair());
247091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return RegStorage(kValid | GetHighReg());
2482700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
2492700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
25000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  void SetHighReg(int reg) {
25100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    DCHECK(IsPair());
252d111c6eeb01955964d9c7f68126adcb1e1824ab3buzbee    reg_ = (reg_ & ~kHighRegMask) | ((reg & kHighRegNumMask) << kHighRegShift);
253091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
254091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
255091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Return the register number of low or solo.
256836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr int GetRegNum() const {
257091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return reg_ & kRegNumMask;
258091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
259091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
260091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Is register number in 0..7?
261836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool Low8() const {
262091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return GetRegNum() < 8;
263091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
264091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
265091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Is register number in 0..3?
266836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr bool Low4() const {
267091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return GetRegNum() < 4;
26800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
26900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
2702700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  // Combine 2 32-bit solo regs into a pair.
2712700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  static RegStorage MakeRegPair(RegStorage low, RegStorage high) {
2722700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(!low.IsPair());
2732700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(low.Is32Bit());
2742700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(!high.IsPair());
2752700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    DCHECK(high.Is32Bit());
2762700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return RegStorage(k64BitPair, low.GetReg(), high.GetReg());
2772700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
2782700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
279836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr bool SameRegType(RegStorage reg1, RegStorage reg2) {
28063999683329612292d534e6be09dbde9480f1250Serban Constantinescu    return ((reg1.reg_ & kShapeTypeMask) == (reg2.reg_ & kShapeTypeMask));
281091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
282091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
283836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr bool SameRegType(int reg1, int reg2) {
28463999683329612292d534e6be09dbde9480f1250Serban Constantinescu    return ((reg1 & kShapeTypeMask) == (reg2 & kShapeTypeMask));
285091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
286091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
2872700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  // Create a 32-bit solo.
2882700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  static RegStorage Solo32(int reg_num) {
289091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return RegStorage(k32BitSolo, reg_num & kRegTypeMask);
290091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
291091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
292091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Create a floating point 32-bit solo.
293836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr RegStorage FloatSolo32(int reg_num) {
294091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return RegStorage(k32BitSolo, (reg_num & kRegNumMask) | kFloatingPoint);
2952700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
2962700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
297fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // Create a 128-bit solo.
298836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr RegStorage Solo128(int reg_num) {
299fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    return RegStorage(k128BitSolo, reg_num & kRegTypeMask);
300fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
301fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
3022700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  // Create a 64-bit solo.
303836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr RegStorage Solo64(int reg_num) {
304091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return RegStorage(k64BitSolo, reg_num & kRegTypeMask);
305091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
306091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
307091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Create a floating point 64-bit solo.
308091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  static RegStorage FloatSolo64(int reg_num) {
309091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return RegStorage(k64BitSolo, (reg_num & kRegNumMask) | kFloatingPoint);
3102700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
3112700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
312836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr RegStorage InvalidReg() {
3132700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return RegStorage(kInvalid);
3142700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  }
3152700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee
316836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  static constexpr uint16_t RegNum(int raw_reg_bits) {
317091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return raw_reg_bits & kRegNumMask;
318091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
319091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
320836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  constexpr int GetRawBits() const {
32100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    return reg_;
32200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  }
32300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
324836424805dd48af67088d30992a3f2e6841ca047Vladimir Marko  size_t StorageSize() const {
325091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    switch (reg_ & kShapeMask) {
326091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case kInvalid: return 0;
327091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case k32BitSolo: return 4;
328091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case k64BitSolo: return 8;
329091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case k64BitPair: return 8;  // Is this useful?  Might want to disallow taking size of pair.
330091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case k128BitSolo: return 16;
331091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case k256BitSolo: return 32;
332091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case k512BitSolo: return 64;
333091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      case k1024BitSolo: return 128;
334ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu      default: LOG(FATAL) << "Unexpected shape";
335091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    }
336091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    return 0;
337091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
338091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
33900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee private:
34000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  uint16_t reg_;
34100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee};
34200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
34300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee}  // namespace art
34400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
34500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee#endif  // ART_COMPILER_DEX_REG_STORAGE_H_
346