| 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 |