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

Side by Side Diff: src/arm/assembler-arm.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 | « 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
53 // CPU Registers. 78 // CPU Registers.
54 // 79 //
55 // 1) We would prefer to use an enum, but enum values are assignment- 80 // 1) We would prefer to use an enum, but enum values are assignment-
56 // compatible with int, which has caused code-generation bugs. 81 // compatible with int, which has caused code-generation bugs.
57 // 82 //
58 // 2) We would prefer to use a class instead of a struct but we don't like 83 // 2) We would prefer to use a class instead of a struct but we don't like
59 // the register initialization to depend on the particular initialization 84 // the register initialization to depend on the particular initialization
60 // order (which appears to be different on OS X, Linux, and Windows for the 85 // order (which appears to be different on OS X, Linux, and Windows for the
61 // installed versions of C++ we tried). Using a struct permits C-style 86 // installed versions of C++ we tried). Using a struct permits C-style
62 // "initialization". Also, the Register objects cannot be const as this 87 // "initialization". Also, the Register objects cannot be const as this
63 // forces initialization stubs in MSVC, making us dependent on initialization 88 // forces initialization stubs in MSVC, making us dependent on initialization
64 // order. 89 // order.
65 // 90 //
66 // 3) By not using an enum, we are possibly preventing the compiler from 91 // 3) By not using an enum, we are possibly preventing the compiler from
67 // doing certain constant folds, which may significantly reduce the 92 // doing certain constant folds, which may significantly reduce the
68 // code generated for some assembly instructions (because they boil down 93 // code generated for some assembly instructions (because they boil down
69 // to a few constants). If this is a problem, we could change the code 94 // to a few constants). If this is a problem, we could change the code
70 // such that we use an enum in optimized mode, and the struct in debug 95 // such that we use an enum in optimized mode, and the struct in debug
71 // mode. This way we get the compile-time error checking in debug mode 96 // mode. This way we get the compile-time error checking in debug mode
72 // and best performance in optimized code. 97 // and best performance in optimized code.
73 98
74 // These constants are used in several locations, including static initializers 99 struct Register {
75 const int kRegister_no_reg_Code = -1; 100 enum Code {
76 const int kRegister_r0_Code = 0; 101 #define REGISTER_CODE(R) kCode_##R,
77 const int kRegister_r1_Code = 1; 102 GENERAL_REGISTERS(REGISTER_CODE)
78 const int kRegister_r2_Code = 2; 103 #undef REGISTER_CODE
79 const int kRegister_r3_Code = 3; 104 kAfterLast,
80 const int kRegister_r4_Code = 4; 105 kCode_no_reg = -1
81 const int kRegister_r5_Code = 5; 106 };
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 107
93 // Core register 108 static const int kNumRegisters = Code::kAfterLast;
94 struct Register {
95 static const int kNumRegisters = 16;
96 static const int kMaxNumAllocatableRegisters =
97 FLAG_enable_embedded_constant_pool ? 8 : 9;
98 static const int kSizeInBytes = 4;
99
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 }
130 109
131 static Register from_code(int code) { 110 static Register from_code(int code) {
132 Register r = { code }; 111 DCHECK(code >= 0);
112 DCHECK(code < kNumRegisters);
113 Register r = {code};
133 return r; 114 return r;
134 } 115 }
135 116 const char* ToString();
136 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } 117 bool IsAllocatable() const;
137 bool is(Register reg) const { return code_ == reg.code_; } 118 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
119 bool is(Register reg) const { return reg_code == reg.reg_code; }
138 int code() const { 120 int code() const {
139 DCHECK(is_valid()); 121 DCHECK(is_valid());
140 return code_; 122 return reg_code;
141 } 123 }
142 int bit() const { 124 int bit() const {
143 DCHECK(is_valid()); 125 DCHECK(is_valid());
144 return 1 << code_; 126 return 1 << reg_code;
145 } 127 }
146
147 void set_code(int code) { 128 void set_code(int code) {
148 code_ = code; 129 reg_code = code;
149 DCHECK(is_valid()); 130 DCHECK(is_valid());
150 } 131 }
151 132
152 // Unfortunately we can't make this private in a struct. 133 // Unfortunately we can't make this private in a struct.
153 int code_; 134 int reg_code;
154 }; 135 };
155 136
156 const Register no_reg = { kRegister_no_reg_Code }; 137 // r7: context register
157 138 // r8: constant pool pointer register if FLAG_enable_embedded_constant_pool.
158 const Register r0 = { kRegister_r0_Code }; 139 // r9: lithium scratch
159 const Register r1 = { kRegister_r1_Code }; 140 #define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
160 const Register r2 = { kRegister_r2_Code }; 141 GENERAL_REGISTERS(DECLARE_REGISTER)
161 const Register r3 = { kRegister_r3_Code }; 142 #undef DECLARE_REGISTER
162 const Register r4 = { kRegister_r4_Code }; 143 const Register no_reg = {Register::kCode_no_reg};
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 };
178 144
179 // Single word VFP register. 145 // Single word VFP register.
180 struct SwVfpRegister { 146 struct SwVfpRegister {
181 static const int kSizeInBytes = 4; 147 static const int kSizeInBytes = 4;
182 bool is_valid() const { return 0 <= code_ && code_ < 32; } 148 bool is_valid() const { return 0 <= reg_code && reg_code < 32; }
183 bool is(SwVfpRegister reg) const { return code_ == reg.code_; } 149 bool is(SwVfpRegister reg) const { return reg_code == reg.reg_code; }
184 int code() const { 150 int code() const {
185 DCHECK(is_valid()); 151 DCHECK(is_valid());
186 return code_; 152 return reg_code;
187 } 153 }
188 int bit() const { 154 int bit() const {
189 DCHECK(is_valid()); 155 DCHECK(is_valid());
190 return 1 << code_; 156 return 1 << reg_code;
191 } 157 }
192 void split_code(int* vm, int* m) const { 158 void split_code(int* vm, int* m) const {
193 DCHECK(is_valid()); 159 DCHECK(is_valid());
194 *m = code_ & 0x1; 160 *m = reg_code & 0x1;
195 *vm = code_ >> 1; 161 *vm = reg_code >> 1;
196 } 162 }
197 163
198 int code_; 164 int reg_code;
199 }; 165 };
200 166
201 167
202 // Double word VFP register. 168 // Double word VFP register.
203 struct DwVfpRegister { 169 struct DoubleRegister {
204 static const int kMaxNumRegisters = 32; 170 enum Code {
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
205 // A few double registers are reserved: one as a scratch register and one to 182 // A few double registers are reserved: one as a scratch register and one to
206 // hold 0.0, that does not fit in the immediate field of vmov instructions. 183 // hold 0.0, that does not fit in the immediate field of vmov instructions.
207 // d14: 0.0 184 // d14: 0.0
208 // d15: scratch register. 185 // d15: scratch register.
209 static const int kNumReservedRegisters = 2;
210 static const int kMaxNumAllocatableRegisters = kMaxNumRegisters -
211 kNumReservedRegisters;
212 static const int kSizeInBytes = 8; 186 static const int kSizeInBytes = 8;
213 187
214 // Note: the number of registers can be different at snapshot and run-time. 188 const char* ToString();
215 // Any code included in the snapshot must be able to run both with 16 or 32 189 bool IsAllocatable() const;
216 // registers. 190 bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
217 inline static int NumRegisters(); 191 bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
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_; }
239 int code() const { 192 int code() const {
240 DCHECK(is_valid()); 193 DCHECK(is_valid());
241 return code_; 194 return reg_code;
242 } 195 }
243 int bit() const { 196 int bit() const {
244 DCHECK(is_valid()); 197 DCHECK(is_valid());
245 return 1 << code_; 198 return 1 << reg_code;
199 }
200
201 static DoubleRegister from_code(int code) {
202 DoubleRegister r = {code};
203 return r;
246 } 204 }
247 void split_code(int* vm, int* m) const { 205 void split_code(int* vm, int* m) const {
248 DCHECK(is_valid()); 206 DCHECK(is_valid());
249 *m = (code_ & 0x10) >> 4; 207 *m = (reg_code & 0x10) >> 4;
250 *vm = code_ & 0x0F; 208 *vm = reg_code & 0x0F;
251 } 209 }
252 210
253 int code_; 211 int reg_code;
254 }; 212 };
255 213
256 214
257 typedef DwVfpRegister DoubleRegister; 215 typedef DoubleRegister DwVfpRegister;
258 216
259 217
260 // Double word VFP register d0-15. 218 // Double word VFP register d0-15.
261 struct LowDwVfpRegister { 219 struct LowDwVfpRegister {
262 public: 220 public:
263 static const int kMaxNumLowRegisters = 16; 221 static const int kMaxNumLowRegisters = 16;
264 operator DwVfpRegister() const { 222 operator DwVfpRegister() const {
265 DwVfpRegister r = { code_ }; 223 DwVfpRegister r = { reg_code };
266 return r; 224 return r;
267 } 225 }
268 static LowDwVfpRegister from_code(int code) { 226 static LowDwVfpRegister from_code(int code) {
269 LowDwVfpRegister r = { code }; 227 LowDwVfpRegister r = { code };
270 return r; 228 return r;
271 } 229 }
272 230
273 bool is_valid() const { 231 bool is_valid() const {
274 return 0 <= code_ && code_ < kMaxNumLowRegisters; 232 return 0 <= reg_code && reg_code < kMaxNumLowRegisters;
275 } 233 }
276 bool is(DwVfpRegister reg) const { return code_ == reg.code_; } 234 bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; }
277 bool is(LowDwVfpRegister reg) const { return code_ == reg.code_; } 235 bool is(LowDwVfpRegister reg) const { return reg_code == reg.reg_code; }
278 int code() const { 236 int code() const {
279 DCHECK(is_valid()); 237 DCHECK(is_valid());
280 return code_; 238 return reg_code;
281 } 239 }
282 SwVfpRegister low() const { 240 SwVfpRegister low() const {
283 SwVfpRegister reg; 241 SwVfpRegister reg;
284 reg.code_ = code_ * 2; 242 reg.reg_code = reg_code * 2;
285 243
286 DCHECK(reg.is_valid()); 244 DCHECK(reg.is_valid());
287 return reg; 245 return reg;
288 } 246 }
289 SwVfpRegister high() const { 247 SwVfpRegister high() const {
290 SwVfpRegister reg; 248 SwVfpRegister reg;
291 reg.code_ = (code_ * 2) + 1; 249 reg.reg_code = (reg_code * 2) + 1;
292 250
293 DCHECK(reg.is_valid()); 251 DCHECK(reg.is_valid());
294 return reg; 252 return reg;
295 } 253 }
296 254
297 int code_; 255 int reg_code;
298 }; 256 };
299 257
300 258
301 // Quad word NEON register. 259 // Quad word NEON register.
302 struct QwNeonRegister { 260 struct QwNeonRegister {
303 static const int kMaxNumRegisters = 16; 261 static const int kMaxNumRegisters = 16;
304 262
305 static QwNeonRegister from_code(int code) { 263 static QwNeonRegister from_code(int code) {
306 QwNeonRegister r = { code }; 264 QwNeonRegister r = { code };
307 return r; 265 return r;
308 } 266 }
309 267
310 bool is_valid() const { 268 bool is_valid() const {
311 return (0 <= code_) && (code_ < kMaxNumRegisters); 269 return (0 <= reg_code) && (reg_code < kMaxNumRegisters);
312 } 270 }
313 bool is(QwNeonRegister reg) const { return code_ == reg.code_; } 271 bool is(QwNeonRegister reg) const { return reg_code == reg.reg_code; }
314 int code() const { 272 int code() const {
315 DCHECK(is_valid()); 273 DCHECK(is_valid());
316 return code_; 274 return reg_code;
317 } 275 }
318 void split_code(int* vm, int* m) const { 276 void split_code(int* vm, int* m) const {
319 DCHECK(is_valid()); 277 DCHECK(is_valid());
320 int encoded_code = code_ << 1; 278 int encoded_code = reg_code << 1;
321 *m = (encoded_code & 0x10) >> 4; 279 *m = (encoded_code & 0x10) >> 4;
322 *vm = encoded_code & 0x0F; 280 *vm = encoded_code & 0x0F;
323 } 281 }
324 282
325 int code_; 283 int reg_code;
326 }; 284 };
327 285
328 286
329 typedef QwNeonRegister QuadRegister; 287 typedef QwNeonRegister QuadRegister;
330 288
331 289
332 // Support for the VFP registers s0 to s31 (d0 to d15). 290 // Support for the VFP registers s0 to s31 (d0 to d15).
333 // Note that "s(N):s(N+1)" is the same as "d(N/2)". 291 // Note that "s(N):s(N+1)" is the same as "d(N/2)".
334 const SwVfpRegister s0 = { 0 }; 292 const SwVfpRegister s0 = { 0 };
335 const SwVfpRegister s1 = { 1 }; 293 const SwVfpRegister s1 = { 1 };
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 // "static const DwVfpRegister&" because Clang complains otherwise when a 378 // "static const DwVfpRegister&" because Clang complains otherwise when a
421 // compilation unit that includes this header doesn't use the variables. 379 // compilation unit that includes this header doesn't use the variables.
422 #define kFirstCalleeSavedDoubleReg d8 380 #define kFirstCalleeSavedDoubleReg d8
423 #define kLastCalleeSavedDoubleReg d15 381 #define kLastCalleeSavedDoubleReg d15
424 #define kDoubleRegZero d14 382 #define kDoubleRegZero d14
425 #define kScratchDoubleReg d15 383 #define kScratchDoubleReg d15
426 384
427 385
428 // Coprocessor register 386 // Coprocessor register
429 struct CRegister { 387 struct CRegister {
430 bool is_valid() const { return 0 <= code_ && code_ < 16; } 388 bool is_valid() const { return 0 <= reg_code && reg_code < 16; }
431 bool is(CRegister creg) const { return code_ == creg.code_; } 389 bool is(CRegister creg) const { return reg_code == creg.reg_code; }
432 int code() const { 390 int code() const {
433 DCHECK(is_valid()); 391 DCHECK(is_valid());
434 return code_; 392 return reg_code;
435 } 393 }
436 int bit() const { 394 int bit() const {
437 DCHECK(is_valid()); 395 DCHECK(is_valid());
438 return 1 << code_; 396 return 1 << reg_code;
439 } 397 }
440 398
441 // Unfortunately we can't make this private in a struct. 399 // Unfortunately we can't make this private in a struct.
442 int code_; 400 int reg_code;
443 }; 401 };
444 402
445 403
446 const CRegister no_creg = { -1 }; 404 const CRegister no_creg = { -1 };
447 405
448 const CRegister cr0 = { 0 }; 406 const CRegister cr0 = { 0 };
449 const CRegister cr1 = { 1 }; 407 const CRegister cr1 = { 1 };
450 const CRegister cr2 = { 2 }; 408 const CRegister cr2 = { 2 };
451 const CRegister cr3 = { 3 }; 409 const CRegister cr3 = { 3 };
452 const CRegister cr4 = { 4 }; 410 const CRegister cr4 = { 4 };
(...skipping 1211 matching lines...) Expand 10 before | Expand all | Expand 10 after
1664 explicit EnsureSpace(Assembler* assembler) { 1622 explicit EnsureSpace(Assembler* assembler) {
1665 assembler->CheckBuffer(); 1623 assembler->CheckBuffer();
1666 } 1624 }
1667 }; 1625 };
1668 1626
1669 1627
1670 } // namespace internal 1628 } // namespace internal
1671 } // namespace v8 1629 } // namespace v8
1672 1630
1673 #endif // V8_ARM_ASSEMBLER_ARM_H_ 1631 #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