Registers-vixl.cpp (9275B)
1 // Copyright 2019, VIXL authors 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are met: 6 // 7 // * Redistributions of source code must retain the above copyright notice, 8 // this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above copyright notice, 10 // this list of conditions and the following disclaimer in the documentation 11 // and/or other materials provided with the distribution. 12 // * Neither the name of ARM Limited nor the names of its contributors may be 13 // used to endorse or promote products derived from this software without 14 // specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 #include "jit/arm64/vixl/Registers-vixl.h" 28 29 namespace vixl { 30 31 unsigned CPURegister::GetMaxCodeFor(CPURegister::RegisterBank bank) { 32 switch (bank) { 33 case kNoRegisterBank: 34 return 0; 35 case kRRegisterBank: 36 return Register::GetMaxCode(); 37 case kVRegisterBank: 38 #ifdef VIXL_HAS_CONSTEXPR 39 VIXL_STATIC_ASSERT(VRegister::GetMaxCode() == ZRegister::GetMaxCode()); 40 #else 41 VIXL_ASSERT(VRegister::GetMaxCode() == ZRegister::GetMaxCode()); 42 #endif 43 return VRegister::GetMaxCode(); 44 case kPRegisterBank: 45 return PRegister::GetMaxCode(); 46 } 47 VIXL_UNREACHABLE(); 48 return 0; 49 } 50 51 // Most coercions simply invoke the necessary constructor. 52 #define VIXL_CPUREG_COERCION_LIST(U) \ 53 U(Register, W, R) \ 54 U(Register, X, R) \ 55 U(VRegister, B, V) \ 56 U(VRegister, H, V) \ 57 U(VRegister, S, V) \ 58 U(VRegister, D, V) \ 59 U(VRegister, Q, V) \ 60 U(VRegister, V, V) \ 61 U(ZRegister, Z, V) \ 62 U(PRegister, P, P) 63 #define VIXL_DEFINE_CPUREG_COERCION(RET_TYPE, CTOR_TYPE, BANK) \ 64 RET_TYPE CPURegister::CTOR_TYPE() const { \ 65 VIXL_ASSERT(GetBank() == k##BANK##RegisterBank); \ 66 return CTOR_TYPE##Register(GetCode()); \ 67 } 68 VIXL_CPUREG_COERCION_LIST(VIXL_DEFINE_CPUREG_COERCION) 69 #undef VIXL_CPUREG_COERCION_LIST 70 #undef VIXL_DEFINE_CPUREG_COERCION 71 72 // NEON lane-format coercions always return VRegisters. 73 #define VIXL_CPUREG_NEON_COERCION_LIST(V) \ 74 V(8, B) \ 75 V(16, B) \ 76 V(2, H) \ 77 V(4, H) \ 78 V(8, H) \ 79 V(2, S) \ 80 V(4, S) \ 81 V(1, D) \ 82 V(2, D) \ 83 V(1, Q) 84 #define VIXL_DEFINE_CPUREG_NEON_COERCION(LANES, LANE_TYPE) \ 85 VRegister VRegister::V##LANES##LANE_TYPE() const { \ 86 VIXL_ASSERT(IsVRegister()); \ 87 return VRegister(GetCode(), LANES * k##LANE_TYPE##RegSize, LANES); \ 88 } 89 VIXL_CPUREG_NEON_COERCION_LIST(VIXL_DEFINE_CPUREG_NEON_COERCION) 90 #undef VIXL_CPUREG_NEON_COERCION_LIST 91 #undef VIXL_DEFINE_CPUREG_NEON_COERCION 92 93 // Semantic type coercion for sdot and udot. 94 // TODO: Use the qualifiers_ field to distinguish this from ::S(). 95 VRegister VRegister::S4B() const { 96 VIXL_ASSERT(IsVRegister()); 97 return SRegister(GetCode()); 98 } 99 100 bool AreAliased(const CPURegister& reg1, 101 const CPURegister& reg2, 102 const CPURegister& reg3, 103 const CPURegister& reg4, 104 const CPURegister& reg5, 105 const CPURegister& reg6, 106 const CPURegister& reg7, 107 const CPURegister& reg8) { 108 int number_of_valid_regs = 0; 109 int number_of_valid_vregs = 0; 110 int number_of_valid_pregs = 0; 111 112 RegList unique_regs = 0; 113 RegList unique_vregs = 0; 114 RegList unique_pregs = 0; 115 116 const CPURegister regs[] = {reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8}; 117 118 for (size_t i = 0; i < ArrayLength(regs); i++) { 119 switch (regs[i].GetBank()) { 120 case CPURegister::kRRegisterBank: 121 number_of_valid_regs++; 122 unique_regs |= regs[i].GetBit(); 123 break; 124 case CPURegister::kVRegisterBank: 125 number_of_valid_vregs++; 126 unique_vregs |= regs[i].GetBit(); 127 break; 128 case CPURegister::kPRegisterBank: 129 number_of_valid_pregs++; 130 unique_pregs |= regs[i].GetBit(); 131 break; 132 case CPURegister::kNoRegisterBank: 133 VIXL_ASSERT(regs[i].IsNone()); 134 break; 135 } 136 } 137 138 int number_of_unique_regs = CountSetBits(unique_regs); 139 int number_of_unique_vregs = CountSetBits(unique_vregs); 140 int number_of_unique_pregs = CountSetBits(unique_pregs); 141 142 VIXL_ASSERT(number_of_valid_regs >= number_of_unique_regs); 143 VIXL_ASSERT(number_of_valid_vregs >= number_of_unique_vregs); 144 VIXL_ASSERT(number_of_valid_pregs >= number_of_unique_pregs); 145 146 return (number_of_valid_regs != number_of_unique_regs) || 147 (number_of_valid_vregs != number_of_unique_vregs) || 148 (number_of_valid_pregs != number_of_unique_pregs); 149 } 150 151 bool AreSameSizeAndType(const CPURegister& reg1, 152 const CPURegister& reg2, 153 const CPURegister& reg3, 154 const CPURegister& reg4, 155 const CPURegister& reg5, 156 const CPURegister& reg6, 157 const CPURegister& reg7, 158 const CPURegister& reg8) { 159 VIXL_ASSERT(reg1.IsValid()); 160 bool match = true; 161 match &= !reg2.IsValid() || reg2.IsSameSizeAndType(reg1); 162 match &= !reg3.IsValid() || reg3.IsSameSizeAndType(reg1); 163 match &= !reg4.IsValid() || reg4.IsSameSizeAndType(reg1); 164 match &= !reg5.IsValid() || reg5.IsSameSizeAndType(reg1); 165 match &= !reg6.IsValid() || reg6.IsSameSizeAndType(reg1); 166 match &= !reg7.IsValid() || reg7.IsSameSizeAndType(reg1); 167 match &= !reg8.IsValid() || reg8.IsSameSizeAndType(reg1); 168 return match; 169 } 170 171 bool AreEven(const CPURegister& reg1, 172 const CPURegister& reg2, 173 const CPURegister& reg3, 174 const CPURegister& reg4, 175 const CPURegister& reg5, 176 const CPURegister& reg6, 177 const CPURegister& reg7, 178 const CPURegister& reg8) { 179 VIXL_ASSERT(reg1.IsValid()); 180 bool even = (reg1.GetCode() % 2) == 0; 181 even &= !reg2.IsValid() || ((reg2.GetCode() % 2) == 0); 182 even &= !reg3.IsValid() || ((reg3.GetCode() % 2) == 0); 183 even &= !reg4.IsValid() || ((reg4.GetCode() % 2) == 0); 184 even &= !reg5.IsValid() || ((reg5.GetCode() % 2) == 0); 185 even &= !reg6.IsValid() || ((reg6.GetCode() % 2) == 0); 186 even &= !reg7.IsValid() || ((reg7.GetCode() % 2) == 0); 187 even &= !reg8.IsValid() || ((reg8.GetCode() % 2) == 0); 188 return even; 189 } 190 191 bool AreConsecutive(const CPURegister& reg1, 192 const CPURegister& reg2, 193 const CPURegister& reg3, 194 const CPURegister& reg4) { 195 VIXL_ASSERT(reg1.IsValid()); 196 197 if (!reg2.IsValid()) { 198 return true; 199 } else if (reg2.GetCode() != 200 ((reg1.GetCode() + 1) % (reg1.GetMaxCode() + 1))) { 201 return false; 202 } 203 204 if (!reg3.IsValid()) { 205 return true; 206 } else if (reg3.GetCode() != 207 ((reg2.GetCode() + 1) % (reg1.GetMaxCode() + 1))) { 208 return false; 209 } 210 211 if (!reg4.IsValid()) { 212 return true; 213 } else if (reg4.GetCode() != 214 ((reg3.GetCode() + 1) % (reg1.GetMaxCode() + 1))) { 215 return false; 216 } 217 218 return true; 219 } 220 221 bool AreSameFormat(const CPURegister& reg1, 222 const CPURegister& reg2, 223 const CPURegister& reg3, 224 const CPURegister& reg4) { 225 VIXL_ASSERT(reg1.IsValid()); 226 bool match = true; 227 match &= !reg2.IsValid() || reg2.IsSameFormat(reg1); 228 match &= !reg3.IsValid() || reg3.IsSameFormat(reg1); 229 match &= !reg4.IsValid() || reg4.IsSameFormat(reg1); 230 return match; 231 } 232 233 bool AreSameLaneSize(const CPURegister& reg1, 234 const CPURegister& reg2, 235 const CPURegister& reg3, 236 const CPURegister& reg4) { 237 VIXL_ASSERT(reg1.IsValid()); 238 bool match = true; 239 match &= 240 !reg2.IsValid() || (reg2.GetLaneSizeInBits() == reg1.GetLaneSizeInBits()); 241 match &= 242 !reg3.IsValid() || (reg3.GetLaneSizeInBits() == reg1.GetLaneSizeInBits()); 243 match &= 244 !reg4.IsValid() || (reg4.GetLaneSizeInBits() == reg1.GetLaneSizeInBits()); 245 return match; 246 } 247 } // namespace vixl