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 1844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 internal | 2151 } // namespace internal |
2112 } // namespace v8 | 2152 } // namespace v8 |
2113 | 2153 |
2114 #endif // V8_X64_ASSEMBLER_X64_H_ | 2154 #endif // V8_X64_ASSEMBLER_X64_H_ |
OLD | NEW |