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:
ArchDefaultRegisterConfiguration(CompilerSelector compiler)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 {
Constructv8::internal::__anon464ea5840111::RegisterConfigurationInitializer102 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
Crankshaft()117 const RegisterConfiguration* RegisterConfiguration::Crankshaft() {
118 return &kDefaultRegisterConfigurationForCrankshaft.Get();
119 }
120
Turbofan()121 const RegisterConfiguration* RegisterConfiguration::Turbofan() {
122 return &kDefaultRegisterConfigurationForTurboFan.Get();
123 }
124
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)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
GetAliases(MachineRepresentation rep,int index,MachineRepresentation other_rep,int * alias_base_index) const180 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
AreAliases(MachineRepresentation rep,int index,MachineRepresentation other_rep,int other_index) const208 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