| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef ART_COMPILER_DEX_REG_STORAGE_H_ |
| #define ART_COMPILER_DEX_REG_STORAGE_H_ |
| |
| |
| namespace art { |
| |
| /* |
| * Representation of the physical register, register pair or vector holding a Dalvik value. |
| * The basic configuration of the storage (i.e. solo reg, pair, vector) is common across all |
| * targets, but the encoding of the actual storage element is target independent. |
| * |
| * The two most-significant bits describe the basic shape of the storage, while meaning of the |
| * lower 14 bits depends on the shape: |
| * |
| * [PW] |
| * P: 0 -> pair, 1 -> solo (or vector) |
| * W: 1 -> 64 bits, 0 -> 32 bits |
| * |
| * [00] [xxxxxxxxxxxxxx] Invalid (typically all zeros) |
| * [01] [HHHHHHH] [LLLLLLL] 64-bit storage, composed of 2 32-bit registers |
| * [10] [0] [xxxxxx] [RRRRRRR] 32-bit solo register |
| * [11] [0] [xxxxxx] [RRRRRRR] 64-bit solo register |
| * [10] [1] [xxxxxx] [VVVVVVV] 32-bit vector storage |
| * [11] [1] [xxxxxx] [VVVVVVV] 64-bit vector storage |
| * |
| * x - don't care |
| * L - low register number of a pair |
| * H - high register number of a pair |
| * R - register number of a solo reg |
| * V - vector description |
| * |
| * Note that in all non-invalid cases, the low 7 bits must be sufficient to describe |
| * whether the storage element is floating point (see IsFloatReg()). |
| * |
| */ |
| |
| class RegStorage { |
| public: |
| enum RegStorageKind { |
| kInvalid = 0x0000, |
| k64BitPair = 0x4000, |
| k32BitSolo = 0x8000, |
| k64BitSolo = 0xc000, |
| k32BitVector = 0xa000, |
| k64BitVector = 0xe000, |
| kPairMask = 0x8000, |
| kPair = 0x0000, |
| kSizeMask = 0x4000, |
| k64Bit = 0x4000, |
| k32Bit = 0x0000, |
| kVectorMask = 0xa000, |
| kVector = 0xa000, |
| kSolo = 0x8000, |
| kShapeMask = 0xc000, |
| kKindMask = 0xe000 |
| }; |
| |
| static const uint16_t kRegValMask = 0x007f; |
| static const uint16_t kInvalidRegVal = 0x007f; |
| static const uint16_t kHighRegShift = 7; |
| static const uint16_t kHighRegMask = kRegValMask << kHighRegShift; |
| |
| RegStorage(RegStorageKind rs_kind, int reg) { |
| DCHECK_NE(rs_kind & kShapeMask, kInvalid); |
| DCHECK_NE(rs_kind & kShapeMask, k64BitPair); |
| DCHECK_EQ(rs_kind & ~kKindMask, 0); |
| DCHECK_EQ(reg & ~kRegValMask, 0); |
| reg_ = rs_kind | reg; |
| } |
| RegStorage(RegStorageKind rs_kind, int low_reg, int high_reg) { |
| DCHECK_EQ(rs_kind, k64BitPair); |
| DCHECK_EQ(low_reg & ~kRegValMask, 0); |
| DCHECK_EQ(high_reg & ~kRegValMask, 0); |
| reg_ = rs_kind | (high_reg << kHighRegShift) | low_reg; |
| } |
| explicit RegStorage(uint16_t val) : reg_(val) {} |
| RegStorage() : reg_(kInvalid) {} |
| ~RegStorage() {} |
| |
| bool operator==(const RegStorage rhs) const { |
| return (reg_ == rhs.GetRawBits()); |
| } |
| |
| bool operator!=(const RegStorage rhs) const { |
| return (reg_ != rhs.GetRawBits()); |
| } |
| |
| bool Valid() const { |
| return ((reg_ & kShapeMask) != kInvalid); |
| } |
| |
| bool Is32Bit() const { |
| return ((reg_ & kSizeMask) == k32Bit); |
| } |
| |
| bool Is64Bit() const { |
| return ((reg_ & kSizeMask) == k64Bit); |
| } |
| |
| bool IsPair() const { |
| return ((reg_ & kPairMask) == kPair); |
| } |
| |
| bool IsSolo() const { |
| return ((reg_ & kVectorMask) == kSolo); |
| } |
| |
| bool IsVector() const { |
| return ((reg_ & kVectorMask) == kVector); |
| } |
| |
| // Used to retrieve either the low register of a pair, or the only register. |
| int GetReg() const { |
| DCHECK(!IsPair()); |
| return Valid() ? (reg_ & kRegValMask) : kInvalidRegVal; |
| } |
| |
| void SetReg(int reg) { |
| DCHECK(Valid()); |
| reg_ = (reg_ & ~kRegValMask) | reg; |
| } |
| |
| void SetLowReg(int reg) { |
| DCHECK(IsPair()); |
| reg_ = (reg_ & ~kRegValMask) | reg; |
| } |
| |
| // Retrieve the least significant register of a pair. |
| int GetLowReg() const { |
| DCHECK(IsPair()); |
| return (reg_ & kRegValMask); |
| } |
| |
| // Create a stand-alone RegStorage from the low reg of a pair. |
| RegStorage GetLow() const { |
| DCHECK(IsPair()); |
| return RegStorage(k32BitSolo, reg_ & kRegValMask); |
| } |
| |
| // Retrieve the most significant register of a pair. |
| int GetHighReg() const { |
| DCHECK(IsPair()); |
| return (reg_ & kHighRegMask) >> kHighRegShift; |
| } |
| |
| // Create a stand-alone RegStorage from the high reg of a pair. |
| RegStorage GetHigh() const { |
| DCHECK(IsPair()); |
| return RegStorage(k32BitSolo, (reg_ & kHighRegMask) >> kHighRegShift); |
| } |
| |
| void SetHighReg(int reg) { |
| DCHECK(IsPair()); |
| reg_ = (reg_ & ~kHighRegMask) | (reg << kHighRegShift); |
| DCHECK_EQ(GetHighReg(), reg); |
| } |
| |
| // Combine 2 32-bit solo regs into a pair. |
| static RegStorage MakeRegPair(RegStorage low, RegStorage high) { |
| DCHECK(!low.IsPair()); |
| DCHECK(low.Is32Bit()); |
| DCHECK(!high.IsPair()); |
| DCHECK(high.Is32Bit()); |
| return RegStorage(k64BitPair, low.GetReg(), high.GetReg()); |
| } |
| |
| // Create a 32-bit solo. |
| static RegStorage Solo32(int reg_num) { |
| return RegStorage(k32BitSolo, reg_num); |
| } |
| |
| // Create a 64-bit solo. |
| static RegStorage Solo64(int reg_num) { |
| return RegStorage(k64BitSolo, reg_num); |
| } |
| |
| static RegStorage InvalidReg() { |
| return RegStorage(kInvalid); |
| } |
| |
| int GetRawBits() const { |
| return reg_; |
| } |
| |
| private: |
| uint16_t reg_; |
| }; |
| |
| } // namespace art |
| |
| #endif // ART_COMPILER_DEX_REG_STORAGE_H_ |