1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/register-configuration.h" 6 #include "src/globals.h" 7 #include "src/macro-assembler.h" 8 9 namespace v8 { 10 namespace internal { 11 12 namespace { 13 14 #define REGISTER_COUNT(R) 1 + 15 static const int kMaxAllocatableGeneralRegisterCount = 16 ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT)0; 17 static const int kMaxAllocatableDoubleRegisterCount = 18 ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_COUNT)0; 19 20 static const int kAllocatableGeneralCodes[] = { 21 #define REGISTER_CODE(R) Register::kCode_##R, 22 ALLOCATABLE_GENERAL_REGISTERS(REGISTER_CODE)}; 23 #undef REGISTER_CODE 24 25 static const int kAllocatableDoubleCodes[] = { 26 #define REGISTER_CODE(R) DoubleRegister::kCode_##R, 27 ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_CODE)}; 28 #undef REGISTER_CODE 29 30 static const char* const kGeneralRegisterNames[] = { 31 #define REGISTER_NAME(R) #R, 32 GENERAL_REGISTERS(REGISTER_NAME) 33 #undef REGISTER_NAME 34 }; 35 36 static const char* const kFloatRegisterNames[] = { 37 #define REGISTER_NAME(R) #R, 38 FLOAT_REGISTERS(REGISTER_NAME) 39 #undef REGISTER_NAME 40 }; 41 42 static const char* const kDoubleRegisterNames[] = { 43 #define REGISTER_NAME(R) #R, 44 DOUBLE_REGISTERS(REGISTER_NAME) 45 #undef REGISTER_NAME 46 }; 47 48 static const char* const kSimd128RegisterNames[] = { 49 #define REGISTER_NAME(R) #R, 50 SIMD128_REGISTERS(REGISTER_NAME) 51 #undef REGISTER_NAME 52 }; 53 54 STATIC_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >= 55 Register::kNumRegisters); 56 STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >= 57 FloatRegister::kMaxNumRegisters); 58 STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >= 59 DoubleRegister::kMaxNumRegisters); 60 STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >= 61 Simd128Register::kMaxNumRegisters); 62 63 enum CompilerSelector { CRANKSHAFT, TURBOFAN }; 64 65 class ArchDefaultRegisterConfiguration : public RegisterConfiguration { 66 public: 67 explicit ArchDefaultRegisterConfiguration(CompilerSelector compiler) 68 : RegisterConfiguration( 69 Register::kNumRegisters, DoubleRegister::kMaxNumRegisters, 70 #if V8_TARGET_ARCH_IA32 71 kMaxAllocatableGeneralRegisterCount, 72 kMaxAllocatableDoubleRegisterCount, 73 #elif V8_TARGET_ARCH_X87 74 kMaxAllocatableGeneralRegisterCount, 75 compiler == TURBOFAN ? 1 : kMaxAllocatableDoubleRegisterCount, 76 #elif V8_TARGET_ARCH_X64 77 kMaxAllocatableGeneralRegisterCount, 78 kMaxAllocatableDoubleRegisterCount, 79 #elif V8_TARGET_ARCH_ARM 80 FLAG_enable_embedded_constant_pool 81 ? (kMaxAllocatableGeneralRegisterCount - 1) 82 : kMaxAllocatableGeneralRegisterCount, 83 CpuFeatures::IsSupported(VFP32DREGS) 84 ? kMaxAllocatableDoubleRegisterCount 85 : (ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_COUNT) 0), 86 #elif V8_TARGET_ARCH_ARM64 87 kMaxAllocatableGeneralRegisterCount, 88 kMaxAllocatableDoubleRegisterCount, 89 #elif V8_TARGET_ARCH_MIPS 90 kMaxAllocatableGeneralRegisterCount, 91 kMaxAllocatableDoubleRegisterCount, 92 #elif V8_TARGET_ARCH_MIPS64 93 kMaxAllocatableGeneralRegisterCount, 94 kMaxAllocatableDoubleRegisterCount, 95 #elif V8_TARGET_ARCH_PPC 96 kMaxAllocatableGeneralRegisterCount, 97 kMaxAllocatableDoubleRegisterCount, 98 #elif V8_TARGET_ARCH_S390 99 kMaxAllocatableGeneralRegisterCount, 100 kMaxAllocatableDoubleRegisterCount, 101 #else 102 #error Unsupported target architecture. 103 #endif 104 kAllocatableGeneralCodes, kAllocatableDoubleCodes, 105 kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE, 106 kGeneralRegisterNames, kFloatRegisterNames, kDoubleRegisterNames, 107 kSimd128RegisterNames) { 108 } 109 }; 110 111 template <CompilerSelector compiler> 112 struct RegisterConfigurationInitializer { 113 static void Construct(ArchDefaultRegisterConfiguration* config) { 114 new (config) ArchDefaultRegisterConfiguration(compiler); 115 } 116 }; 117 118 static base::LazyInstance<ArchDefaultRegisterConfiguration, 119 RegisterConfigurationInitializer<CRANKSHAFT>>::type 120 kDefaultRegisterConfigurationForCrankshaft = LAZY_INSTANCE_INITIALIZER; 121 122 static base::LazyInstance<ArchDefaultRegisterConfiguration, 123 RegisterConfigurationInitializer<TURBOFAN>>::type 124 kDefaultRegisterConfigurationForTurboFan = LAZY_INSTANCE_INITIALIZER; 125 126 } // namespace 127 128 const RegisterConfiguration* RegisterConfiguration::Crankshaft() { 129 return &kDefaultRegisterConfigurationForCrankshaft.Get(); 130 } 131 132 const RegisterConfiguration* RegisterConfiguration::Turbofan() { 133 return &kDefaultRegisterConfigurationForTurboFan.Get(); 134 } 135 136 RegisterConfiguration::RegisterConfiguration( 137 int num_general_registers, int num_double_registers, 138 int num_allocatable_general_registers, int num_allocatable_double_registers, 139 const int* allocatable_general_codes, const int* allocatable_double_codes, 140 AliasingKind fp_aliasing_kind, const char* const* general_register_names, 141 const char* const* float_register_names, 142 const char* const* double_register_names, 143 const char* const* simd128_register_names) 144 : num_general_registers_(num_general_registers), 145 num_float_registers_(0), 146 num_double_registers_(num_double_registers), 147 num_simd128_registers_(0), 148 num_allocatable_general_registers_(num_allocatable_general_registers), 149 num_allocatable_float_registers_(0), 150 num_allocatable_double_registers_(num_allocatable_double_registers), 151 num_allocatable_simd128_registers_(0), 152 allocatable_general_codes_mask_(0), 153 allocatable_float_codes_mask_(0), 154 allocatable_double_codes_mask_(0), 155 allocatable_simd128_codes_mask_(0), 156 allocatable_general_codes_(allocatable_general_codes), 157 allocatable_double_codes_(allocatable_double_codes), 158 fp_aliasing_kind_(fp_aliasing_kind), 159 general_register_names_(general_register_names), 160 float_register_names_(float_register_names), 161 double_register_names_(double_register_names), 162 simd128_register_names_(simd128_register_names) { 163 DCHECK(num_general_registers_ <= RegisterConfiguration::kMaxGeneralRegisters); 164 DCHECK(num_double_registers_ <= RegisterConfiguration::kMaxFPRegisters); 165 for (int i = 0; i < num_allocatable_general_registers_; ++i) { 166 allocatable_general_codes_mask_ |= (1 << allocatable_general_codes_[i]); 167 } 168 for (int i = 0; i < num_allocatable_double_registers_; ++i) { 169 allocatable_double_codes_mask_ |= (1 << allocatable_double_codes_[i]); 170 } 171 172 if (fp_aliasing_kind_ == COMBINE) { 173 num_float_registers_ = num_double_registers_ * 2 <= kMaxFPRegisters 174 ? num_double_registers_ * 2 175 : kMaxFPRegisters; 176 num_allocatable_float_registers_ = 0; 177 for (int i = 0; i < num_allocatable_double_registers_; i++) { 178 int base_code = allocatable_double_codes_[i] * 2; 179 if (base_code >= kMaxFPRegisters) continue; 180 allocatable_float_codes_[num_allocatable_float_registers_++] = base_code; 181 allocatable_float_codes_[num_allocatable_float_registers_++] = 182 base_code + 1; 183 allocatable_float_codes_mask_ |= (0x3 << base_code); 184 } 185 num_simd128_registers_ = num_double_registers_ / 2; 186 num_allocatable_simd128_registers_ = 0; 187 int last_simd128_code = allocatable_double_codes_[0] / 2; 188 for (int i = 1; i < num_allocatable_double_registers_; i++) { 189 int next_simd128_code = allocatable_double_codes_[i] / 2; 190 // This scheme assumes allocatable_double_codes_ are strictly increasing. 191 DCHECK_GE(next_simd128_code, last_simd128_code); 192 if (last_simd128_code == next_simd128_code) { 193 allocatable_simd128_codes_[num_allocatable_simd128_registers_++] = 194 next_simd128_code; 195 allocatable_simd128_codes_mask_ |= (0x1 << next_simd128_code); 196 } 197 last_simd128_code = next_simd128_code; 198 } 199 } else { 200 DCHECK(fp_aliasing_kind_ == OVERLAP); 201 num_float_registers_ = num_simd128_registers_ = num_double_registers_; 202 num_allocatable_float_registers_ = num_allocatable_simd128_registers_ = 203 num_allocatable_double_registers_; 204 for (int i = 0; i < num_allocatable_float_registers_; ++i) { 205 allocatable_float_codes_[i] = allocatable_simd128_codes_[i] = 206 allocatable_double_codes_[i]; 207 } 208 allocatable_float_codes_mask_ = allocatable_simd128_codes_mask_ = 209 allocatable_double_codes_mask_; 210 } 211 } 212 213 // Assert that kFloat32, kFloat64, and kSimd128 are consecutive values. 214 STATIC_ASSERT(static_cast<int>(MachineRepresentation::kSimd128) == 215 static_cast<int>(MachineRepresentation::kFloat64) + 1); 216 STATIC_ASSERT(static_cast<int>(MachineRepresentation::kFloat64) == 217 static_cast<int>(MachineRepresentation::kFloat32) + 1); 218 219 int RegisterConfiguration::GetAliases(MachineRepresentation rep, int index, 220 MachineRepresentation other_rep, 221 int* alias_base_index) const { 222 DCHECK(fp_aliasing_kind_ == COMBINE); 223 DCHECK(IsFloatingPoint(rep) && IsFloatingPoint(other_rep)); 224 if (rep == other_rep) { 225 *alias_base_index = index; 226 return 1; 227 } 228 int rep_int = static_cast<int>(rep); 229 int other_rep_int = static_cast<int>(other_rep); 230 if (rep_int > other_rep_int) { 231 int shift = rep_int - other_rep_int; 232 int base_index = index << shift; 233 if (base_index >= kMaxFPRegisters) { 234 // Alias indices would be out of FP register range. 235 return 0; 236 } 237 *alias_base_index = base_index; 238 return 1 << shift; 239 } 240 int shift = other_rep_int - rep_int; 241 *alias_base_index = index >> shift; 242 return 1; 243 } 244 245 bool RegisterConfiguration::AreAliases(MachineRepresentation rep, int index, 246 MachineRepresentation other_rep, 247 int other_index) const { 248 DCHECK(fp_aliasing_kind_ == COMBINE); 249 DCHECK(IsFloatingPoint(rep) && IsFloatingPoint(other_rep)); 250 if (rep == other_rep) { 251 return index == other_index; 252 } 253 int rep_int = static_cast<int>(rep); 254 int other_rep_int = static_cast<int>(other_rep); 255 if (rep_int > other_rep_int) { 256 int shift = rep_int - other_rep_int; 257 return index == other_index >> shift; 258 } 259 int shift = other_rep_int - rep_int; 260 return index >> shift == other_index; 261 } 262 263 #undef REGISTER_COUNT 264 265 } // namespace internal 266 } // namespace v8 267