Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(499)

Side by Side Diff: src/arm64/assembler-arm64.h

Issue 1287383003: Re-reland: Remove register index/code indirection (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix MIPS tests again Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/arm/simulator-arm.cc ('k') | src/arm64/assembler-arm64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_ARM64_ASSEMBLER_ARM64_H_ 5 #ifndef V8_ARM64_ASSEMBLER_ARM64_H_
6 #define V8_ARM64_ASSEMBLER_ARM64_H_ 6 #define V8_ARM64_ASSEMBLER_ARM64_H_
7 7
8 #include <deque> 8 #include <deque>
9 #include <list> 9 #include <list>
10 #include <map> 10 #include <map>
11 #include <vector> 11 #include <vector>
12 12
13 #include "src/arm64/instructions-arm64.h" 13 #include "src/arm64/instructions-arm64.h"
14 #include "src/assembler.h" 14 #include "src/assembler.h"
15 #include "src/compiler.h" 15 #include "src/compiler.h"
16 #include "src/globals.h" 16 #include "src/globals.h"
17 #include "src/utils.h" 17 #include "src/utils.h"
18 18
19 19
20 namespace v8 { 20 namespace v8 {
21 namespace internal { 21 namespace internal {
22 22
23 23
24 // ----------------------------------------------------------------------------- 24 // -----------------------------------------------------------------------------
25 // Registers. 25 // Registers.
26 #define REGISTER_CODE_LIST(R) \ 26 // clang-format off
27 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ 27 #define GENERAL_REGISTER_CODE_LIST(R) \
28 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \ 28 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \
29 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \ 29 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \
30 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31) 30 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \
31 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
31 32
33 #define GENERAL_REGISTERS(R) \
34 R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \
35 R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
36 R(x16) R(x17) R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) \
37 R(x24) R(x25) R(x26) R(x27) R(x28) R(x29) R(x30) R(x31)
38
39 #define ALLOCATABLE_GENERAL_REGISTERS(R) \
40 R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \
41 R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
42 R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x27)
43
44 #define DOUBLE_REGISTERS(R) \
45 R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \
46 R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d15) \
47 R(d16) R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) \
48 R(d24) R(d25) R(d26) R(d27) R(d28) R(d29) R(d30) R(d31)
49
50 #define ALLOCATABLE_DOUBLE_REGISTERS(R) \
51 R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \
52 R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d16) \
53 R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) R(d24) \
54 R(d25) R(d26) R(d27) R(d28)
55 // clang-format on
32 56
33 static const int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte; 57 static const int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte;
34 58
35 59
36 // Some CPURegister methods can return Register and FPRegister types, so we 60 // Some CPURegister methods can return Register and FPRegister types, so we
37 // need to declare them in advance. 61 // need to declare them in advance.
38 struct Register; 62 struct Register;
39 struct FPRegister; 63 struct FPRegister;
40 64
41 65
42 struct CPURegister { 66 struct CPURegister {
67 enum Code {
68 #define REGISTER_CODE(R) kCode_##R,
69 GENERAL_REGISTERS(REGISTER_CODE)
70 #undef REGISTER_CODE
71 kAfterLast,
72 kCode_no_reg = -1
73 };
74
43 enum RegisterType { 75 enum RegisterType {
44 // The kInvalid value is used to detect uninitialized static instances, 76 // The kInvalid value is used to detect uninitialized static instances,
45 // which are always zero-initialized before any constructors are called. 77 // which are always zero-initialized before any constructors are called.
46 kInvalid = 0, 78 kInvalid = 0,
47 kRegister, 79 kRegister,
48 kFPRegister, 80 kFPRegister,
49 kNoRegister 81 kNoRegister
50 }; 82 };
51 83
52 static CPURegister Create(unsigned code, unsigned size, RegisterType type) { 84 static CPURegister Create(unsigned code, unsigned size, RegisterType type) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 DCHECK(IsValidOrNone()); 142 DCHECK(IsValidOrNone());
111 } 143 }
112 144
113 Register(const Register& r) { // NOLINT(runtime/explicit) 145 Register(const Register& r) { // NOLINT(runtime/explicit)
114 reg_code = r.reg_code; 146 reg_code = r.reg_code;
115 reg_size = r.reg_size; 147 reg_size = r.reg_size;
116 reg_type = r.reg_type; 148 reg_type = r.reg_type;
117 DCHECK(IsValidOrNone()); 149 DCHECK(IsValidOrNone());
118 } 150 }
119 151
152 const char* ToString();
153 bool IsAllocatable() const;
120 bool IsValid() const { 154 bool IsValid() const {
121 DCHECK(IsRegister() || IsNone()); 155 DCHECK(IsRegister() || IsNone());
122 return IsValidRegister(); 156 return IsValidRegister();
123 } 157 }
124 158
125 static Register XRegFromCode(unsigned code); 159 static Register XRegFromCode(unsigned code);
126 static Register WRegFromCode(unsigned code); 160 static Register WRegFromCode(unsigned code);
127 161
128 // Start of V8 compatibility section --------------------- 162 // Start of V8 compatibility section ---------------------
129 // These memebers are necessary for compilation. 163 // These memebers are necessary for compilation.
130 // A few of them may be unused for now. 164 // A few of them may be unused for now.
131 165
132 static const int kNumRegisters = kNumberOfRegisters; 166 static const int kNumRegisters = kNumberOfRegisters;
167 STATIC_ASSERT(kNumRegisters == Code::kAfterLast);
133 static int NumRegisters() { return kNumRegisters; } 168 static int NumRegisters() { return kNumRegisters; }
134 169
135 // We allow crankshaft to use the following registers: 170 // We allow crankshaft to use the following registers:
136 // - x0 to x15 171 // - x0 to x15
137 // - x18 to x24 172 // - x18 to x24
138 // - x27 (also context) 173 // - x27 (also context)
139 // 174 //
140 // TODO(all): Register x25 is currently free and could be available for 175 // TODO(all): Register x25 is currently free and could be available for
141 // crankshaft, but we don't use it as we might use it as a per function 176 // crankshaft, but we don't use it as we might use it as a per function
142 // literal pool pointer in the future. 177 // literal pool pointer in the future.
143 // 178 //
144 // TODO(all): Consider storing cp in x25 to have only two ranges. 179 // TODO(all): Consider storing cp in x25 to have only two ranges.
145 // We split allocatable registers in three ranges called 180 // We split allocatable registers in three ranges called
146 // - "low range" 181 // - "low range"
147 // - "high range" 182 // - "high range"
148 // - "context" 183 // - "context"
149 static const unsigned kAllocatableLowRangeBegin = 0;
150 static const unsigned kAllocatableLowRangeEnd = 15;
151 static const unsigned kAllocatableHighRangeBegin = 18;
152 static const unsigned kAllocatableHighRangeEnd = 24;
153 static const unsigned kAllocatableContext = 27;
154
155 // Gap between low and high ranges.
156 static const int kAllocatableRangeGapSize =
157 (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1;
158
159 static const int kMaxNumAllocatableRegisters =
160 (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) +
161 (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1) + 1; // cp
162 static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
163
164 // Return true if the register is one that crankshaft can allocate.
165 bool IsAllocatable() const {
166 return ((reg_code == kAllocatableContext) ||
167 (reg_code <= kAllocatableLowRangeEnd) ||
168 ((reg_code >= kAllocatableHighRangeBegin) &&
169 (reg_code <= kAllocatableHighRangeEnd)));
170 }
171
172 static Register FromAllocationIndex(unsigned index) {
173 DCHECK(index < static_cast<unsigned>(NumAllocatableRegisters()));
174 // cp is the last allocatable register.
175 if (index == (static_cast<unsigned>(NumAllocatableRegisters() - 1))) {
176 return from_code(kAllocatableContext);
177 }
178
179 // Handle low and high ranges.
180 return (index <= kAllocatableLowRangeEnd)
181 ? from_code(index)
182 : from_code(index + kAllocatableRangeGapSize);
183 }
184
185 static const char* AllocationIndexToString(int index) {
186 DCHECK((index >= 0) && (index < NumAllocatableRegisters()));
187 DCHECK((kAllocatableLowRangeBegin == 0) &&
188 (kAllocatableLowRangeEnd == 15) &&
189 (kAllocatableHighRangeBegin == 18) &&
190 (kAllocatableHighRangeEnd == 24) &&
191 (kAllocatableContext == 27));
192 const char* const names[] = {
193 "x0", "x1", "x2", "x3", "x4",
194 "x5", "x6", "x7", "x8", "x9",
195 "x10", "x11", "x12", "x13", "x14",
196 "x15", "x18", "x19", "x20", "x21",
197 "x22", "x23", "x24", "x27",
198 };
199 return names[index];
200 }
201
202 static int ToAllocationIndex(Register reg) {
203 DCHECK(reg.IsAllocatable());
204 unsigned code = reg.code();
205 if (code == kAllocatableContext) {
206 return NumAllocatableRegisters() - 1;
207 }
208
209 return (code <= kAllocatableLowRangeEnd)
210 ? code
211 : code - kAllocatableRangeGapSize;
212 }
213 184
214 static Register from_code(int code) { 185 static Register from_code(int code) {
215 // Always return an X register. 186 // Always return an X register.
216 return Register::Create(code, kXRegSizeInBits); 187 return Register::Create(code, kXRegSizeInBits);
217 } 188 }
218 189
219 // End of V8 compatibility section ----------------------- 190 // End of V8 compatibility section -----------------------
220 }; 191 };
221 192
222 193
223 struct FPRegister : public CPURegister { 194 struct FPRegister : public CPURegister {
195 enum Code {
196 #define REGISTER_CODE(R) kCode_##R,
197 DOUBLE_REGISTERS(REGISTER_CODE)
198 #undef REGISTER_CODE
199 kAfterLast,
200 kCode_no_reg = -1
201 };
202
224 static FPRegister Create(unsigned code, unsigned size) { 203 static FPRegister Create(unsigned code, unsigned size) {
225 return FPRegister( 204 return FPRegister(
226 CPURegister::Create(code, size, CPURegister::kFPRegister)); 205 CPURegister::Create(code, size, CPURegister::kFPRegister));
227 } 206 }
228 207
229 FPRegister() { 208 FPRegister() {
230 reg_code = 0; 209 reg_code = 0;
231 reg_size = 0; 210 reg_size = 0;
232 reg_type = CPURegister::kNoRegister; 211 reg_type = CPURegister::kNoRegister;
233 } 212 }
234 213
235 explicit FPRegister(const CPURegister& r) { 214 explicit FPRegister(const CPURegister& r) {
236 reg_code = r.reg_code; 215 reg_code = r.reg_code;
237 reg_size = r.reg_size; 216 reg_size = r.reg_size;
238 reg_type = r.reg_type; 217 reg_type = r.reg_type;
239 DCHECK(IsValidOrNone()); 218 DCHECK(IsValidOrNone());
240 } 219 }
241 220
242 FPRegister(const FPRegister& r) { // NOLINT(runtime/explicit) 221 FPRegister(const FPRegister& r) { // NOLINT(runtime/explicit)
243 reg_code = r.reg_code; 222 reg_code = r.reg_code;
244 reg_size = r.reg_size; 223 reg_size = r.reg_size;
245 reg_type = r.reg_type; 224 reg_type = r.reg_type;
246 DCHECK(IsValidOrNone()); 225 DCHECK(IsValidOrNone());
247 } 226 }
248 227
228 const char* ToString();
229 bool IsAllocatable() const;
249 bool IsValid() const { 230 bool IsValid() const {
250 DCHECK(IsFPRegister() || IsNone()); 231 DCHECK(IsFPRegister() || IsNone());
251 return IsValidFPRegister(); 232 return IsValidFPRegister();
252 } 233 }
253 234
254 static FPRegister SRegFromCode(unsigned code); 235 static FPRegister SRegFromCode(unsigned code);
255 static FPRegister DRegFromCode(unsigned code); 236 static FPRegister DRegFromCode(unsigned code);
256 237
257 // Start of V8 compatibility section --------------------- 238 // Start of V8 compatibility section ---------------------
258 static const int kMaxNumRegisters = kNumberOfFPRegisters; 239 static const int kMaxNumRegisters = kNumberOfFPRegisters;
240 STATIC_ASSERT(kMaxNumRegisters == Code::kAfterLast);
259 241
260 // Crankshaft can use all the FP registers except: 242 // Crankshaft can use all the FP registers except:
261 // - d15 which is used to keep the 0 double value 243 // - d15 which is used to keep the 0 double value
262 // - d30 which is used in crankshaft as a double scratch register 244 // - d30 which is used in crankshaft as a double scratch register
263 // - d31 which is used in the MacroAssembler as a double scratch register 245 // - d31 which is used in the MacroAssembler as a double scratch register
264 static const unsigned kAllocatableLowRangeBegin = 0;
265 static const unsigned kAllocatableLowRangeEnd = 14;
266 static const unsigned kAllocatableHighRangeBegin = 16;
267 static const unsigned kAllocatableHighRangeEnd = 28;
268
269 static const RegList kAllocatableFPRegisters = 0x1fff7fff;
270
271 // Gap between low and high ranges.
272 static const int kAllocatableRangeGapSize =
273 (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1;
274
275 static const int kMaxNumAllocatableRegisters =
276 (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) +
277 (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1);
278 static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
279
280 // TODO(turbofan): Proper float32 support.
281 static int NumAllocatableAliasedRegisters() {
282 return NumAllocatableRegisters();
283 }
284
285 // Return true if the register is one that crankshaft can allocate.
286 bool IsAllocatable() const {
287 return (Bit() & kAllocatableFPRegisters) != 0;
288 }
289
290 static FPRegister FromAllocationIndex(unsigned int index) {
291 DCHECK(index < static_cast<unsigned>(NumAllocatableRegisters()));
292
293 return (index <= kAllocatableLowRangeEnd)
294 ? from_code(index)
295 : from_code(index + kAllocatableRangeGapSize);
296 }
297
298 static const char* AllocationIndexToString(int index) {
299 DCHECK((index >= 0) && (index < NumAllocatableRegisters()));
300 DCHECK((kAllocatableLowRangeBegin == 0) &&
301 (kAllocatableLowRangeEnd == 14) &&
302 (kAllocatableHighRangeBegin == 16) &&
303 (kAllocatableHighRangeEnd == 28));
304 const char* const names[] = {
305 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
306 "d8", "d9", "d10", "d11", "d12", "d13", "d14",
307 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
308 "d24", "d25", "d26", "d27", "d28"
309 };
310 return names[index];
311 }
312
313 static int ToAllocationIndex(FPRegister reg) {
314 DCHECK(reg.IsAllocatable());
315 unsigned code = reg.code();
316
317 return (code <= kAllocatableLowRangeEnd)
318 ? code
319 : code - kAllocatableRangeGapSize;
320 }
321
322 static FPRegister from_code(int code) { 246 static FPRegister from_code(int code) {
323 // Always return a D register. 247 // Always return a D register.
324 return FPRegister::Create(code, kDRegSizeInBits); 248 return FPRegister::Create(code, kDRegSizeInBits);
325 } 249 }
326 // End of V8 compatibility section ----------------------- 250 // End of V8 compatibility section -----------------------
327 }; 251 };
328 252
329 253
330 STATIC_ASSERT(sizeof(CPURegister) == sizeof(Register)); 254 STATIC_ASSERT(sizeof(CPURegister) == sizeof(Register));
331 STATIC_ASSERT(sizeof(CPURegister) == sizeof(FPRegister)); 255 STATIC_ASSERT(sizeof(CPURegister) == sizeof(FPRegister));
(...skipping 22 matching lines...) Expand all
354 INITIALIZE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister); 278 INITIALIZE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister);
355 279
356 // v8 compatibility. 280 // v8 compatibility.
357 INITIALIZE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister); 281 INITIALIZE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister);
358 282
359 #define DEFINE_REGISTERS(N) \ 283 #define DEFINE_REGISTERS(N) \
360 INITIALIZE_REGISTER(Register, w##N, N, \ 284 INITIALIZE_REGISTER(Register, w##N, N, \
361 kWRegSizeInBits, CPURegister::kRegister); \ 285 kWRegSizeInBits, CPURegister::kRegister); \
362 INITIALIZE_REGISTER(Register, x##N, N, \ 286 INITIALIZE_REGISTER(Register, x##N, N, \
363 kXRegSizeInBits, CPURegister::kRegister); 287 kXRegSizeInBits, CPURegister::kRegister);
364 REGISTER_CODE_LIST(DEFINE_REGISTERS) 288 GENERAL_REGISTER_CODE_LIST(DEFINE_REGISTERS)
365 #undef DEFINE_REGISTERS 289 #undef DEFINE_REGISTERS
366 290
367 INITIALIZE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits, 291 INITIALIZE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits,
368 CPURegister::kRegister); 292 CPURegister::kRegister);
369 INITIALIZE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits, 293 INITIALIZE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits,
370 CPURegister::kRegister); 294 CPURegister::kRegister);
371 295
372 #define DEFINE_FPREGISTERS(N) \ 296 #define DEFINE_FPREGISTERS(N) \
373 INITIALIZE_REGISTER(FPRegister, s##N, N, \ 297 INITIALIZE_REGISTER(FPRegister, s##N, N, \
374 kSRegSizeInBits, CPURegister::kFPRegister); \ 298 kSRegSizeInBits, CPURegister::kFPRegister); \
375 INITIALIZE_REGISTER(FPRegister, d##N, N, \ 299 INITIALIZE_REGISTER(FPRegister, d##N, N, \
376 kDRegSizeInBits, CPURegister::kFPRegister); 300 kDRegSizeInBits, CPURegister::kFPRegister);
377 REGISTER_CODE_LIST(DEFINE_FPREGISTERS) 301 GENERAL_REGISTER_CODE_LIST(DEFINE_FPREGISTERS)
378 #undef DEFINE_FPREGISTERS 302 #undef DEFINE_FPREGISTERS
379 303
380 #undef INITIALIZE_REGISTER 304 #undef INITIALIZE_REGISTER
381 305
382 // Registers aliases. 306 // Registers aliases.
383 ALIAS_REGISTER(Register, ip0, x16); 307 ALIAS_REGISTER(Register, ip0, x16);
384 ALIAS_REGISTER(Register, ip1, x17); 308 ALIAS_REGISTER(Register, ip1, x17);
385 ALIAS_REGISTER(Register, wip0, w16); 309 ALIAS_REGISTER(Register, wip0, w16);
386 ALIAS_REGISTER(Register, wip1, w17); 310 ALIAS_REGISTER(Register, wip1, w17);
387 // Root register. 311 // Root register.
(...skipping 1905 matching lines...) Expand 10 before | Expand all | Expand 10 after
2293 public: 2217 public:
2294 explicit EnsureSpace(Assembler* assembler) { 2218 explicit EnsureSpace(Assembler* assembler) {
2295 assembler->CheckBufferSpace(); 2219 assembler->CheckBufferSpace();
2296 } 2220 }
2297 }; 2221 };
2298 2222
2299 } // namespace internal 2223 } // namespace internal
2300 } // namespace v8 2224 } // namespace v8
2301 2225
2302 #endif // V8_ARM64_ASSEMBLER_ARM64_H_ 2226 #endif // V8_ARM64_ASSEMBLER_ARM64_H_
OLDNEW
« no previous file with comments | « src/arm/simulator-arm.cc ('k') | src/arm64/assembler-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698