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 9namespace v8 { 10namespace internal { 11 12namespace { 13 14#define REGISTER_COUNT(R) 1 + 15static const int kMaxAllocatableGeneralRegisterCount = 16 ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT)0; 17static const int kMaxAllocatableDoubleRegisterCount = 18 ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_COUNT)0; 19 20static const int kAllocatableGeneralCodes[] = { 21#define REGISTER_CODE(R) Register::kCode_##R, 22 ALLOCATABLE_GENERAL_REGISTERS(REGISTER_CODE)}; 23#undef REGISTER_CODE 24 25static const int kAllocatableDoubleCodes[] = { 26#define REGISTER_CODE(R) DoubleRegister::kCode_##R, 27 ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_CODE)}; 28#undef REGISTER_CODE 29 30static const char* const kGeneralRegisterNames[] = { 31#define REGISTER_NAME(R) #R, 32 GENERAL_REGISTERS(REGISTER_NAME) 33#undef REGISTER_NAME 34}; 35 36static const char* const kFloatRegisterNames[] = { 37#define REGISTER_NAME(R) #R, 38 FLOAT_REGISTERS(REGISTER_NAME) 39#undef REGISTER_NAME 40}; 41 42static const char* const kDoubleRegisterNames[] = { 43#define REGISTER_NAME(R) #R, 44 DOUBLE_REGISTERS(REGISTER_NAME) 45#undef REGISTER_NAME 46}; 47 48static const char* const kSimd128RegisterNames[] = { 49#define REGISTER_NAME(R) #R, 50 SIMD128_REGISTERS(REGISTER_NAME) 51#undef REGISTER_NAME 52}; 53 54STATIC_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >= 55 Register::kNumRegisters); 56STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >= 57 FloatRegister::kMaxNumRegisters); 58STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >= 59 DoubleRegister::kMaxNumRegisters); 60STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >= 61 Simd128Register::kMaxNumRegisters); 62 63enum CompilerSelector { CRANKSHAFT, TURBOFAN }; 64 65class 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 111template <CompilerSelector compiler> 112struct RegisterConfigurationInitializer { 113 static void Construct(ArchDefaultRegisterConfiguration* config) { 114 new (config) ArchDefaultRegisterConfiguration(compiler); 115 } 116}; 117 118static base::LazyInstance<ArchDefaultRegisterConfiguration, 119 RegisterConfigurationInitializer<CRANKSHAFT>>::type 120 kDefaultRegisterConfigurationForCrankshaft = LAZY_INSTANCE_INITIALIZER; 121 122static base::LazyInstance<ArchDefaultRegisterConfiguration, 123 RegisterConfigurationInitializer<TURBOFAN>>::type 124 kDefaultRegisterConfigurationForTurboFan = LAZY_INSTANCE_INITIALIZER; 125 126} // namespace 127 128const RegisterConfiguration* RegisterConfiguration::Crankshaft() { 129 return &kDefaultRegisterConfigurationForCrankshaft.Get(); 130} 131 132const RegisterConfiguration* RegisterConfiguration::Turbofan() { 133 return &kDefaultRegisterConfigurationForTurboFan.Get(); 134} 135 136RegisterConfiguration::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. 214STATIC_ASSERT(static_cast<int>(MachineRepresentation::kSimd128) == 215 static_cast<int>(MachineRepresentation::kFloat64) + 1); 216STATIC_ASSERT(static_cast<int>(MachineRepresentation::kFloat64) == 217 static_cast<int>(MachineRepresentation::kFloat32) + 1); 218 219int 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 245bool 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