blob: 11bec99585474cec70cb86590eaba1bf2e0c2cbd [file] [log] [blame]
/*
* 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_