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

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

Issue 1365073002: Revert of Remove register index/code indirection (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 3 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 // clang-format off 26 #define REGISTER_CODE_LIST(R) \
27 #define GENERAL_REGISTER_CODE_LIST(R) \ 27 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \
28 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ 28 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \
29 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \ 29 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \
30 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \ 30 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
31 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
32 31
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
56 32
57 static const int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte; 33 static const int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte;
58 34
59 35
60 // Some CPURegister methods can return Register and FPRegister types, so we 36 // Some CPURegister methods can return Register and FPRegister types, so we
61 // need to declare them in advance. 37 // need to declare them in advance.
62 struct Register; 38 struct Register;
63 struct FPRegister; 39 struct FPRegister;
64 40
65 41
66 struct CPURegister { 42 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
75 enum RegisterType { 43 enum RegisterType {
76 // The kInvalid value is used to detect uninitialized static instances, 44 // The kInvalid value is used to detect uninitialized static instances,
77 // which are always zero-initialized before any constructors are called. 45 // which are always zero-initialized before any constructors are called.
78 kInvalid = 0, 46 kInvalid = 0,
79 kRegister, 47 kRegister,
80 kFPRegister, 48 kFPRegister,
81 kNoRegister 49 kNoRegister
82 }; 50 };
83 51
84 static CPURegister Create(unsigned code, unsigned size, RegisterType type) { 52 static CPURegister Create(unsigned code, unsigned size, RegisterType type) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 DCHECK(IsValidOrNone()); 110 DCHECK(IsValidOrNone());
143 } 111 }
144 112
145 Register(const Register& r) { // NOLINT(runtime/explicit) 113 Register(const Register& r) { // NOLINT(runtime/explicit)
146 reg_code = r.reg_code; 114 reg_code = r.reg_code;
147 reg_size = r.reg_size; 115 reg_size = r.reg_size;
148 reg_type = r.reg_type; 116 reg_type = r.reg_type;
149 DCHECK(IsValidOrNone()); 117 DCHECK(IsValidOrNone());
150 } 118 }
151 119
152 const char* ToString();
153 bool IsAllocatable() const;
154 bool IsValid() const { 120 bool IsValid() const {
155 DCHECK(IsRegister() || IsNone()); 121 DCHECK(IsRegister() || IsNone());
156 return IsValidRegister(); 122 return IsValidRegister();
157 } 123 }
158 124
159 static Register XRegFromCode(unsigned code); 125 static Register XRegFromCode(unsigned code);
160 static Register WRegFromCode(unsigned code); 126 static Register WRegFromCode(unsigned code);
161 127
162 // Start of V8 compatibility section --------------------- 128 // Start of V8 compatibility section ---------------------
163 // These memebers are necessary for compilation. 129 // These memebers are necessary for compilation.
164 // A few of them may be unused for now. 130 // A few of them may be unused for now.
165 131
166 static const int kNumRegisters = kNumberOfRegisters; 132 static const int kNumRegisters = kNumberOfRegisters;
167 STATIC_ASSERT(kNumRegisters == Code::kAfterLast);
168 static int NumRegisters() { return kNumRegisters; } 133 static int NumRegisters() { return kNumRegisters; }
169 134
170 // We allow crankshaft to use the following registers: 135 // We allow crankshaft to use the following registers:
171 // - x0 to x15 136 // - x0 to x15
172 // - x18 to x24 137 // - x18 to x24
173 // - x27 (also context) 138 // - x27 (also context)
174 // 139 //
175 // TODO(all): Register x25 is currently free and could be available for 140 // TODO(all): Register x25 is currently free and could be available for
176 // crankshaft, but we don't use it as we might use it as a per function 141 // crankshaft, but we don't use it as we might use it as a per function
177 // literal pool pointer in the future. 142 // literal pool pointer in the future.
178 // 143 //
179 // TODO(all): Consider storing cp in x25 to have only two ranges. 144 // TODO(all): Consider storing cp in x25 to have only two ranges.
180 // We split allocatable registers in three ranges called 145 // We split allocatable registers in three ranges called
181 // - "low range" 146 // - "low range"
182 // - "high range" 147 // - "high range"
183 // - "context" 148 // - "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 }
184 213
185 static Register from_code(int code) { 214 static Register from_code(int code) {
186 // Always return an X register. 215 // Always return an X register.
187 return Register::Create(code, kXRegSizeInBits); 216 return Register::Create(code, kXRegSizeInBits);
188 } 217 }
189 218
190 // End of V8 compatibility section ----------------------- 219 // End of V8 compatibility section -----------------------
191 }; 220 };
192 221
193 222
194 struct FPRegister : public CPURegister { 223 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
203 static FPRegister Create(unsigned code, unsigned size) { 224 static FPRegister Create(unsigned code, unsigned size) {
204 return FPRegister( 225 return FPRegister(
205 CPURegister::Create(code, size, CPURegister::kFPRegister)); 226 CPURegister::Create(code, size, CPURegister::kFPRegister));
206 } 227 }
207 228
208 FPRegister() { 229 FPRegister() {
209 reg_code = 0; 230 reg_code = 0;
210 reg_size = 0; 231 reg_size = 0;
211 reg_type = CPURegister::kNoRegister; 232 reg_type = CPURegister::kNoRegister;
212 } 233 }
213 234
214 explicit FPRegister(const CPURegister& r) { 235 explicit FPRegister(const CPURegister& r) {
215 reg_code = r.reg_code; 236 reg_code = r.reg_code;
216 reg_size = r.reg_size; 237 reg_size = r.reg_size;
217 reg_type = r.reg_type; 238 reg_type = r.reg_type;
218 DCHECK(IsValidOrNone()); 239 DCHECK(IsValidOrNone());
219 } 240 }
220 241
221 FPRegister(const FPRegister& r) { // NOLINT(runtime/explicit) 242 FPRegister(const FPRegister& r) { // NOLINT(runtime/explicit)
222 reg_code = r.reg_code; 243 reg_code = r.reg_code;
223 reg_size = r.reg_size; 244 reg_size = r.reg_size;
224 reg_type = r.reg_type; 245 reg_type = r.reg_type;
225 DCHECK(IsValidOrNone()); 246 DCHECK(IsValidOrNone());
226 } 247 }
227 248
228 const char* ToString();
229 bool IsAllocatable() const;
230 bool IsValid() const { 249 bool IsValid() const {
231 DCHECK(IsFPRegister() || IsNone()); 250 DCHECK(IsFPRegister() || IsNone());
232 return IsValidFPRegister(); 251 return IsValidFPRegister();
233 } 252 }
234 253
235 static FPRegister SRegFromCode(unsigned code); 254 static FPRegister SRegFromCode(unsigned code);
236 static FPRegister DRegFromCode(unsigned code); 255 static FPRegister DRegFromCode(unsigned code);
237 256
238 // Start of V8 compatibility section --------------------- 257 // Start of V8 compatibility section ---------------------
239 static const int kMaxNumRegisters = kNumberOfFPRegisters; 258 static const int kMaxNumRegisters = kNumberOfFPRegisters;
240 STATIC_ASSERT(kMaxNumRegisters == Code::kAfterLast);
241 259
242 // Crankshaft can use all the FP registers except: 260 // Crankshaft can use all the FP registers except:
243 // - d15 which is used to keep the 0 double value 261 // - d15 which is used to keep the 0 double value
244 // - d30 which is used in crankshaft as a double scratch register 262 // - d30 which is used in crankshaft as a double scratch register
245 // - d31 which is used in the MacroAssembler as a double scratch register 263 // - 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
246 static FPRegister from_code(int code) { 322 static FPRegister from_code(int code) {
247 // Always return a D register. 323 // Always return a D register.
248 return FPRegister::Create(code, kDRegSizeInBits); 324 return FPRegister::Create(code, kDRegSizeInBits);
249 } 325 }
250 // End of V8 compatibility section ----------------------- 326 // End of V8 compatibility section -----------------------
251 }; 327 };
252 328
253 329
254 STATIC_ASSERT(sizeof(CPURegister) == sizeof(Register)); 330 STATIC_ASSERT(sizeof(CPURegister) == sizeof(Register));
255 STATIC_ASSERT(sizeof(CPURegister) == sizeof(FPRegister)); 331 STATIC_ASSERT(sizeof(CPURegister) == sizeof(FPRegister));
(...skipping 22 matching lines...) Expand all
278 INITIALIZE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister); 354 INITIALIZE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister);
279 355
280 // v8 compatibility. 356 // v8 compatibility.
281 INITIALIZE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister); 357 INITIALIZE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister);
282 358
283 #define DEFINE_REGISTERS(N) \ 359 #define DEFINE_REGISTERS(N) \
284 INITIALIZE_REGISTER(Register, w##N, N, \ 360 INITIALIZE_REGISTER(Register, w##N, N, \
285 kWRegSizeInBits, CPURegister::kRegister); \ 361 kWRegSizeInBits, CPURegister::kRegister); \
286 INITIALIZE_REGISTER(Register, x##N, N, \ 362 INITIALIZE_REGISTER(Register, x##N, N, \
287 kXRegSizeInBits, CPURegister::kRegister); 363 kXRegSizeInBits, CPURegister::kRegister);
288 GENERAL_REGISTER_CODE_LIST(DEFINE_REGISTERS) 364 REGISTER_CODE_LIST(DEFINE_REGISTERS)
289 #undef DEFINE_REGISTERS 365 #undef DEFINE_REGISTERS
290 366
291 INITIALIZE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits, 367 INITIALIZE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits,
292 CPURegister::kRegister); 368 CPURegister::kRegister);
293 INITIALIZE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits, 369 INITIALIZE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits,
294 CPURegister::kRegister); 370 CPURegister::kRegister);
295 371
296 #define DEFINE_FPREGISTERS(N) \ 372 #define DEFINE_FPREGISTERS(N) \
297 INITIALIZE_REGISTER(FPRegister, s##N, N, \ 373 INITIALIZE_REGISTER(FPRegister, s##N, N, \
298 kSRegSizeInBits, CPURegister::kFPRegister); \ 374 kSRegSizeInBits, CPURegister::kFPRegister); \
299 INITIALIZE_REGISTER(FPRegister, d##N, N, \ 375 INITIALIZE_REGISTER(FPRegister, d##N, N, \
300 kDRegSizeInBits, CPURegister::kFPRegister); 376 kDRegSizeInBits, CPURegister::kFPRegister);
301 GENERAL_REGISTER_CODE_LIST(DEFINE_FPREGISTERS) 377 REGISTER_CODE_LIST(DEFINE_FPREGISTERS)
302 #undef DEFINE_FPREGISTERS 378 #undef DEFINE_FPREGISTERS
303 379
304 #undef INITIALIZE_REGISTER 380 #undef INITIALIZE_REGISTER
305 381
306 // Registers aliases. 382 // Registers aliases.
307 ALIAS_REGISTER(Register, ip0, x16); 383 ALIAS_REGISTER(Register, ip0, x16);
308 ALIAS_REGISTER(Register, ip1, x17); 384 ALIAS_REGISTER(Register, ip1, x17);
309 ALIAS_REGISTER(Register, wip0, w16); 385 ALIAS_REGISTER(Register, wip0, w16);
310 ALIAS_REGISTER(Register, wip1, w17); 386 ALIAS_REGISTER(Register, wip1, w17);
311 // Root register. 387 // Root register.
(...skipping 1904 matching lines...) Expand 10 before | Expand all | Expand 10 after
2216 class EnsureSpace BASE_EMBEDDED { 2292 class EnsureSpace BASE_EMBEDDED {
2217 public: 2293 public:
2218 explicit EnsureSpace(Assembler* assembler) { 2294 explicit EnsureSpace(Assembler* assembler) {
2219 assembler->CheckBufferSpace(); 2295 assembler->CheckBufferSpace();
2220 } 2296 }
2221 }; 2297 };
2222 2298
2223 } } // namespace v8::internal 2299 } } // namespace v8::internal
2224 2300
2225 #endif // V8_ARM64_ASSEMBLER_ARM64_H_ 2301 #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