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:
ArchDefaultRegisterConfiguration(CompilerSelector compiler)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 {
Constructv8::internal::__anonf84f25400111::RegisterConfigurationInitializer113 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
Crankshaft()128 const RegisterConfiguration* RegisterConfiguration::Crankshaft() {
129 return &kDefaultRegisterConfigurationForCrankshaft.Get();
130 }
131
Turbofan()132 const RegisterConfiguration* RegisterConfiguration::Turbofan() {
133 return &kDefaultRegisterConfigurationForTurboFan.Get();
134 }
135
RegisterConfiguration(int num_general_registers,int num_double_registers,int num_allocatable_general_registers,int num_allocatable_double_registers,const int * allocatable_general_codes,const int * allocatable_double_codes,AliasingKind fp_aliasing_kind,const char * const * general_register_names,const char * const * float_register_names,const char * const * double_register_names,const char * const * simd128_register_names)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
GetAliases(MachineRepresentation rep,int index,MachineRepresentation other_rep,int * alias_base_index) const219 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
AreAliases(MachineRepresentation rep,int index,MachineRepresentation other_rep,int other_index) const245 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