| OLD | NEW |
| 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 are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // 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 29 matching lines...) Expand all Loading... |
| 40 #include <deque> | 40 #include <deque> |
| 41 | 41 |
| 42 #include "src/assembler.h" | 42 #include "src/assembler.h" |
| 43 #include "src/compiler.h" | 43 #include "src/compiler.h" |
| 44 | 44 |
| 45 namespace v8 { | 45 namespace v8 { |
| 46 namespace internal { | 46 namespace internal { |
| 47 | 47 |
| 48 // Utility functions | 48 // Utility functions |
| 49 | 49 |
| 50 #define GENERAL_REGISTERS(V) \ | |
| 51 V(rax) \ | |
| 52 V(rcx) \ | |
| 53 V(rdx) \ | |
| 54 V(rbx) \ | |
| 55 V(rsp) \ | |
| 56 V(rbp) \ | |
| 57 V(rsi) \ | |
| 58 V(rdi) \ | |
| 59 V(r8) \ | |
| 60 V(r9) \ | |
| 61 V(r10) \ | |
| 62 V(r11) \ | |
| 63 V(r12) \ | |
| 64 V(r13) \ | |
| 65 V(r14) \ | |
| 66 V(r15) | |
| 67 | |
| 68 #define ALLOCATABLE_GENERAL_REGISTERS(V) \ | |
| 69 V(rax) \ | |
| 70 V(rbx) \ | |
| 71 V(rdx) \ | |
| 72 V(rcx) \ | |
| 73 V(rsi) \ | |
| 74 V(rdi) \ | |
| 75 V(r8) \ | |
| 76 V(r9) \ | |
| 77 V(r11) \ | |
| 78 V(r12) \ | |
| 79 V(r14) \ | |
| 80 V(r15) | |
| 81 | |
| 82 | |
| 83 // CPU Registers. | 50 // CPU Registers. |
| 84 // | 51 // |
| 85 // 1) We would prefer to use an enum, but enum values are assignment- | 52 // 1) We would prefer to use an enum, but enum values are assignment- |
| 86 // compatible with int, which has caused code-generation bugs. | 53 // compatible with int, which has caused code-generation bugs. |
| 87 // | 54 // |
| 88 // 2) We would prefer to use a class instead of a struct but we don't like | 55 // 2) We would prefer to use a class instead of a struct but we don't like |
| 89 // the register initialization to depend on the particular initialization | 56 // the register initialization to depend on the particular initialization |
| 90 // order (which appears to be different on OS X, Linux, and Windows for the | 57 // order (which appears to be different on OS X, Linux, and Windows for the |
| 91 // installed versions of C++ we tried). Using a struct permits C-style | 58 // installed versions of C++ we tried). Using a struct permits C-style |
| 92 // "initialization". Also, the Register objects cannot be const as this | 59 // "initialization". Also, the Register objects cannot be const as this |
| 93 // forces initialization stubs in MSVC, making us dependent on initialization | 60 // forces initialization stubs in MSVC, making us dependent on initialization |
| 94 // order. | 61 // order. |
| 95 // | 62 // |
| 96 // 3) By not using an enum, we are possibly preventing the compiler from | 63 // 3) By not using an enum, we are possibly preventing the compiler from |
| 97 // doing certain constant folds, which may significantly reduce the | 64 // doing certain constant folds, which may significantly reduce the |
| 98 // code generated for some assembly instructions (because they boil down | 65 // code generated for some assembly instructions (because they boil down |
| 99 // to a few constants). If this is a problem, we could change the code | 66 // to a few constants). If this is a problem, we could change the code |
| 100 // such that we use an enum in optimized mode, and the struct in debug | 67 // such that we use an enum in optimized mode, and the struct in debug |
| 101 // mode. This way we get the compile-time error checking in debug mode | 68 // mode. This way we get the compile-time error checking in debug mode |
| 102 // and best performance in optimized code. | 69 // and best performance in optimized code. |
| 103 // | 70 // |
| 71 |
| 104 struct Register { | 72 struct Register { |
| 105 enum Code { | 73 // The non-allocatable registers are: |
| 106 #define REGISTER_CODE(R) kCode_##R, | 74 // rsp - stack pointer |
| 107 GENERAL_REGISTERS(REGISTER_CODE) | 75 // rbp - frame pointer |
| 108 #undef REGISTER_CODE | 76 // r10 - fixed scratch register |
| 109 kAfterLast, | 77 // r13 - root register |
| 110 kCode_no_reg = -1 | 78 static const int kMaxNumAllocatableRegisters = 12; |
| 111 }; | 79 static int NumAllocatableRegisters() { |
| 112 | 80 return kMaxNumAllocatableRegisters; |
| 113 static const int kNumRegisters = Code::kAfterLast; | 81 } |
| 82 static const int kNumRegisters = 16; |
| 83 |
| 84 static int ToAllocationIndex(Register reg) { |
| 85 return kAllocationIndexByRegisterCode[reg.code()]; |
| 86 } |
| 87 |
| 88 static Register FromAllocationIndex(int index) { |
| 89 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); |
| 90 Register result = { kRegisterCodeByAllocationIndex[index] }; |
| 91 return result; |
| 92 } |
| 93 |
| 94 static const char* AllocationIndexToString(int index) { |
| 95 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); |
| 96 const char* const names[] = { |
| 97 "rax", |
| 98 "rbx", |
| 99 "rdx", |
| 100 "rcx", |
| 101 "rsi", |
| 102 "rdi", |
| 103 "r8", |
| 104 "r9", |
| 105 "r11", |
| 106 "r12", |
| 107 "r14", |
| 108 "r15" |
| 109 }; |
| 110 return names[index]; |
| 111 } |
| 114 | 112 |
| 115 static Register from_code(int code) { | 113 static Register from_code(int code) { |
| 116 DCHECK(code >= 0); | 114 Register r = { code }; |
| 117 DCHECK(code < kNumRegisters); | |
| 118 Register r = {code}; | |
| 119 return r; | 115 return r; |
| 120 } | 116 } |
| 121 const char* ToString(); | 117 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } |
| 122 bool IsAllocatable() const; | 118 bool is(Register reg) const { return code_ == reg.code_; } |
| 123 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } | 119 // rax, rbx, rcx and rdx are byte registers, the rest are not. |
| 124 bool is(Register reg) const { return reg_code == reg.reg_code; } | 120 bool is_byte_register() const { return code_ <= 3; } |
| 125 int code() const { | 121 int code() const { |
| 126 DCHECK(is_valid()); | 122 DCHECK(is_valid()); |
| 127 return reg_code; | 123 return code_; |
| 128 } | 124 } |
| 129 int bit() const { | 125 int bit() const { |
| 130 DCHECK(is_valid()); | 126 return 1 << code_; |
| 131 return 1 << reg_code; | 127 } |
| 132 } | 128 |
| 133 | |
| 134 bool is_byte_register() const { return reg_code <= 3; } | |
| 135 // Return the high bit of the register code as a 0 or 1. Used often | 129 // Return the high bit of the register code as a 0 or 1. Used often |
| 136 // when constructing the REX prefix byte. | 130 // when constructing the REX prefix byte. |
| 137 int high_bit() const { return reg_code >> 3; } | 131 int high_bit() const { |
| 132 return code_ >> 3; |
| 133 } |
| 138 // Return the 3 low bits of the register code. Used when encoding registers | 134 // Return the 3 low bits of the register code. Used when encoding registers |
| 139 // in modR/M, SIB, and opcode bytes. | 135 // in modR/M, SIB, and opcode bytes. |
| 140 int low_bits() const { return reg_code & 0x7; } | 136 int low_bits() const { |
| 137 return code_ & 0x7; |
| 138 } |
| 141 | 139 |
| 142 // Unfortunately we can't make this private in a struct when initializing | 140 // Unfortunately we can't make this private in a struct when initializing |
| 143 // by assignment. | 141 // by assignment. |
| 144 int reg_code; | 142 int code_; |
| 143 |
| 144 private: |
| 145 static const int kRegisterCodeByAllocationIndex[kMaxNumAllocatableRegisters]; |
| 146 static const int kAllocationIndexByRegisterCode[kNumRegisters]; |
| 145 }; | 147 }; |
| 146 | 148 |
| 147 | 149 const int kRegister_rax_Code = 0; |
| 148 #define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R}; | 150 const int kRegister_rcx_Code = 1; |
| 149 GENERAL_REGISTERS(DECLARE_REGISTER) | 151 const int kRegister_rdx_Code = 2; |
| 150 #undef DECLARE_REGISTER | 152 const int kRegister_rbx_Code = 3; |
| 151 const Register no_reg = {Register::kCode_no_reg}; | 153 const int kRegister_rsp_Code = 4; |
| 152 | 154 const int kRegister_rbp_Code = 5; |
| 155 const int kRegister_rsi_Code = 6; |
| 156 const int kRegister_rdi_Code = 7; |
| 157 const int kRegister_r8_Code = 8; |
| 158 const int kRegister_r9_Code = 9; |
| 159 const int kRegister_r10_Code = 10; |
| 160 const int kRegister_r11_Code = 11; |
| 161 const int kRegister_r12_Code = 12; |
| 162 const int kRegister_r13_Code = 13; |
| 163 const int kRegister_r14_Code = 14; |
| 164 const int kRegister_r15_Code = 15; |
| 165 const int kRegister_no_reg_Code = -1; |
| 166 |
| 167 const Register rax = { kRegister_rax_Code }; |
| 168 const Register rcx = { kRegister_rcx_Code }; |
| 169 const Register rdx = { kRegister_rdx_Code }; |
| 170 const Register rbx = { kRegister_rbx_Code }; |
| 171 const Register rsp = { kRegister_rsp_Code }; |
| 172 const Register rbp = { kRegister_rbp_Code }; |
| 173 const Register rsi = { kRegister_rsi_Code }; |
| 174 const Register rdi = { kRegister_rdi_Code }; |
| 175 const Register r8 = { kRegister_r8_Code }; |
| 176 const Register r9 = { kRegister_r9_Code }; |
| 177 const Register r10 = { kRegister_r10_Code }; |
| 178 const Register r11 = { kRegister_r11_Code }; |
| 179 const Register r12 = { kRegister_r12_Code }; |
| 180 const Register r13 = { kRegister_r13_Code }; |
| 181 const Register r14 = { kRegister_r14_Code }; |
| 182 const Register r15 = { kRegister_r15_Code }; |
| 183 const Register no_reg = { kRegister_no_reg_Code }; |
| 153 | 184 |
| 154 #ifdef _WIN64 | 185 #ifdef _WIN64 |
| 155 // Windows calling convention | 186 // Windows calling convention |
| 156 const Register arg_reg_1 = {Register::kCode_rcx}; | 187 const Register arg_reg_1 = { kRegister_rcx_Code }; |
| 157 const Register arg_reg_2 = {Register::kCode_rdx}; | 188 const Register arg_reg_2 = { kRegister_rdx_Code }; |
| 158 const Register arg_reg_3 = {Register::kCode_r8}; | 189 const Register arg_reg_3 = { kRegister_r8_Code }; |
| 159 const Register arg_reg_4 = {Register::kCode_r9}; | 190 const Register arg_reg_4 = { kRegister_r9_Code }; |
| 160 #else | 191 #else |
| 161 // AMD64 calling convention | 192 // AMD64 calling convention |
| 162 const Register arg_reg_1 = {Register::kCode_rdi}; | 193 const Register arg_reg_1 = { kRegister_rdi_Code }; |
| 163 const Register arg_reg_2 = {Register::kCode_rsi}; | 194 const Register arg_reg_2 = { kRegister_rsi_Code }; |
| 164 const Register arg_reg_3 = {Register::kCode_rdx}; | 195 const Register arg_reg_3 = { kRegister_rdx_Code }; |
| 165 const Register arg_reg_4 = {Register::kCode_rcx}; | 196 const Register arg_reg_4 = { kRegister_rcx_Code }; |
| 166 #endif // _WIN64 | 197 #endif // _WIN64 |
| 167 | 198 |
| 168 | 199 struct XMMRegister { |
| 169 #define DOUBLE_REGISTERS(V) \ | 200 static const int kMaxNumRegisters = 16; |
| 170 V(xmm0) \ | 201 static const int kMaxNumAllocatableRegisters = 15; |
| 171 V(xmm1) \ | 202 static int NumAllocatableRegisters() { |
| 172 V(xmm2) \ | 203 return kMaxNumAllocatableRegisters; |
| 173 V(xmm3) \ | 204 } |
| 174 V(xmm4) \ | 205 |
| 175 V(xmm5) \ | 206 // TODO(turbofan): Proper support for float32. |
| 176 V(xmm6) \ | 207 static int NumAllocatableAliasedRegisters() { |
| 177 V(xmm7) \ | 208 return NumAllocatableRegisters(); |
| 178 V(xmm8) \ | 209 } |
| 179 V(xmm9) \ | 210 |
| 180 V(xmm10) \ | 211 static int ToAllocationIndex(XMMRegister reg) { |
| 181 V(xmm11) \ | 212 DCHECK(reg.code() != 0); |
| 182 V(xmm12) \ | 213 return reg.code() - 1; |
| 183 V(xmm13) \ | 214 } |
| 184 V(xmm14) \ | 215 |
| 185 V(xmm15) | 216 static XMMRegister FromAllocationIndex(int index) { |
| 186 | 217 DCHECK(0 <= index && index < kMaxNumAllocatableRegisters); |
| 187 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \ | 218 XMMRegister result = { index + 1 }; |
| 188 V(xmm1) \ | |
| 189 V(xmm2) \ | |
| 190 V(xmm3) \ | |
| 191 V(xmm4) \ | |
| 192 V(xmm5) \ | |
| 193 V(xmm6) \ | |
| 194 V(xmm7) \ | |
| 195 V(xmm8) \ | |
| 196 V(xmm9) \ | |
| 197 V(xmm10) \ | |
| 198 V(xmm11) \ | |
| 199 V(xmm12) \ | |
| 200 V(xmm13) \ | |
| 201 V(xmm14) \ | |
| 202 V(xmm15) | |
| 203 | |
| 204 | |
| 205 struct DoubleRegister { | |
| 206 enum Code { | |
| 207 #define REGISTER_CODE(R) kCode_##R, | |
| 208 DOUBLE_REGISTERS(REGISTER_CODE) | |
| 209 #undef REGISTER_CODE | |
| 210 kAfterLast, | |
| 211 kCode_no_reg = -1 | |
| 212 }; | |
| 213 | |
| 214 static const int kMaxNumRegisters = Code::kAfterLast; | |
| 215 | |
| 216 static DoubleRegister from_code(int code) { | |
| 217 DoubleRegister result = {code}; | |
| 218 return result; | 219 return result; |
| 219 } | 220 } |
| 220 | 221 |
| 221 const char* ToString(); | 222 static const char* AllocationIndexToString(int index) { |
| 222 bool IsAllocatable() const; | 223 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); |
| 223 bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; } | 224 const char* const names[] = { |
| 224 bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; } | 225 "xmm1", |
| 226 "xmm2", |
| 227 "xmm3", |
| 228 "xmm4", |
| 229 "xmm5", |
| 230 "xmm6", |
| 231 "xmm7", |
| 232 "xmm8", |
| 233 "xmm9", |
| 234 "xmm10", |
| 235 "xmm11", |
| 236 "xmm12", |
| 237 "xmm13", |
| 238 "xmm14", |
| 239 "xmm15" |
| 240 }; |
| 241 return names[index]; |
| 242 } |
| 243 |
| 244 static XMMRegister from_code(int code) { |
| 245 DCHECK(code >= 0); |
| 246 DCHECK(code < kMaxNumRegisters); |
| 247 XMMRegister r = { code }; |
| 248 return r; |
| 249 } |
| 250 bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters; } |
| 251 bool is(XMMRegister reg) const { return code_ == reg.code_; } |
| 225 int code() const { | 252 int code() const { |
| 226 DCHECK(is_valid()); | 253 DCHECK(is_valid()); |
| 227 return reg_code; | 254 return code_; |
| 228 } | 255 } |
| 229 | 256 |
| 230 // Return the high bit of the register code as a 0 or 1. Used often | 257 // Return the high bit of the register code as a 0 or 1. Used often |
| 231 // when constructing the REX prefix byte. | 258 // when constructing the REX prefix byte. |
| 232 int high_bit() const { return reg_code >> 3; } | 259 int high_bit() const { |
| 260 return code_ >> 3; |
| 261 } |
| 233 // Return the 3 low bits of the register code. Used when encoding registers | 262 // Return the 3 low bits of the register code. Used when encoding registers |
| 234 // in modR/M, SIB, and opcode bytes. | 263 // in modR/M, SIB, and opcode bytes. |
| 235 int low_bits() const { return reg_code & 0x7; } | 264 int low_bits() const { |
| 236 | 265 return code_ & 0x7; |
| 237 // Unfortunately we can't make this private in a struct when initializing | 266 } |
| 238 // by assignment. | 267 |
| 239 int reg_code; | 268 int code_; |
| 240 }; | 269 }; |
| 241 | 270 |
| 242 | 271 const XMMRegister xmm0 = { 0 }; |
| 243 #define DECLARE_REGISTER(R) \ | 272 const XMMRegister xmm1 = { 1 }; |
| 244 const DoubleRegister R = {DoubleRegister::kCode_##R}; | 273 const XMMRegister xmm2 = { 2 }; |
| 245 DOUBLE_REGISTERS(DECLARE_REGISTER) | 274 const XMMRegister xmm3 = { 3 }; |
| 246 #undef DECLARE_REGISTER | 275 const XMMRegister xmm4 = { 4 }; |
| 247 const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg}; | 276 const XMMRegister xmm5 = { 5 }; |
| 248 | 277 const XMMRegister xmm6 = { 6 }; |
| 249 | 278 const XMMRegister xmm7 = { 7 }; |
| 250 typedef DoubleRegister XMMRegister; | 279 const XMMRegister xmm8 = { 8 }; |
| 280 const XMMRegister xmm9 = { 9 }; |
| 281 const XMMRegister xmm10 = { 10 }; |
| 282 const XMMRegister xmm11 = { 11 }; |
| 283 const XMMRegister xmm12 = { 12 }; |
| 284 const XMMRegister xmm13 = { 13 }; |
| 285 const XMMRegister xmm14 = { 14 }; |
| 286 const XMMRegister xmm15 = { 15 }; |
| 287 |
| 288 |
| 289 typedef XMMRegister DoubleRegister; |
| 290 |
| 251 | 291 |
| 252 enum Condition { | 292 enum Condition { |
| 253 // any value < 0 is considered no_condition | 293 // any value < 0 is considered no_condition |
| 254 no_condition = -1, | 294 no_condition = -1, |
| 255 | 295 |
| 256 overflow = 0, | 296 overflow = 0, |
| 257 no_overflow = 1, | 297 no_overflow = 1, |
| 258 below = 2, | 298 below = 2, |
| 259 above_equal = 3, | 299 above_equal = 3, |
| 260 equal = 4, | 300 equal = 4, |
| (...skipping 1843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2104 private: | 2144 private: |
| 2105 Assembler* assembler_; | 2145 Assembler* assembler_; |
| 2106 #ifdef DEBUG | 2146 #ifdef DEBUG |
| 2107 int space_before_; | 2147 int space_before_; |
| 2108 #endif | 2148 #endif |
| 2109 }; | 2149 }; |
| 2110 | 2150 |
| 2111 } } // namespace v8::internal | 2151 } } // namespace v8::internal |
| 2112 | 2152 |
| 2113 #endif // V8_X64_ASSEMBLER_X64_H_ | 2153 #endif // V8_X64_ASSEMBLER_X64_H_ |
| OLD | NEW |