Index: src/arm/assembler-arm.h |
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h |
index aa13a828461d5fbc05994eacc4c61003a95c723e..c54e51df78cb57c146f1f9f815214ca899057e49 100644 |
--- a/src/arm/assembler-arm.h |
+++ b/src/arm/assembler-arm.h |
@@ -50,31 +50,6 @@ |
namespace v8 { |
namespace internal { |
-// clang-format off |
-#define GENERAL_REGISTERS(V) \ |
- V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \ |
- V(r8) V(r9) V(r10) V(fp) V(ip) V(sp) V(lr) V(pc) |
- |
-#define ALLOCATABLE_GENERAL_REGISTERS(V) \ |
- V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) V(r8) |
- |
-#define DOUBLE_REGISTERS(V) \ |
- V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \ |
- V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) \ |
- V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \ |
- V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31) |
- |
-#define ALLOCATABLE_DOUBLE_REGISTERS(V) \ |
- V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \ |
- V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) \ |
- V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \ |
- V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31) |
- |
-#define ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(V) \ |
- V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \ |
- V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) \ |
-// clang-format on |
- |
// CPU Registers. |
// |
// 1) We would prefer to use an enum, but enum values are assignment- |
@@ -96,123 +71,190 @@ |
// mode. This way we get the compile-time error checking in debug mode |
// and best performance in optimized code. |
+// These constants are used in several locations, including static initializers |
+const int kRegister_no_reg_Code = -1; |
+const int kRegister_r0_Code = 0; |
+const int kRegister_r1_Code = 1; |
+const int kRegister_r2_Code = 2; |
+const int kRegister_r3_Code = 3; |
+const int kRegister_r4_Code = 4; |
+const int kRegister_r5_Code = 5; |
+const int kRegister_r6_Code = 6; |
+const int kRegister_r7_Code = 7; |
+const int kRegister_r8_Code = 8; |
+const int kRegister_r9_Code = 9; |
+const int kRegister_r10_Code = 10; |
+const int kRegister_fp_Code = 11; |
+const int kRegister_ip_Code = 12; |
+const int kRegister_sp_Code = 13; |
+const int kRegister_lr_Code = 14; |
+const int kRegister_pc_Code = 15; |
+ |
+// Core register |
struct Register { |
- enum Code { |
-#define REGISTER_CODE(R) kCode_##R, |
- GENERAL_REGISTERS(REGISTER_CODE) |
-#undef REGISTER_CODE |
- kAfterLast, |
- kCode_no_reg = -1 |
- }; |
- |
- static const int kNumRegisters = Code::kAfterLast; |
+ static const int kNumRegisters = 16; |
+ static const int kMaxNumAllocatableRegisters = |
+ FLAG_enable_embedded_constant_pool ? 8 : 9; |
+ static const int kSizeInBytes = 4; |
+ |
+ inline static int NumAllocatableRegisters(); |
+ |
+ static int ToAllocationIndex(Register reg) { |
+ DCHECK(reg.code() < kMaxNumAllocatableRegisters); |
+ return reg.code(); |
+ } |
+ |
+ static Register FromAllocationIndex(int index) { |
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); |
+ return from_code(index); |
+ } |
+ |
+ static const char* AllocationIndexToString(int index) { |
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); |
+ const char* const names[] = { |
+ "r0", |
+ "r1", |
+ "r2", |
+ "r3", |
+ "r4", |
+ "r5", |
+ "r6", |
+ "r7", |
+ "r8", |
+ }; |
+ if (FLAG_enable_embedded_constant_pool && (index >= 7)) { |
+ return names[index + 1]; |
+ } |
+ return names[index]; |
+ } |
static Register from_code(int code) { |
- DCHECK(code >= 0); |
- DCHECK(code < kNumRegisters); |
- Register r = {code}; |
+ Register r = { code }; |
return r; |
} |
- const char* ToString(); |
- bool IsAllocatable() const; |
- bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } |
- bool is(Register reg) const { return reg_code == reg.reg_code; } |
+ |
+ bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } |
+ bool is(Register reg) const { return code_ == reg.code_; } |
int code() const { |
DCHECK(is_valid()); |
- return reg_code; |
+ return code_; |
} |
int bit() const { |
DCHECK(is_valid()); |
- return 1 << reg_code; |
- } |
+ return 1 << code_; |
+ } |
+ |
void set_code(int code) { |
- reg_code = code; |
+ code_ = code; |
DCHECK(is_valid()); |
} |
// Unfortunately we can't make this private in a struct. |
- int reg_code; |
+ int code_; |
}; |
-// r7: context register |
-// r8: constant pool pointer register if FLAG_enable_embedded_constant_pool. |
-// r9: lithium scratch |
-#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R}; |
-GENERAL_REGISTERS(DECLARE_REGISTER) |
-#undef DECLARE_REGISTER |
-const Register no_reg = {Register::kCode_no_reg}; |
+const Register no_reg = { kRegister_no_reg_Code }; |
+ |
+const Register r0 = { kRegister_r0_Code }; |
+const Register r1 = { kRegister_r1_Code }; |
+const Register r2 = { kRegister_r2_Code }; |
+const Register r3 = { kRegister_r3_Code }; |
+const Register r4 = { kRegister_r4_Code }; |
+const Register r5 = { kRegister_r5_Code }; |
+const Register r6 = { kRegister_r6_Code }; |
+// Used as context register. |
+const Register r7 = {kRegister_r7_Code}; |
+// Used as constant pool pointer register if FLAG_enable_embedded_constant_pool. |
+const Register r8 = { kRegister_r8_Code }; |
+// Used as lithium codegen scratch register. |
+const Register r9 = { kRegister_r9_Code }; |
+// Used as roots register. |
+const Register r10 = { kRegister_r10_Code }; |
+const Register fp = { kRegister_fp_Code }; |
+const Register ip = { kRegister_ip_Code }; |
+const Register sp = { kRegister_sp_Code }; |
+const Register lr = { kRegister_lr_Code }; |
+const Register pc = { kRegister_pc_Code }; |
// Single word VFP register. |
struct SwVfpRegister { |
static const int kSizeInBytes = 4; |
- bool is_valid() const { return 0 <= reg_code && reg_code < 32; } |
- bool is(SwVfpRegister reg) const { return reg_code == reg.reg_code; } |
+ bool is_valid() const { return 0 <= code_ && code_ < 32; } |
+ bool is(SwVfpRegister reg) const { return code_ == reg.code_; } |
int code() const { |
DCHECK(is_valid()); |
- return reg_code; |
+ return code_; |
} |
int bit() const { |
DCHECK(is_valid()); |
- return 1 << reg_code; |
+ return 1 << code_; |
} |
void split_code(int* vm, int* m) const { |
DCHECK(is_valid()); |
- *m = reg_code & 0x1; |
- *vm = reg_code >> 1; |
- } |
- |
- int reg_code; |
+ *m = code_ & 0x1; |
+ *vm = code_ >> 1; |
+ } |
+ |
+ int code_; |
}; |
// Double word VFP register. |
-struct DoubleRegister { |
- enum Code { |
-#define REGISTER_CODE(R) kCode_##R, |
- DOUBLE_REGISTERS(REGISTER_CODE) |
-#undef REGISTER_CODE |
- kAfterLast, |
- kCode_no_reg = -1 |
- }; |
- |
- static const int kMaxNumRegisters = Code::kAfterLast; |
- |
- inline static int NumRegisters(); |
- |
+struct DwVfpRegister { |
+ static const int kMaxNumRegisters = 32; |
// A few double registers are reserved: one as a scratch register and one to |
// hold 0.0, that does not fit in the immediate field of vmov instructions. |
// d14: 0.0 |
// d15: scratch register. |
+ static const int kNumReservedRegisters = 2; |
+ static const int kMaxNumAllocatableRegisters = kMaxNumRegisters - |
+ kNumReservedRegisters; |
static const int kSizeInBytes = 8; |
- const char* ToString(); |
- bool IsAllocatable() const; |
- bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; } |
- bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; } |
+ // Note: the number of registers can be different at snapshot and run-time. |
+ // Any code included in the snapshot must be able to run both with 16 or 32 |
+ // registers. |
+ inline static int NumRegisters(); |
+ inline static int NumReservedRegisters(); |
+ inline static int NumAllocatableRegisters(); |
+ |
+ // TODO(turbofan): This is a temporary work-around required because our |
+ // register allocator does not yet support the aliasing of single/double |
+ // registers on ARM. |
+ inline static int NumAllocatableAliasedRegisters(); |
+ |
+ inline static int ToAllocationIndex(DwVfpRegister reg); |
+ static const char* AllocationIndexToString(int index); |
+ inline static DwVfpRegister FromAllocationIndex(int index); |
+ |
+ static DwVfpRegister from_code(int code) { |
+ DwVfpRegister r = { code }; |
+ return r; |
+ } |
+ |
+ bool is_valid() const { |
+ return 0 <= code_ && code_ < kMaxNumRegisters; |
+ } |
+ bool is(DwVfpRegister reg) const { return code_ == reg.code_; } |
int code() const { |
DCHECK(is_valid()); |
- return reg_code; |
+ return code_; |
} |
int bit() const { |
DCHECK(is_valid()); |
- return 1 << reg_code; |
- } |
- |
- static DoubleRegister from_code(int code) { |
- DoubleRegister r = {code}; |
- return r; |
+ return 1 << code_; |
} |
void split_code(int* vm, int* m) const { |
DCHECK(is_valid()); |
- *m = (reg_code & 0x10) >> 4; |
- *vm = reg_code & 0x0F; |
- } |
- |
- int reg_code; |
+ *m = (code_ & 0x10) >> 4; |
+ *vm = code_ & 0x0F; |
+ } |
+ |
+ int code_; |
}; |
-typedef DoubleRegister DwVfpRegister; |
+typedef DwVfpRegister DoubleRegister; |
// Double word VFP register d0-15. |
@@ -220,7 +262,7 @@ |
public: |
static const int kMaxNumLowRegisters = 16; |
operator DwVfpRegister() const { |
- DwVfpRegister r = { reg_code }; |
+ DwVfpRegister r = { code_ }; |
return r; |
} |
static LowDwVfpRegister from_code(int code) { |
@@ -229,30 +271,30 @@ |
} |
bool is_valid() const { |
- return 0 <= reg_code && reg_code < kMaxNumLowRegisters; |
- } |
- bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; } |
- bool is(LowDwVfpRegister reg) const { return reg_code == reg.reg_code; } |
+ return 0 <= code_ && code_ < kMaxNumLowRegisters; |
+ } |
+ bool is(DwVfpRegister reg) const { return code_ == reg.code_; } |
+ bool is(LowDwVfpRegister reg) const { return code_ == reg.code_; } |
int code() const { |
DCHECK(is_valid()); |
- return reg_code; |
+ return code_; |
} |
SwVfpRegister low() const { |
SwVfpRegister reg; |
- reg.reg_code = reg_code * 2; |
+ reg.code_ = code_ * 2; |
DCHECK(reg.is_valid()); |
return reg; |
} |
SwVfpRegister high() const { |
SwVfpRegister reg; |
- reg.reg_code = (reg_code * 2) + 1; |
+ reg.code_ = (code_ * 2) + 1; |
DCHECK(reg.is_valid()); |
return reg; |
} |
- int reg_code; |
+ int code_; |
}; |
@@ -266,21 +308,21 @@ |
} |
bool is_valid() const { |
- return (0 <= reg_code) && (reg_code < kMaxNumRegisters); |
- } |
- bool is(QwNeonRegister reg) const { return reg_code == reg.reg_code; } |
+ return (0 <= code_) && (code_ < kMaxNumRegisters); |
+ } |
+ bool is(QwNeonRegister reg) const { return code_ == reg.code_; } |
int code() const { |
DCHECK(is_valid()); |
- return reg_code; |
+ return code_; |
} |
void split_code(int* vm, int* m) const { |
DCHECK(is_valid()); |
- int encoded_code = reg_code << 1; |
+ int encoded_code = code_ << 1; |
*m = (encoded_code & 0x10) >> 4; |
*vm = encoded_code & 0x0F; |
} |
- int reg_code; |
+ int code_; |
}; |
@@ -385,19 +427,19 @@ |
// Coprocessor register |
struct CRegister { |
- bool is_valid() const { return 0 <= reg_code && reg_code < 16; } |
- bool is(CRegister creg) const { return reg_code == creg.reg_code; } |
+ bool is_valid() const { return 0 <= code_ && code_ < 16; } |
+ bool is(CRegister creg) const { return code_ == creg.code_; } |
int code() const { |
DCHECK(is_valid()); |
- return reg_code; |
+ return code_; |
} |
int bit() const { |
DCHECK(is_valid()); |
- return 1 << reg_code; |
+ return 1 << code_; |
} |
// Unfortunately we can't make this private in a struct. |
- int reg_code; |
+ int code_; |
}; |