Path: blob/master/dep/vixl/src/aarch64/registers-aarch64.cc
6242 views
// Copyright 2019, VIXL authors1// All rights reserved.2//3// Redistribution and use in source and binary forms, with or without4// modification, are permitted provided that the following conditions are met:5//6// * Redistributions of source code must retain the above copyright notice,7// this list of conditions and the following disclaimer.8// * Redistributions in binary form must reproduce the above copyright notice,9// this list of conditions and the following disclaimer in the documentation10// and/or other materials provided with the distribution.11// * Neither the name of ARM Limited nor the names of its contributors may be12// used to endorse or promote products derived from this software without13// specific prior written permission.14//15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND16// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED17// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE18// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE19// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR21// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER22// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,23// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE24// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2526#include "registers-aarch64.h"2728#include <sstream>29#include <string>3031namespace vixl {32namespace aarch64 {3334std::string CPURegister::GetArchitecturalName() const {35std::ostringstream name;36if (IsZRegister()) {37name << 'z' << GetCode();38if (HasLaneSize()) {39name << '.' << GetLaneSizeSymbol();40}41} else if (IsPRegister()) {42name << 'p' << GetCode();43if (HasLaneSize()) {44name << '.' << GetLaneSizeSymbol();45}46switch (qualifiers_) {47case kNoQualifiers:48break;49case kMerging:50name << "/m";51break;52case kZeroing:53name << "/z";54break;55}56} else {57VIXL_UNIMPLEMENTED();58}59return name.str();60}6162unsigned CPURegister::GetMaxCodeFor(CPURegister::RegisterBank bank) {63switch (bank) {64case kNoRegisterBank:65return 0;66case kRRegisterBank:67return Register::GetMaxCode();68case kVRegisterBank:69#ifdef VIXL_HAS_CONSTEXPR70VIXL_STATIC_ASSERT(VRegister::GetMaxCode() == ZRegister::GetMaxCode());71#else72VIXL_ASSERT(VRegister::GetMaxCode() == ZRegister::GetMaxCode());73#endif74return VRegister::GetMaxCode();75case kPRegisterBank:76return PRegister::GetMaxCode();77}78VIXL_UNREACHABLE();79return 0;80}8182bool CPURegister::IsValidRegister() const {83return ((code_ < kNumberOfRegisters) || (code_ == kSPRegInternalCode)) &&84(bank_ == kRRegisterBank) &&85((size_ == kEncodedWRegSize) || (size_ == kEncodedXRegSize)) &&86(qualifiers_ == kNoQualifiers) && (lane_size_ == size_);87}8889bool CPURegister::IsValidVRegister() const {90VIXL_STATIC_ASSERT(kEncodedBRegSize < kEncodedQRegSize);91return (code_ < kNumberOfVRegisters) && (bank_ == kVRegisterBank) &&92((size_ >= kEncodedBRegSize) && (size_ <= kEncodedQRegSize)) &&93(qualifiers_ == kNoQualifiers) &&94(lane_size_ != kEncodedUnknownSize) && (lane_size_ <= size_);95}9697bool CPURegister::IsValidFPRegister() const {98return IsValidVRegister() && IsFPRegister();99}100101bool CPURegister::IsValidZRegister() const {102VIXL_STATIC_ASSERT(kEncodedBRegSize < kEncodedQRegSize);103// Z registers are valid with or without a lane size, so we don't need to104// check lane_size_.105return (code_ < kNumberOfZRegisters) && (bank_ == kVRegisterBank) &&106(size_ == kEncodedUnknownSize) && (qualifiers_ == kNoQualifiers);107}108109bool CPURegister::IsValidPRegister() const {110VIXL_STATIC_ASSERT(kEncodedBRegSize < kEncodedQRegSize);111// P registers are valid with or without a lane size, so we don't need to112// check lane_size_.113return (code_ < kNumberOfPRegisters) && (bank_ == kPRegisterBank) &&114(size_ == kEncodedUnknownSize) &&115((qualifiers_ == kNoQualifiers) || (qualifiers_ == kMerging) ||116(qualifiers_ == kZeroing));117}118119bool CPURegister::IsValid() const {120return IsValidRegister() || IsValidVRegister() || IsValidZRegister() ||121IsValidPRegister();122}123124// Most coercions simply invoke the necessary constructor.125#define VIXL_CPUREG_COERCION_LIST(U) \126U(Register, W, R) \127U(Register, X, R) \128U(VRegister, B, V) \129U(VRegister, H, V) \130U(VRegister, S, V) \131U(VRegister, D, V) \132U(VRegister, Q, V) \133U(VRegister, V, V) \134U(ZRegister, Z, V) \135U(PRegister, P, P)136#define VIXL_DEFINE_CPUREG_COERCION(RET_TYPE, CTOR_TYPE, BANK) \137RET_TYPE CPURegister::CTOR_TYPE() const { \138VIXL_ASSERT(GetBank() == k##BANK##RegisterBank); \139return CTOR_TYPE##Register(GetCode()); \140}141VIXL_CPUREG_COERCION_LIST(VIXL_DEFINE_CPUREG_COERCION)142#undef VIXL_CPUREG_COERCION_LIST143#undef VIXL_DEFINE_CPUREG_COERCION144145// NEON lane-format coercions always return VRegisters.146#define VIXL_CPUREG_NEON_COERCION_LIST(V) \147V(8, B) \148V(16, B) \149V(2, H) \150V(4, H) \151V(8, H) \152V(2, S) \153V(4, S) \154V(1, D) \155V(2, D) \156V(1, Q)157#define VIXL_DEFINE_CPUREG_NEON_COERCION(LANES, LANE_TYPE) \158VRegister VRegister::V##LANES##LANE_TYPE() const { \159VIXL_ASSERT(IsVRegister()); \160return VRegister(GetCode(), LANES * k##LANE_TYPE##RegSize, LANES); \161}162VIXL_CPUREG_NEON_COERCION_LIST(VIXL_DEFINE_CPUREG_NEON_COERCION)163#undef VIXL_CPUREG_NEON_COERCION_LIST164#undef VIXL_DEFINE_CPUREG_NEON_COERCION165166// Semantic type coercion for sdot and udot.167// TODO: Use the qualifiers_ field to distinguish this from ::S().168VRegister VRegister::S4B() const {169VIXL_ASSERT(IsVRegister());170return SRegister(GetCode());171}172173bool AreAliased(const CPURegister& reg1,174const CPURegister& reg2,175const CPURegister& reg3,176const CPURegister& reg4,177const CPURegister& reg5,178const CPURegister& reg6,179const CPURegister& reg7,180const CPURegister& reg8) {181int number_of_valid_regs = 0;182int number_of_valid_vregs = 0;183int number_of_valid_pregs = 0;184185RegList unique_regs = 0;186RegList unique_vregs = 0;187RegList unique_pregs = 0;188189const CPURegister regs[] = {reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8};190191for (size_t i = 0; i < ArrayLength(regs); i++) {192switch (regs[i].GetBank()) {193case CPURegister::kRRegisterBank:194number_of_valid_regs++;195unique_regs |= regs[i].GetBit();196break;197case CPURegister::kVRegisterBank:198number_of_valid_vregs++;199unique_vregs |= regs[i].GetBit();200break;201case CPURegister::kPRegisterBank:202number_of_valid_pregs++;203unique_pregs |= regs[i].GetBit();204break;205case CPURegister::kNoRegisterBank:206VIXL_ASSERT(regs[i].IsNone());207break;208}209}210211int number_of_unique_regs = CountSetBits(unique_regs);212int number_of_unique_vregs = CountSetBits(unique_vregs);213int number_of_unique_pregs = CountSetBits(unique_pregs);214215VIXL_ASSERT(number_of_valid_regs >= number_of_unique_regs);216VIXL_ASSERT(number_of_valid_vregs >= number_of_unique_vregs);217VIXL_ASSERT(number_of_valid_pregs >= number_of_unique_pregs);218219return (number_of_valid_regs != number_of_unique_regs) ||220(number_of_valid_vregs != number_of_unique_vregs) ||221(number_of_valid_pregs != number_of_unique_pregs);222}223224bool AreSameSizeAndType(const CPURegister& reg1,225const CPURegister& reg2,226const CPURegister& reg3,227const CPURegister& reg4,228const CPURegister& reg5,229const CPURegister& reg6,230const CPURegister& reg7,231const CPURegister& reg8) {232VIXL_ASSERT(reg1.IsValid());233bool match = true;234match &= !reg2.IsValid() || reg2.IsSameSizeAndType(reg1);235match &= !reg3.IsValid() || reg3.IsSameSizeAndType(reg1);236match &= !reg4.IsValid() || reg4.IsSameSizeAndType(reg1);237match &= !reg5.IsValid() || reg5.IsSameSizeAndType(reg1);238match &= !reg6.IsValid() || reg6.IsSameSizeAndType(reg1);239match &= !reg7.IsValid() || reg7.IsSameSizeAndType(reg1);240match &= !reg8.IsValid() || reg8.IsSameSizeAndType(reg1);241return match;242}243244bool AreEven(const CPURegister& reg1,245const CPURegister& reg2,246const CPURegister& reg3,247const CPURegister& reg4,248const CPURegister& reg5,249const CPURegister& reg6,250const CPURegister& reg7,251const CPURegister& reg8) {252VIXL_ASSERT(reg1.IsValid());253bool even = (reg1.GetCode() % 2) == 0;254even &= !reg2.IsValid() || ((reg2.GetCode() % 2) == 0);255even &= !reg3.IsValid() || ((reg3.GetCode() % 2) == 0);256even &= !reg4.IsValid() || ((reg4.GetCode() % 2) == 0);257even &= !reg5.IsValid() || ((reg5.GetCode() % 2) == 0);258even &= !reg6.IsValid() || ((reg6.GetCode() % 2) == 0);259even &= !reg7.IsValid() || ((reg7.GetCode() % 2) == 0);260even &= !reg8.IsValid() || ((reg8.GetCode() % 2) == 0);261return even;262}263264bool AreConsecutive(const CPURegister& reg1,265const CPURegister& reg2,266const CPURegister& reg3,267const CPURegister& reg4) {268VIXL_ASSERT(reg1.IsValid());269270if (!reg2.IsValid()) {271return true;272} else if (reg2.GetCode() !=273((reg1.GetCode() + 1) % (reg1.GetMaxCode() + 1))) {274return false;275}276277if (!reg3.IsValid()) {278return true;279} else if (reg3.GetCode() !=280((reg2.GetCode() + 1) % (reg1.GetMaxCode() + 1))) {281return false;282}283284if (!reg4.IsValid()) {285return true;286} else if (reg4.GetCode() !=287((reg3.GetCode() + 1) % (reg1.GetMaxCode() + 1))) {288return false;289}290291return true;292}293294bool AreSameFormat(const CPURegister& reg1,295const CPURegister& reg2,296const CPURegister& reg3,297const CPURegister& reg4) {298VIXL_ASSERT(reg1.IsValid());299bool match = true;300match &= !reg2.IsValid() || reg2.IsSameFormat(reg1);301match &= !reg3.IsValid() || reg3.IsSameFormat(reg1);302match &= !reg4.IsValid() || reg4.IsSameFormat(reg1);303return match;304}305306bool AreSameLaneSize(const CPURegister& reg1,307const CPURegister& reg2,308const CPURegister& reg3,309const CPURegister& reg4) {310VIXL_ASSERT(reg1.IsValid());311bool match = true;312match &=313!reg2.IsValid() || (reg2.GetLaneSizeInBits() == reg1.GetLaneSizeInBits());314match &=315!reg3.IsValid() || (reg3.GetLaneSizeInBits() == reg1.GetLaneSizeInBits());316match &=317!reg4.IsValid() || (reg4.GetLaneSizeInBits() == reg1.GetLaneSizeInBits());318return match;319}320} // namespace aarch64321} // namespace vixl322323324