Index: src/x64/assembler-x64.h |
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h |
index f1ffcd29d6c46282efa366338e05873c43e5e416..956e142c9ef35649608a1cb466bbeb42da5b84c0 100644 |
--- a/src/x64/assembler-x64.h |
+++ b/src/x64/assembler-x64.h |
@@ -47,39 +47,6 @@ |
// Utility functions |
-#define GENERAL_REGISTERS(V) \ |
- V(rax) \ |
- V(rcx) \ |
- V(rdx) \ |
- V(rbx) \ |
- V(rsp) \ |
- V(rbp) \ |
- V(rsi) \ |
- V(rdi) \ |
- V(r8) \ |
- V(r9) \ |
- V(r10) \ |
- V(r11) \ |
- V(r12) \ |
- V(r13) \ |
- V(r14) \ |
- V(r15) |
- |
-#define ALLOCATABLE_GENERAL_REGISTERS(V) \ |
- V(rax) \ |
- V(rbx) \ |
- V(rdx) \ |
- V(rcx) \ |
- V(rsi) \ |
- V(rdi) \ |
- V(r8) \ |
- V(r9) \ |
- V(r11) \ |
- V(r12) \ |
- V(r14) \ |
- V(r15) |
- |
- |
// CPU Registers. |
// |
// 1) We would prefer to use an enum, but enum values are assignment- |
@@ -101,153 +68,226 @@ |
// mode. This way we get the compile-time error checking in debug mode |
// and best performance in optimized code. |
// |
+ |
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; |
+ // The non-allocatable registers are: |
+ // rsp - stack pointer |
+ // rbp - frame pointer |
+ // r10 - fixed scratch register |
+ // r13 - root register |
+ static const int kMaxNumAllocatableRegisters = 12; |
+ static int NumAllocatableRegisters() { |
+ return kMaxNumAllocatableRegisters; |
+ } |
+ static const int kNumRegisters = 16; |
+ |
+ static int ToAllocationIndex(Register reg) { |
+ return kAllocationIndexByRegisterCode[reg.code()]; |
+ } |
+ |
+ static Register FromAllocationIndex(int index) { |
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); |
+ Register result = { kRegisterCodeByAllocationIndex[index] }; |
+ return result; |
+ } |
+ |
+ static const char* AllocationIndexToString(int index) { |
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); |
+ const char* const names[] = { |
+ "rax", |
+ "rbx", |
+ "rdx", |
+ "rcx", |
+ "rsi", |
+ "rdi", |
+ "r8", |
+ "r9", |
+ "r11", |
+ "r12", |
+ "r14", |
+ "r15" |
+ }; |
+ 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_; } |
+ // rax, rbx, rcx and rdx are byte registers, the rest are not. |
+ bool is_byte_register() const { return code_ <= 3; } |
int code() const { |
DCHECK(is_valid()); |
- return reg_code; |
+ return code_; |
} |
int bit() const { |
- DCHECK(is_valid()); |
- return 1 << reg_code; |
- } |
- |
- bool is_byte_register() const { return reg_code <= 3; } |
+ return 1 << code_; |
+ } |
+ |
// Return the high bit of the register code as a 0 or 1. Used often |
// when constructing the REX prefix byte. |
- int high_bit() const { return reg_code >> 3; } |
+ int high_bit() const { |
+ return code_ >> 3; |
+ } |
// Return the 3 low bits of the register code. Used when encoding registers |
// in modR/M, SIB, and opcode bytes. |
- int low_bits() const { return reg_code & 0x7; } |
+ int low_bits() const { |
+ return code_ & 0x7; |
+ } |
// Unfortunately we can't make this private in a struct when initializing |
// by assignment. |
- int reg_code; |
+ int code_; |
+ |
+ private: |
+ static const int kRegisterCodeByAllocationIndex[kMaxNumAllocatableRegisters]; |
+ static const int kAllocationIndexByRegisterCode[kNumRegisters]; |
}; |
- |
-#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 int kRegister_rax_Code = 0; |
+const int kRegister_rcx_Code = 1; |
+const int kRegister_rdx_Code = 2; |
+const int kRegister_rbx_Code = 3; |
+const int kRegister_rsp_Code = 4; |
+const int kRegister_rbp_Code = 5; |
+const int kRegister_rsi_Code = 6; |
+const int kRegister_rdi_Code = 7; |
+const int kRegister_r8_Code = 8; |
+const int kRegister_r9_Code = 9; |
+const int kRegister_r10_Code = 10; |
+const int kRegister_r11_Code = 11; |
+const int kRegister_r12_Code = 12; |
+const int kRegister_r13_Code = 13; |
+const int kRegister_r14_Code = 14; |
+const int kRegister_r15_Code = 15; |
+const int kRegister_no_reg_Code = -1; |
+ |
+const Register rax = { kRegister_rax_Code }; |
+const Register rcx = { kRegister_rcx_Code }; |
+const Register rdx = { kRegister_rdx_Code }; |
+const Register rbx = { kRegister_rbx_Code }; |
+const Register rsp = { kRegister_rsp_Code }; |
+const Register rbp = { kRegister_rbp_Code }; |
+const Register rsi = { kRegister_rsi_Code }; |
+const Register rdi = { kRegister_rdi_Code }; |
+const Register r8 = { kRegister_r8_Code }; |
+const Register r9 = { kRegister_r9_Code }; |
+const Register r10 = { kRegister_r10_Code }; |
+const Register r11 = { kRegister_r11_Code }; |
+const Register r12 = { kRegister_r12_Code }; |
+const Register r13 = { kRegister_r13_Code }; |
+const Register r14 = { kRegister_r14_Code }; |
+const Register r15 = { kRegister_r15_Code }; |
+const Register no_reg = { kRegister_no_reg_Code }; |
#ifdef _WIN64 |
// Windows calling convention |
-const Register arg_reg_1 = {Register::kCode_rcx}; |
-const Register arg_reg_2 = {Register::kCode_rdx}; |
-const Register arg_reg_3 = {Register::kCode_r8}; |
-const Register arg_reg_4 = {Register::kCode_r9}; |
+ const Register arg_reg_1 = { kRegister_rcx_Code }; |
+ const Register arg_reg_2 = { kRegister_rdx_Code }; |
+ const Register arg_reg_3 = { kRegister_r8_Code }; |
+ const Register arg_reg_4 = { kRegister_r9_Code }; |
#else |
// AMD64 calling convention |
-const Register arg_reg_1 = {Register::kCode_rdi}; |
-const Register arg_reg_2 = {Register::kCode_rsi}; |
-const Register arg_reg_3 = {Register::kCode_rdx}; |
-const Register arg_reg_4 = {Register::kCode_rcx}; |
+ const Register arg_reg_1 = { kRegister_rdi_Code }; |
+ const Register arg_reg_2 = { kRegister_rsi_Code }; |
+ const Register arg_reg_3 = { kRegister_rdx_Code }; |
+ const Register arg_reg_4 = { kRegister_rcx_Code }; |
#endif // _WIN64 |
- |
-#define DOUBLE_REGISTERS(V) \ |
- V(xmm0) \ |
- V(xmm1) \ |
- V(xmm2) \ |
- V(xmm3) \ |
- V(xmm4) \ |
- V(xmm5) \ |
- V(xmm6) \ |
- V(xmm7) \ |
- V(xmm8) \ |
- V(xmm9) \ |
- V(xmm10) \ |
- V(xmm11) \ |
- V(xmm12) \ |
- V(xmm13) \ |
- V(xmm14) \ |
- V(xmm15) |
- |
-#define ALLOCATABLE_DOUBLE_REGISTERS(V) \ |
- V(xmm1) \ |
- V(xmm2) \ |
- V(xmm3) \ |
- V(xmm4) \ |
- V(xmm5) \ |
- V(xmm6) \ |
- V(xmm7) \ |
- V(xmm8) \ |
- V(xmm9) \ |
- V(xmm10) \ |
- V(xmm11) \ |
- V(xmm12) \ |
- V(xmm13) \ |
- V(xmm14) \ |
- V(xmm15) |
- |
- |
-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; |
- |
- static DoubleRegister from_code(int code) { |
- DoubleRegister result = {code}; |
+struct XMMRegister { |
+ static const int kMaxNumRegisters = 16; |
+ static const int kMaxNumAllocatableRegisters = 15; |
+ static int NumAllocatableRegisters() { |
+ return kMaxNumAllocatableRegisters; |
+ } |
+ |
+ // TODO(turbofan): Proper support for float32. |
+ static int NumAllocatableAliasedRegisters() { |
+ return NumAllocatableRegisters(); |
+ } |
+ |
+ static int ToAllocationIndex(XMMRegister reg) { |
+ DCHECK(reg.code() != 0); |
+ return reg.code() - 1; |
+ } |
+ |
+ static XMMRegister FromAllocationIndex(int index) { |
+ DCHECK(0 <= index && index < kMaxNumAllocatableRegisters); |
+ XMMRegister result = { index + 1 }; |
return result; |
} |
- 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; } |
+ static const char* AllocationIndexToString(int index) { |
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); |
+ const char* const names[] = { |
+ "xmm1", |
+ "xmm2", |
+ "xmm3", |
+ "xmm4", |
+ "xmm5", |
+ "xmm6", |
+ "xmm7", |
+ "xmm8", |
+ "xmm9", |
+ "xmm10", |
+ "xmm11", |
+ "xmm12", |
+ "xmm13", |
+ "xmm14", |
+ "xmm15" |
+ }; |
+ return names[index]; |
+ } |
+ |
+ static XMMRegister from_code(int code) { |
+ DCHECK(code >= 0); |
+ DCHECK(code < kMaxNumRegisters); |
+ XMMRegister r = { code }; |
+ return r; |
+ } |
+ bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters; } |
+ bool is(XMMRegister reg) const { return code_ == reg.code_; } |
int code() const { |
DCHECK(is_valid()); |
- return reg_code; |
+ return code_; |
} |
// Return the high bit of the register code as a 0 or 1. Used often |
// when constructing the REX prefix byte. |
- int high_bit() const { return reg_code >> 3; } |
+ int high_bit() const { |
+ return code_ >> 3; |
+ } |
// Return the 3 low bits of the register code. Used when encoding registers |
// in modR/M, SIB, and opcode bytes. |
- int low_bits() const { return reg_code & 0x7; } |
- |
- // Unfortunately we can't make this private in a struct when initializing |
- // by assignment. |
- int reg_code; |
+ int low_bits() const { |
+ return code_ & 0x7; |
+ } |
+ |
+ int code_; |
}; |
- |
-#define DECLARE_REGISTER(R) \ |
- const DoubleRegister R = {DoubleRegister::kCode_##R}; |
-DOUBLE_REGISTERS(DECLARE_REGISTER) |
-#undef DECLARE_REGISTER |
-const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg}; |
- |
- |
-typedef DoubleRegister XMMRegister; |
+const XMMRegister xmm0 = { 0 }; |
+const XMMRegister xmm1 = { 1 }; |
+const XMMRegister xmm2 = { 2 }; |
+const XMMRegister xmm3 = { 3 }; |
+const XMMRegister xmm4 = { 4 }; |
+const XMMRegister xmm5 = { 5 }; |
+const XMMRegister xmm6 = { 6 }; |
+const XMMRegister xmm7 = { 7 }; |
+const XMMRegister xmm8 = { 8 }; |
+const XMMRegister xmm9 = { 9 }; |
+const XMMRegister xmm10 = { 10 }; |
+const XMMRegister xmm11 = { 11 }; |
+const XMMRegister xmm12 = { 12 }; |
+const XMMRegister xmm13 = { 13 }; |
+const XMMRegister xmm14 = { 14 }; |
+const XMMRegister xmm15 = { 15 }; |
+ |
+ |
+typedef XMMRegister DoubleRegister; |
+ |
enum Condition { |
// any value < 0 is considered no_condition |