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

Side by Side Diff: src/arm/assembler-arm.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 | « BUILD.gn ('k') | src/arm/assembler-arm.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 (c) 1994-2006 Sun Microsystems Inc. 1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved. 2 // All Rights Reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions 5 // modification, are permitted provided that the following conditions
6 // are met: 6 // are met:
7 // 7 //
8 // - Redistributions of source code must retain the above copyright notice, 8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer. 9 // this list of conditions and the following disclaimer.
10 // 10 //
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 #include <stdio.h> 43 #include <stdio.h>
44 #include <vector> 44 #include <vector>
45 45
46 #include "src/arm/constants-arm.h" 46 #include "src/arm/constants-arm.h"
47 #include "src/assembler.h" 47 #include "src/assembler.h"
48 #include "src/compiler.h" 48 #include "src/compiler.h"
49 49
50 namespace v8 { 50 namespace v8 {
51 namespace internal { 51 namespace internal {
52 52
53 // clang-format off
54 #define GENERAL_REGISTERS(V) \
55 V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \
56 V(r8) V(r9) V(r10) V(fp) V(ip) V(sp) V(lr) V(pc)
57
58 #define ALLOCATABLE_GENERAL_REGISTERS(V) \
59 V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) V(r8)
60
61 #define DOUBLE_REGISTERS(V) \
62 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
63 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) \
64 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
65 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
66
67 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \
68 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
69 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) \
70 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
71 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
72
73 #define ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(V) \
74 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
75 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) \
76 // clang-format on
77
78 // CPU Registers. 53 // CPU Registers.
79 // 54 //
80 // 1) We would prefer to use an enum, but enum values are assignment- 55 // 1) We would prefer to use an enum, but enum values are assignment-
81 // compatible with int, which has caused code-generation bugs. 56 // compatible with int, which has caused code-generation bugs.
82 // 57 //
83 // 2) We would prefer to use a class instead of a struct but we don't like 58 // 2) We would prefer to use a class instead of a struct but we don't like
84 // the register initialization to depend on the particular initialization 59 // the register initialization to depend on the particular initialization
85 // order (which appears to be different on OS X, Linux, and Windows for the 60 // order (which appears to be different on OS X, Linux, and Windows for the
86 // installed versions of C++ we tried). Using a struct permits C-style 61 // installed versions of C++ we tried). Using a struct permits C-style
87 // "initialization". Also, the Register objects cannot be const as this 62 // "initialization". Also, the Register objects cannot be const as this
88 // forces initialization stubs in MSVC, making us dependent on initialization 63 // forces initialization stubs in MSVC, making us dependent on initialization
89 // order. 64 // order.
90 // 65 //
91 // 3) By not using an enum, we are possibly preventing the compiler from 66 // 3) By not using an enum, we are possibly preventing the compiler from
92 // doing certain constant folds, which may significantly reduce the 67 // doing certain constant folds, which may significantly reduce the
93 // code generated for some assembly instructions (because they boil down 68 // code generated for some assembly instructions (because they boil down
94 // to a few constants). If this is a problem, we could change the code 69 // to a few constants). If this is a problem, we could change the code
95 // such that we use an enum in optimized mode, and the struct in debug 70 // such that we use an enum in optimized mode, and the struct in debug
96 // mode. This way we get the compile-time error checking in debug mode 71 // mode. This way we get the compile-time error checking in debug mode
97 // and best performance in optimized code. 72 // and best performance in optimized code.
98 73
74 // These constants are used in several locations, including static initializers
75 const int kRegister_no_reg_Code = -1;
76 const int kRegister_r0_Code = 0;
77 const int kRegister_r1_Code = 1;
78 const int kRegister_r2_Code = 2;
79 const int kRegister_r3_Code = 3;
80 const int kRegister_r4_Code = 4;
81 const int kRegister_r5_Code = 5;
82 const int kRegister_r6_Code = 6;
83 const int kRegister_r7_Code = 7;
84 const int kRegister_r8_Code = 8;
85 const int kRegister_r9_Code = 9;
86 const int kRegister_r10_Code = 10;
87 const int kRegister_fp_Code = 11;
88 const int kRegister_ip_Code = 12;
89 const int kRegister_sp_Code = 13;
90 const int kRegister_lr_Code = 14;
91 const int kRegister_pc_Code = 15;
92
93 // Core register
99 struct Register { 94 struct Register {
100 enum Code { 95 static const int kNumRegisters = 16;
101 #define REGISTER_CODE(R) kCode_##R, 96 static const int kMaxNumAllocatableRegisters =
102 GENERAL_REGISTERS(REGISTER_CODE) 97 FLAG_enable_embedded_constant_pool ? 8 : 9;
103 #undef REGISTER_CODE 98 static const int kSizeInBytes = 4;
104 kAfterLast,
105 kCode_no_reg = -1
106 };
107 99
108 static const int kNumRegisters = Code::kAfterLast; 100 inline static int NumAllocatableRegisters();
101
102 static int ToAllocationIndex(Register reg) {
103 DCHECK(reg.code() < kMaxNumAllocatableRegisters);
104 return reg.code();
105 }
106
107 static Register FromAllocationIndex(int index) {
108 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
109 return from_code(index);
110 }
111
112 static const char* AllocationIndexToString(int index) {
113 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
114 const char* const names[] = {
115 "r0",
116 "r1",
117 "r2",
118 "r3",
119 "r4",
120 "r5",
121 "r6",
122 "r7",
123 "r8",
124 };
125 if (FLAG_enable_embedded_constant_pool && (index >= 7)) {
126 return names[index + 1];
127 }
128 return names[index];
129 }
109 130
110 static Register from_code(int code) { 131 static Register from_code(int code) {
111 DCHECK(code >= 0); 132 Register r = { code };
112 DCHECK(code < kNumRegisters);
113 Register r = {code};
114 return r; 133 return r;
115 } 134 }
116 const char* ToString(); 135
117 bool IsAllocatable() const; 136 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
118 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } 137 bool is(Register reg) const { return code_ == reg.code_; }
119 bool is(Register reg) const { return reg_code == reg.reg_code; }
120 int code() const { 138 int code() const {
121 DCHECK(is_valid()); 139 DCHECK(is_valid());
122 return reg_code; 140 return code_;
123 } 141 }
124 int bit() const { 142 int bit() const {
125 DCHECK(is_valid()); 143 DCHECK(is_valid());
126 return 1 << reg_code; 144 return 1 << code_;
127 } 145 }
146
128 void set_code(int code) { 147 void set_code(int code) {
129 reg_code = code; 148 code_ = code;
130 DCHECK(is_valid()); 149 DCHECK(is_valid());
131 } 150 }
132 151
133 // Unfortunately we can't make this private in a struct. 152 // Unfortunately we can't make this private in a struct.
134 int reg_code; 153 int code_;
135 }; 154 };
136 155
137 // r7: context register 156 const Register no_reg = { kRegister_no_reg_Code };
138 // r8: constant pool pointer register if FLAG_enable_embedded_constant_pool. 157
139 // r9: lithium scratch 158 const Register r0 = { kRegister_r0_Code };
140 #define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R}; 159 const Register r1 = { kRegister_r1_Code };
141 GENERAL_REGISTERS(DECLARE_REGISTER) 160 const Register r2 = { kRegister_r2_Code };
142 #undef DECLARE_REGISTER 161 const Register r3 = { kRegister_r3_Code };
143 const Register no_reg = {Register::kCode_no_reg}; 162 const Register r4 = { kRegister_r4_Code };
163 const Register r5 = { kRegister_r5_Code };
164 const Register r6 = { kRegister_r6_Code };
165 // Used as context register.
166 const Register r7 = {kRegister_r7_Code};
167 // Used as constant pool pointer register if FLAG_enable_embedded_constant_pool.
168 const Register r8 = { kRegister_r8_Code };
169 // Used as lithium codegen scratch register.
170 const Register r9 = { kRegister_r9_Code };
171 // Used as roots register.
172 const Register r10 = { kRegister_r10_Code };
173 const Register fp = { kRegister_fp_Code };
174 const Register ip = { kRegister_ip_Code };
175 const Register sp = { kRegister_sp_Code };
176 const Register lr = { kRegister_lr_Code };
177 const Register pc = { kRegister_pc_Code };
144 178
145 // Single word VFP register. 179 // Single word VFP register.
146 struct SwVfpRegister { 180 struct SwVfpRegister {
147 static const int kSizeInBytes = 4; 181 static const int kSizeInBytes = 4;
148 bool is_valid() const { return 0 <= reg_code && reg_code < 32; } 182 bool is_valid() const { return 0 <= code_ && code_ < 32; }
149 bool is(SwVfpRegister reg) const { return reg_code == reg.reg_code; } 183 bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
150 int code() const { 184 int code() const {
151 DCHECK(is_valid()); 185 DCHECK(is_valid());
152 return reg_code; 186 return code_;
153 } 187 }
154 int bit() const { 188 int bit() const {
155 DCHECK(is_valid()); 189 DCHECK(is_valid());
156 return 1 << reg_code; 190 return 1 << code_;
157 } 191 }
158 void split_code(int* vm, int* m) const { 192 void split_code(int* vm, int* m) const {
159 DCHECK(is_valid()); 193 DCHECK(is_valid());
160 *m = reg_code & 0x1; 194 *m = code_ & 0x1;
161 *vm = reg_code >> 1; 195 *vm = code_ >> 1;
162 } 196 }
163 197
164 int reg_code; 198 int code_;
165 }; 199 };
166 200
167 201
168 // Double word VFP register. 202 // Double word VFP register.
169 struct DoubleRegister { 203 struct DwVfpRegister {
170 enum Code { 204 static const int kMaxNumRegisters = 32;
171 #define REGISTER_CODE(R) kCode_##R,
172 DOUBLE_REGISTERS(REGISTER_CODE)
173 #undef REGISTER_CODE
174 kAfterLast,
175 kCode_no_reg = -1
176 };
177
178 static const int kMaxNumRegisters = Code::kAfterLast;
179
180 inline static int NumRegisters();
181
182 // A few double registers are reserved: one as a scratch register and one to 205 // A few double registers are reserved: one as a scratch register and one to
183 // hold 0.0, that does not fit in the immediate field of vmov instructions. 206 // hold 0.0, that does not fit in the immediate field of vmov instructions.
184 // d14: 0.0 207 // d14: 0.0
185 // d15: scratch register. 208 // d15: scratch register.
209 static const int kNumReservedRegisters = 2;
210 static const int kMaxNumAllocatableRegisters = kMaxNumRegisters -
211 kNumReservedRegisters;
186 static const int kSizeInBytes = 8; 212 static const int kSizeInBytes = 8;
187 213
188 const char* ToString(); 214 // Note: the number of registers can be different at snapshot and run-time.
189 bool IsAllocatable() const; 215 // Any code included in the snapshot must be able to run both with 16 or 32
190 bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; } 216 // registers.
191 bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; } 217 inline static int NumRegisters();
218 inline static int NumReservedRegisters();
219 inline static int NumAllocatableRegisters();
220
221 // TODO(turbofan): This is a temporary work-around required because our
222 // register allocator does not yet support the aliasing of single/double
223 // registers on ARM.
224 inline static int NumAllocatableAliasedRegisters();
225
226 inline static int ToAllocationIndex(DwVfpRegister reg);
227 static const char* AllocationIndexToString(int index);
228 inline static DwVfpRegister FromAllocationIndex(int index);
229
230 static DwVfpRegister from_code(int code) {
231 DwVfpRegister r = { code };
232 return r;
233 }
234
235 bool is_valid() const {
236 return 0 <= code_ && code_ < kMaxNumRegisters;
237 }
238 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
192 int code() const { 239 int code() const {
193 DCHECK(is_valid()); 240 DCHECK(is_valid());
194 return reg_code; 241 return code_;
195 } 242 }
196 int bit() const { 243 int bit() const {
197 DCHECK(is_valid()); 244 DCHECK(is_valid());
198 return 1 << reg_code; 245 return 1 << code_;
199 }
200
201 static DoubleRegister from_code(int code) {
202 DoubleRegister r = {code};
203 return r;
204 } 246 }
205 void split_code(int* vm, int* m) const { 247 void split_code(int* vm, int* m) const {
206 DCHECK(is_valid()); 248 DCHECK(is_valid());
207 *m = (reg_code & 0x10) >> 4; 249 *m = (code_ & 0x10) >> 4;
208 *vm = reg_code & 0x0F; 250 *vm = code_ & 0x0F;
209 } 251 }
210 252
211 int reg_code; 253 int code_;
212 }; 254 };
213 255
214 256
215 typedef DoubleRegister DwVfpRegister; 257 typedef DwVfpRegister DoubleRegister;
216 258
217 259
218 // Double word VFP register d0-15. 260 // Double word VFP register d0-15.
219 struct LowDwVfpRegister { 261 struct LowDwVfpRegister {
220 public: 262 public:
221 static const int kMaxNumLowRegisters = 16; 263 static const int kMaxNumLowRegisters = 16;
222 operator DwVfpRegister() const { 264 operator DwVfpRegister() const {
223 DwVfpRegister r = { reg_code }; 265 DwVfpRegister r = { code_ };
224 return r; 266 return r;
225 } 267 }
226 static LowDwVfpRegister from_code(int code) { 268 static LowDwVfpRegister from_code(int code) {
227 LowDwVfpRegister r = { code }; 269 LowDwVfpRegister r = { code };
228 return r; 270 return r;
229 } 271 }
230 272
231 bool is_valid() const { 273 bool is_valid() const {
232 return 0 <= reg_code && reg_code < kMaxNumLowRegisters; 274 return 0 <= code_ && code_ < kMaxNumLowRegisters;
233 } 275 }
234 bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; } 276 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
235 bool is(LowDwVfpRegister reg) const { return reg_code == reg.reg_code; } 277 bool is(LowDwVfpRegister reg) const { return code_ == reg.code_; }
236 int code() const { 278 int code() const {
237 DCHECK(is_valid()); 279 DCHECK(is_valid());
238 return reg_code; 280 return code_;
239 } 281 }
240 SwVfpRegister low() const { 282 SwVfpRegister low() const {
241 SwVfpRegister reg; 283 SwVfpRegister reg;
242 reg.reg_code = reg_code * 2; 284 reg.code_ = code_ * 2;
243 285
244 DCHECK(reg.is_valid()); 286 DCHECK(reg.is_valid());
245 return reg; 287 return reg;
246 } 288 }
247 SwVfpRegister high() const { 289 SwVfpRegister high() const {
248 SwVfpRegister reg; 290 SwVfpRegister reg;
249 reg.reg_code = (reg_code * 2) + 1; 291 reg.code_ = (code_ * 2) + 1;
250 292
251 DCHECK(reg.is_valid()); 293 DCHECK(reg.is_valid());
252 return reg; 294 return reg;
253 } 295 }
254 296
255 int reg_code; 297 int code_;
256 }; 298 };
257 299
258 300
259 // Quad word NEON register. 301 // Quad word NEON register.
260 struct QwNeonRegister { 302 struct QwNeonRegister {
261 static const int kMaxNumRegisters = 16; 303 static const int kMaxNumRegisters = 16;
262 304
263 static QwNeonRegister from_code(int code) { 305 static QwNeonRegister from_code(int code) {
264 QwNeonRegister r = { code }; 306 QwNeonRegister r = { code };
265 return r; 307 return r;
266 } 308 }
267 309
268 bool is_valid() const { 310 bool is_valid() const {
269 return (0 <= reg_code) && (reg_code < kMaxNumRegisters); 311 return (0 <= code_) && (code_ < kMaxNumRegisters);
270 } 312 }
271 bool is(QwNeonRegister reg) const { return reg_code == reg.reg_code; } 313 bool is(QwNeonRegister reg) const { return code_ == reg.code_; }
272 int code() const { 314 int code() const {
273 DCHECK(is_valid()); 315 DCHECK(is_valid());
274 return reg_code; 316 return code_;
275 } 317 }
276 void split_code(int* vm, int* m) const { 318 void split_code(int* vm, int* m) const {
277 DCHECK(is_valid()); 319 DCHECK(is_valid());
278 int encoded_code = reg_code << 1; 320 int encoded_code = code_ << 1;
279 *m = (encoded_code & 0x10) >> 4; 321 *m = (encoded_code & 0x10) >> 4;
280 *vm = encoded_code & 0x0F; 322 *vm = encoded_code & 0x0F;
281 } 323 }
282 324
283 int reg_code; 325 int code_;
284 }; 326 };
285 327
286 328
287 typedef QwNeonRegister QuadRegister; 329 typedef QwNeonRegister QuadRegister;
288 330
289 331
290 // Support for the VFP registers s0 to s31 (d0 to d15). 332 // Support for the VFP registers s0 to s31 (d0 to d15).
291 // Note that "s(N):s(N+1)" is the same as "d(N/2)". 333 // Note that "s(N):s(N+1)" is the same as "d(N/2)".
292 const SwVfpRegister s0 = { 0 }; 334 const SwVfpRegister s0 = { 0 };
293 const SwVfpRegister s1 = { 1 }; 335 const SwVfpRegister s1 = { 1 };
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 // "static const DwVfpRegister&" because Clang complains otherwise when a 420 // "static const DwVfpRegister&" because Clang complains otherwise when a
379 // compilation unit that includes this header doesn't use the variables. 421 // compilation unit that includes this header doesn't use the variables.
380 #define kFirstCalleeSavedDoubleReg d8 422 #define kFirstCalleeSavedDoubleReg d8
381 #define kLastCalleeSavedDoubleReg d15 423 #define kLastCalleeSavedDoubleReg d15
382 #define kDoubleRegZero d14 424 #define kDoubleRegZero d14
383 #define kScratchDoubleReg d15 425 #define kScratchDoubleReg d15
384 426
385 427
386 // Coprocessor register 428 // Coprocessor register
387 struct CRegister { 429 struct CRegister {
388 bool is_valid() const { return 0 <= reg_code && reg_code < 16; } 430 bool is_valid() const { return 0 <= code_ && code_ < 16; }
389 bool is(CRegister creg) const { return reg_code == creg.reg_code; } 431 bool is(CRegister creg) const { return code_ == creg.code_; }
390 int code() const { 432 int code() const {
391 DCHECK(is_valid()); 433 DCHECK(is_valid());
392 return reg_code; 434 return code_;
393 } 435 }
394 int bit() const { 436 int bit() const {
395 DCHECK(is_valid()); 437 DCHECK(is_valid());
396 return 1 << reg_code; 438 return 1 << code_;
397 } 439 }
398 440
399 // Unfortunately we can't make this private in a struct. 441 // Unfortunately we can't make this private in a struct.
400 int reg_code; 442 int code_;
401 }; 443 };
402 444
403 445
404 const CRegister no_creg = { -1 }; 446 const CRegister no_creg = { -1 };
405 447
406 const CRegister cr0 = { 0 }; 448 const CRegister cr0 = { 0 };
407 const CRegister cr1 = { 1 }; 449 const CRegister cr1 = { 1 };
408 const CRegister cr2 = { 2 }; 450 const CRegister cr2 = { 2 };
409 const CRegister cr3 = { 3 }; 451 const CRegister cr3 = { 3 };
410 const CRegister cr4 = { 4 }; 452 const CRegister cr4 = { 4 };
(...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after
1613 public: 1655 public:
1614 explicit EnsureSpace(Assembler* assembler) { 1656 explicit EnsureSpace(Assembler* assembler) {
1615 assembler->CheckBuffer(); 1657 assembler->CheckBuffer();
1616 } 1658 }
1617 }; 1659 };
1618 1660
1619 1661
1620 } } // namespace v8::internal 1662 } } // namespace v8::internal
1621 1663
1622 #endif // V8_ARM_ASSEMBLER_ARM_H_ 1664 #endif // V8_ARM_ASSEMBLER_ARM_H_
OLDNEW
« no previous file with comments | « BUILD.gn ('k') | src/arm/assembler-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698