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