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_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >= 49 Register::kNumRegisters); 50 STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >= 51 DoubleRegister::kMaxNumRegisters); 52 53 enum CompilerSelector { CRANKSHAFT, TURBOFAN }; 54 55 class ArchDefaultRegisterConfiguration : public RegisterConfiguration { 56 public: 57 explicit ArchDefaultRegisterConfiguration(CompilerSelector compiler) 58 : RegisterConfiguration( 59 Register::kNumRegisters, DoubleRegister::kMaxNumRegisters, 60 #if V8_TARGET_ARCH_IA32 61 kMaxAllocatableGeneralRegisterCount, 62 kMaxAllocatableDoubleRegisterCount, 63 #elif V8_TARGET_ARCH_X87 64 kMaxAllocatableGeneralRegisterCount, 65 compiler == TURBOFAN ? 1 : kMaxAllocatableDoubleRegisterCount, 66 #elif V8_TARGET_ARCH_X64 67 kMaxAllocatableGeneralRegisterCount, 68 kMaxAllocatableDoubleRegisterCount, 69 #elif V8_TARGET_ARCH_ARM 70 FLAG_enable_embedded_constant_pool 71 ? (kMaxAllocatableGeneralRegisterCount - 1) 72 : kMaxAllocatableGeneralRegisterCount, 73 CpuFeatures::IsSupported(VFP32DREGS) 74 ? kMaxAllocatableDoubleRegisterCount 75 : (ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_COUNT) 0), 76 #elif V8_TARGET_ARCH_ARM64 77 kMaxAllocatableGeneralRegisterCount, 78 kMaxAllocatableDoubleRegisterCount, 79 #elif V8_TARGET_ARCH_MIPS 80 kMaxAllocatableGeneralRegisterCount, 81 kMaxAllocatableDoubleRegisterCount, 82 #elif V8_TARGET_ARCH_MIPS64 83 kMaxAllocatableGeneralRegisterCount, 84 kMaxAllocatableDoubleRegisterCount, 85 #elif V8_TARGET_ARCH_PPC 86 kMaxAllocatableGeneralRegisterCount, 87 kMaxAllocatableDoubleRegisterCount, 88 #elif V8_TARGET_ARCH_S390 89 kMaxAllocatableGeneralRegisterCount, 90 kMaxAllocatableDoubleRegisterCount, 91 #else 92 #error Unsupported target architecture. 93 #endif 94 kAllocatableGeneralCodes, kAllocatableDoubleCodes, 95 kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE, 96 kGeneralRegisterNames, kFloatRegisterNames, kDoubleRegisterNames) { 97 } 98 }; 99 100 template <CompilerSelector compiler> 101 struct RegisterConfigurationInitializer { 102 static void Construct(ArchDefaultRegisterConfiguration* config) { 103 new (config) ArchDefaultRegisterConfiguration(compiler); 104 } 105 }; 106 107 static base::LazyInstance<ArchDefaultRegisterConfiguration, 108 RegisterConfigurationInitializer<CRANKSHAFT>>::type 109 kDefaultRegisterConfigurationForCrankshaft = LAZY_INSTANCE_INITIALIZER; 110 111 static base::LazyInstance<ArchDefaultRegisterConfiguration, 112 RegisterConfigurationInitializer<TURBOFAN>>::type 113 kDefaultRegisterConfigurationForTurboFan = LAZY_INSTANCE_INITIALIZER; 114 115 } // namespace 116 117 const RegisterConfiguration* RegisterConfiguration::Crankshaft() { 118 return &kDefaultRegisterConfigurationForCrankshaft.Get(); 119 } 120 121 const RegisterConfiguration* RegisterConfiguration::Turbofan() { 122 return &kDefaultRegisterConfigurationForTurboFan.Get(); 123 } 124 125 RegisterConfiguration::RegisterConfiguration( 126 int num_general_registers, int num_double_registers, 127 int num_allocatable_general_registers, int num_allocatable_double_registers, 128 const int* allocatable_general_codes, const int* allocatable_double_codes, 129 AliasingKind fp_aliasing_kind, const char* const* general_register_names, 130 const char* const* float_register_names, 131 const char* const* double_register_names) 132 : num_general_registers_(num_general_registers), 133 num_float_registers_(0), 134 num_double_registers_(num_double_registers), 135 num_allocatable_general_registers_(num_allocatable_general_registers), 136 num_allocatable_double_registers_(num_allocatable_double_registers), 137 num_allocatable_float_registers_(0), 138 allocatable_general_codes_mask_(0), 139 allocatable_double_codes_mask_(0), 140 allocatable_float_codes_mask_(0), 141 allocatable_general_codes_(allocatable_general_codes), 142 allocatable_double_codes_(allocatable_double_codes), 143 fp_aliasing_kind_(fp_aliasing_kind), 144 general_register_names_(general_register_names), 145 float_register_names_(float_register_names), 146 double_register_names_(double_register_names) { 147 DCHECK(num_general_registers_ <= RegisterConfiguration::kMaxGeneralRegisters); 148 DCHECK(num_double_registers_ <= RegisterConfiguration::kMaxFPRegisters); 149 for (int i = 0; i < num_allocatable_general_registers_; ++i) { 150 allocatable_general_codes_mask_ |= (1 << allocatable_general_codes_[i]); 151 } 152 for (int i = 0; i < num_allocatable_double_registers_; ++i) { 153 allocatable_double_codes_mask_ |= (1 << allocatable_double_codes_[i]); 154 } 155 156 if (fp_aliasing_kind_ == COMBINE) { 157 num_float_registers_ = num_double_registers_ * 2 <= kMaxFPRegisters 158 ? num_double_registers_ * 2 159 : kMaxFPRegisters; 160 num_allocatable_float_registers_ = 0; 161 for (int i = 0; i < num_allocatable_double_registers_; i++) { 162 int base_code = allocatable_double_codes_[i] * 2; 163 if (base_code >= kMaxFPRegisters) continue; 164 allocatable_float_codes_[num_allocatable_float_registers_++] = base_code; 165 allocatable_float_codes_[num_allocatable_float_registers_++] = 166 base_code + 1; 167 allocatable_float_codes_mask_ |= (0x3 << base_code); 168 } 169 } else { 170 DCHECK(fp_aliasing_kind_ == OVERLAP); 171 num_float_registers_ = num_double_registers_; 172 num_allocatable_float_registers_ = num_allocatable_double_registers_; 173 for (int i = 0; i < num_allocatable_float_registers_; ++i) { 174 allocatable_float_codes_[i] = allocatable_double_codes_[i]; 175 } 176 allocatable_float_codes_mask_ = allocatable_double_codes_mask_; 177 } 178 } 179 180 int RegisterConfiguration::GetAliases(MachineRepresentation rep, int index, 181 MachineRepresentation other_rep, 182 int* alias_base_index) const { 183 DCHECK(fp_aliasing_kind_ == COMBINE); 184 DCHECK(rep == MachineRepresentation::kFloat32 || 185 rep == MachineRepresentation::kFloat64); 186 DCHECK(other_rep == MachineRepresentation::kFloat32 || 187 other_rep == MachineRepresentation::kFloat64); 188 if (rep == other_rep) { 189 *alias_base_index = index; 190 return 1; 191 } 192 if (rep == MachineRepresentation::kFloat32) { 193 DCHECK(other_rep == MachineRepresentation::kFloat64); 194 DCHECK(index < num_allocatable_float_registers_); 195 *alias_base_index = index / 2; 196 return 1; 197 } 198 DCHECK(rep == MachineRepresentation::kFloat64); 199 DCHECK(other_rep == MachineRepresentation::kFloat32); 200 if (index * 2 >= kMaxFPRegisters) { 201 // Alias indices are out of float register range. 202 return 0; 203 } 204 *alias_base_index = index * 2; 205 return 2; 206 } 207 208 bool RegisterConfiguration::AreAliases(MachineRepresentation rep, int index, 209 MachineRepresentation other_rep, 210 int other_index) const { 211 DCHECK(fp_aliasing_kind_ == COMBINE); 212 DCHECK(rep == MachineRepresentation::kFloat32 || 213 rep == MachineRepresentation::kFloat64); 214 DCHECK(other_rep == MachineRepresentation::kFloat32 || 215 other_rep == MachineRepresentation::kFloat64); 216 if (rep == other_rep) { 217 return index == other_index; 218 } 219 if (rep == MachineRepresentation::kFloat32) { 220 DCHECK(other_rep == MachineRepresentation::kFloat64); 221 return index / 2 == other_index; 222 } 223 DCHECK(rep == MachineRepresentation::kFloat64); 224 DCHECK(other_rep == MachineRepresentation::kFloat32); 225 if (index * 2 >= kMaxFPRegisters) { 226 // Alias indices are out of float register range. 227 return false; 228 } 229 return index == other_index / 2; 230 } 231 232 #undef REGISTER_COUNT 233 234 } // namespace internal 235 } // namespace v8 236