Bill Buzbee | 00e1ec6 | 2014-02-27 23:44:13 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2014 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #ifndef ART_COMPILER_DEX_REG_STORAGE_H_ |
| 18 | #define ART_COMPILER_DEX_REG_STORAGE_H_ |
| 19 | |
| 20 | |
| 21 | namespace art { |
| 22 | |
| 23 | /* |
| 24 | * Representation of the physical register, register pair or vector holding a Dalvik value. |
| 25 | * The basic configuration of the storage (i.e. solo reg, pair, vector) is common across all |
| 26 | * targets, but the encoding of the actual storage element is target independent. |
| 27 | * |
| 28 | * The two most-significant bits describe the basic shape of the storage, while meaning of the |
| 29 | * lower 14 bits depends on the shape: |
| 30 | * |
| 31 | * [PW] |
| 32 | * P: 0 -> pair, 1 -> solo (or vector) |
| 33 | * W: 1 -> 64 bits, 0 -> 32 bits |
| 34 | * |
| 35 | * [00] [xxxxxxxxxxxxxx] Invalid (typically all zeros) |
| 36 | * [01] [HHHHHHH] [LLLLLLL] 64-bit storage, composed of 2 32-bit registers |
| 37 | * [10] [0] [xxxxxx] [RRRRRRR] 32-bit solo register |
| 38 | * [11] [0] [xxxxxx] [RRRRRRR] 64-bit solo register |
| 39 | * [10] [1] [xxxxxx] [VVVVVVV] 32-bit vector storage |
| 40 | * [11] [1] [xxxxxx] [VVVVVVV] 64-bit vector storage |
| 41 | * |
| 42 | * x - don't care |
| 43 | * L - low register number of a pair |
| 44 | * H - high register number of a pair |
| 45 | * R - register number of a solo reg |
| 46 | * V - vector description |
| 47 | * |
| 48 | * Note that in all non-invalid cases, the low 7 bits must be sufficient to describe |
| 49 | * whether the storage element is floating point (see IsFloatReg()). |
| 50 | * |
| 51 | */ |
| 52 | |
| 53 | class RegStorage { |
| 54 | public: |
| 55 | enum RegStorageKind { |
| 56 | kInvalid = 0x0000, |
| 57 | k64BitPair = 0x4000, |
| 58 | k32BitSolo = 0x8000, |
| 59 | k64BitSolo = 0xc000, |
| 60 | k32BitVector = 0xa000, |
| 61 | k64BitVector = 0xe000, |
| 62 | kPairMask = 0x8000, |
| 63 | kPair = 0x0000, |
| 64 | kSizeMask = 0x4000, |
| 65 | k64Bit = 0x4000, |
| 66 | k32Bit = 0x0000, |
| 67 | kVectorMask = 0xa000, |
| 68 | kVector = 0xa000, |
| 69 | kSolo = 0x8000, |
| 70 | kShapeMask = 0xc000, |
| 71 | kKindMask = 0xe000 |
| 72 | }; |
| 73 | |
| 74 | static const uint16_t kRegValMask = 0x007f; |
| 75 | static const uint16_t kHighRegShift = 7; |
| 76 | static const uint16_t kHighRegMask = kRegValMask << kHighRegShift; |
| 77 | |
| 78 | RegStorage(RegStorageKind rs_kind, int reg) { |
| 79 | DCHECK_NE(rs_kind & kShapeMask, kInvalid); |
| 80 | DCHECK_NE(rs_kind & kShapeMask, k64BitPair); |
| 81 | DCHECK_EQ(rs_kind & ~kKindMask, 0); |
| 82 | DCHECK_EQ(reg & ~kRegValMask, 0); |
| 83 | reg_ = rs_kind | reg; |
| 84 | } |
| 85 | RegStorage(RegStorageKind rs_kind, int low_reg, int high_reg) { |
| 86 | DCHECK_EQ(rs_kind, k64BitPair); |
| 87 | DCHECK_EQ(low_reg & ~kRegValMask, 0); |
| 88 | DCHECK_EQ(high_reg & ~kRegValMask, 0); |
| 89 | reg_ = rs_kind | (high_reg << kHighRegShift) | low_reg; |
| 90 | } |
| 91 | explicit RegStorage(uint16_t val) : reg_(val) {} |
| 92 | RegStorage() : reg_(kInvalid) {} |
| 93 | ~RegStorage() {} |
| 94 | |
| 95 | bool IsInvalid() const { |
| 96 | return ((reg_ & kShapeMask) == kInvalid); |
| 97 | } |
| 98 | |
| 99 | bool Is32Bit() const { |
| 100 | DCHECK(!IsInvalid()); |
| 101 | return ((reg_ & kSizeMask) == k32Bit); |
| 102 | } |
| 103 | |
| 104 | bool Is64Bit() const { |
| 105 | DCHECK(!IsInvalid()); |
| 106 | return ((reg_ & kSizeMask) == k64Bit); |
| 107 | } |
| 108 | |
| 109 | bool IsPair() const { |
| 110 | DCHECK(!IsInvalid()); |
| 111 | return ((reg_ & kPairMask) == kPair); |
| 112 | } |
| 113 | |
| 114 | bool IsSolo() const { |
| 115 | DCHECK(!IsInvalid()); |
| 116 | return ((reg_ & kVectorMask) == kSolo); |
| 117 | } |
| 118 | |
| 119 | bool IsVector() const { |
| 120 | DCHECK(!IsInvalid()); |
| 121 | return ((reg_ & kVectorMask) == kVector); |
| 122 | } |
| 123 | |
| 124 | // Used to retrieve either the low register of a pair, or the only register. |
| 125 | int GetReg() const { |
| 126 | DCHECK(!IsInvalid()); |
| 127 | return (reg_ & kRegValMask); |
| 128 | } |
| 129 | |
| 130 | void SetReg(int reg) { |
| 131 | DCHECK(!IsInvalid()); |
| 132 | reg_ = (reg_ & ~kRegValMask) | reg; |
| 133 | DCHECK_EQ(GetReg(), reg); |
| 134 | } |
| 135 | |
| 136 | // Retrieve the most significant register of a pair. |
| 137 | int GetHighReg() const { |
| 138 | DCHECK(IsPair()); |
| 139 | return (reg_ & kHighRegMask) >> kHighRegShift; |
| 140 | } |
| 141 | |
| 142 | void SetHighReg(int reg) { |
| 143 | DCHECK(IsPair()); |
| 144 | reg_ = (reg_ & ~kHighRegMask) | (reg << kHighRegShift); |
| 145 | DCHECK_EQ(GetHighReg(), reg); |
| 146 | } |
| 147 | |
| 148 | int GetRawBits() const { |
| 149 | return reg_; |
| 150 | } |
| 151 | |
| 152 | private: |
| 153 | uint16_t reg_; |
| 154 | }; |
| 155 | |
| 156 | } // namespace art |
| 157 | |
| 158 | #endif // ART_COMPILER_DEX_REG_STORAGE_H_ |