| 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 12 matching lines...) Expand all Loading... |
| 23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| 27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 | 30 |
| 31 // The original source code covered by the above license above has been | 31 // The original source code covered by the above license above has been |
| 32 // modified significantly by Google Inc. | 32 // modified significantly by Google Inc. |
| 33 // Copyright 2010 the V8 project authors. All rights reserved. | 33 // Copyright 2011 the V8 project authors. All rights reserved. |
| 34 | 34 |
| 35 // A light-weight IA32 Assembler. | 35 // A light-weight IA32 Assembler. |
| 36 | 36 |
| 37 #ifndef V8_IA32_ASSEMBLER_IA32_H_ | 37 #ifndef V8_IA32_ASSEMBLER_IA32_H_ |
| 38 #define V8_IA32_ASSEMBLER_IA32_H_ | 38 #define V8_IA32_ASSEMBLER_IA32_H_ |
| 39 | 39 |
| 40 #include "isolate.h" | 40 #include "isolate.h" |
| 41 #include "serialize.h" | 41 #include "serialize.h" |
| 42 | 42 |
| 43 namespace v8 { | 43 namespace v8 { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 58 // | 58 // |
| 59 // 3) By not using an enum, we are possibly preventing the compiler from | 59 // 3) By not using an enum, we are possibly preventing the compiler from |
| 60 // doing certain constant folds, which may significantly reduce the | 60 // doing certain constant folds, which may significantly reduce the |
| 61 // code generated for some assembly instructions (because they boil down | 61 // code generated for some assembly instructions (because they boil down |
| 62 // to a few constants). If this is a problem, we could change the code | 62 // to a few constants). If this is a problem, we could change the code |
| 63 // such that we use an enum in optimized mode, and the struct in debug | 63 // such that we use an enum in optimized mode, and the struct in debug |
| 64 // mode. This way we get the compile-time error checking in debug mode | 64 // mode. This way we get the compile-time error checking in debug mode |
| 65 // and best performance in optimized code. | 65 // and best performance in optimized code. |
| 66 // | 66 // |
| 67 struct Register { | 67 struct Register { |
| 68 static const int kNumAllocatableRegisters = 5; | 68 static const int kNumAllocatableRegisters = 6; |
| 69 static const int kNumRegisters = 8; | 69 static const int kNumRegisters = 8; |
| 70 | 70 |
| 71 static int ToAllocationIndex(Register reg) { | 71 static inline const char* AllocationIndexToString(int index); |
| 72 ASSERT(reg.code() < 4 || reg.code() == 7); | |
| 73 return (reg.code() == 7) ? 4 : reg.code(); | |
| 74 } | |
| 75 | 72 |
| 76 static Register FromAllocationIndex(int index) { | 73 static inline int ToAllocationIndex(Register reg); |
| 77 ASSERT(index >= 0 && index < kNumAllocatableRegisters); | |
| 78 return (index == 4) ? from_code(7) : from_code(index); | |
| 79 } | |
| 80 | 74 |
| 81 static const char* AllocationIndexToString(int index) { | 75 static inline Register FromAllocationIndex(int index); |
| 82 ASSERT(index >= 0 && index < kNumAllocatableRegisters); | |
| 83 const char* const names[] = { | |
| 84 "eax", | |
| 85 "ecx", | |
| 86 "edx", | |
| 87 "ebx", | |
| 88 "edi" | |
| 89 }; | |
| 90 return names[index]; | |
| 91 } | |
| 92 | 76 |
| 93 static Register from_code(int code) { | 77 static Register from_code(int code) { |
| 94 Register r = { code }; | 78 Register r = { code }; |
| 95 return r; | 79 return r; |
| 96 } | 80 } |
| 97 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } | 81 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } |
| 98 bool is(Register reg) const { return code_ == reg.code_; } | 82 bool is(Register reg) const { return code_ == reg.code_; } |
| 99 // eax, ebx, ecx and edx are byte registers, the rest are not. | 83 // eax, ebx, ecx and edx are byte registers, the rest are not. |
| 100 bool is_byte_register() const { return code_ <= 3; } | 84 bool is_byte_register() const { return code_ <= 3; } |
| 101 int code() const { | 85 int code() const { |
| 102 ASSERT(is_valid()); | 86 ASSERT(is_valid()); |
| 103 return code_; | 87 return code_; |
| 104 } | 88 } |
| 105 int bit() const { | 89 int bit() const { |
| 106 ASSERT(is_valid()); | 90 ASSERT(is_valid()); |
| 107 return 1 << code_; | 91 return 1 << code_; |
| 108 } | 92 } |
| 109 | 93 |
| 110 // Unfortunately we can't make this private in a struct. | 94 // Unfortunately we can't make this private in a struct. |
| 111 int code_; | 95 int code_; |
| 112 }; | 96 }; |
| 113 | 97 |
| 98 |
| 114 const Register eax = { 0 }; | 99 const Register eax = { 0 }; |
| 115 const Register ecx = { 1 }; | 100 const Register ecx = { 1 }; |
| 116 const Register edx = { 2 }; | 101 const Register edx = { 2 }; |
| 117 const Register ebx = { 3 }; | 102 const Register ebx = { 3 }; |
| 118 const Register esp = { 4 }; | 103 const Register esp = { 4 }; |
| 119 const Register ebp = { 5 }; | 104 const Register ebp = { 5 }; |
| 120 const Register esi = { 6 }; | 105 const Register esi = { 6 }; |
| 121 const Register edi = { 7 }; | 106 const Register edi = { 7 }; |
| 122 const Register no_reg = { -1 }; | 107 const Register no_reg = { -1 }; |
| 123 | 108 |
| 124 | 109 |
| 110 inline const char* Register::AllocationIndexToString(int index) { |
| 111 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
| 112 // This is the mapping of allocation indices to registers. |
| 113 const char* const kNames[] = { "eax", "ecx", "edx", "ebx", "esi", "edi" }; |
| 114 return kNames[index]; |
| 115 } |
| 116 |
| 117 |
| 118 inline int Register::ToAllocationIndex(Register reg) { |
| 119 ASSERT(reg.is_valid() && !reg.is(esp) && !reg.is(ebp)); |
| 120 return (reg.code() >= 6) ? reg.code() - 2 : reg.code(); |
| 121 } |
| 122 |
| 123 |
| 124 inline Register Register::FromAllocationIndex(int index) { |
| 125 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
| 126 return (index >= 4) ? from_code(index + 2) : from_code(index); |
| 127 } |
| 128 |
| 129 |
| 125 struct XMMRegister { | 130 struct XMMRegister { |
| 126 static const int kNumAllocatableRegisters = 7; | 131 static const int kNumAllocatableRegisters = 7; |
| 127 static const int kNumRegisters = 8; | 132 static const int kNumRegisters = 8; |
| 128 | 133 |
| 129 static int ToAllocationIndex(XMMRegister reg) { | 134 static int ToAllocationIndex(XMMRegister reg) { |
| 130 ASSERT(reg.code() != 0); | 135 ASSERT(reg.code() != 0); |
| 131 return reg.code() - 1; | 136 return reg.code() - 1; |
| 132 } | 137 } |
| 133 | 138 |
| 134 static XMMRegister FromAllocationIndex(int index) { | 139 static XMMRegister FromAllocationIndex(int index) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 const XMMRegister xmm3 = { 3 }; | 177 const XMMRegister xmm3 = { 3 }; |
| 173 const XMMRegister xmm4 = { 4 }; | 178 const XMMRegister xmm4 = { 4 }; |
| 174 const XMMRegister xmm5 = { 5 }; | 179 const XMMRegister xmm5 = { 5 }; |
| 175 const XMMRegister xmm6 = { 6 }; | 180 const XMMRegister xmm6 = { 6 }; |
| 176 const XMMRegister xmm7 = { 7 }; | 181 const XMMRegister xmm7 = { 7 }; |
| 177 | 182 |
| 178 | 183 |
| 179 typedef XMMRegister DoubleRegister; | 184 typedef XMMRegister DoubleRegister; |
| 180 | 185 |
| 181 | 186 |
| 182 // Index of register used in pusha/popa. | |
| 183 // Order of pushed registers: EAX, ECX, EDX, EBX, ESP, EBP, ESI, and EDI | |
| 184 inline int EspIndexForPushAll(Register reg) { | |
| 185 return Register::kNumRegisters - 1 - reg.code(); | |
| 186 } | |
| 187 | |
| 188 | |
| 189 enum Condition { | 187 enum Condition { |
| 190 // any value < 0 is considered no_condition | 188 // any value < 0 is considered no_condition |
| 191 no_condition = -1, | 189 no_condition = -1, |
| 192 | 190 |
| 193 overflow = 0, | 191 overflow = 0, |
| 194 no_overflow = 1, | 192 no_overflow = 1, |
| 195 below = 2, | 193 below = 2, |
| 196 above_equal = 3, | 194 above_equal = 3, |
| 197 equal = 4, | 195 equal = 4, |
| 198 not_equal = 5, | 196 not_equal = 5, |
| (...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 961 // Check the code size generated from label to here. | 959 // Check the code size generated from label to here. |
| 962 int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); } | 960 int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); } |
| 963 | 961 |
| 964 // Mark address of the ExitJSFrame code. | 962 // Mark address of the ExitJSFrame code. |
| 965 void RecordJSReturn(); | 963 void RecordJSReturn(); |
| 966 | 964 |
| 967 // Mark address of a debug break slot. | 965 // Mark address of a debug break slot. |
| 968 void RecordDebugBreakSlot(); | 966 void RecordDebugBreakSlot(); |
| 969 | 967 |
| 970 // Record a comment relocation entry that can be used by a disassembler. | 968 // Record a comment relocation entry that can be used by a disassembler. |
| 971 // Use --code-comments to enable. | 969 // Use --code-comments to enable, or provide "force = true" flag to always |
| 972 void RecordComment(const char* msg); | 970 // write a comment. |
| 971 void RecordComment(const char* msg, bool force = false); |
| 973 | 972 |
| 974 // Writes a single byte or word of data in the code stream. Used for | 973 // Writes a single byte or word of data in the code stream. Used for |
| 975 // inline tables, e.g., jump-tables. | 974 // inline tables, e.g., jump-tables. |
| 976 void db(uint8_t data); | 975 void db(uint8_t data); |
| 977 void dd(uint32_t data); | 976 void dd(uint32_t data); |
| 978 | 977 |
| 979 int pc_offset() const { return pc_ - buffer_; } | 978 int pc_offset() const { return pc_ - buffer_; } |
| 980 | 979 |
| 981 // Check if there is less than kGap bytes available in the buffer. | 980 // Check if there is less than kGap bytes available in the buffer. |
| 982 // If this is the case, we need to grow the buffer before emitting | 981 // If this is the case, we need to grow the buffer before emitting |
| 983 // an instruction or relocation information. | 982 // an instruction or relocation information. |
| 984 inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; } | 983 inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; } |
| 985 | 984 |
| 986 // Get the number of bytes available in the buffer. | 985 // Get the number of bytes available in the buffer. |
| 987 inline int available_space() const { return reloc_info_writer.pos() - pc_; } | 986 inline int available_space() const { return reloc_info_writer.pos() - pc_; } |
| 988 | 987 |
| 989 static bool IsNop(Address addr) { return *addr == 0x90; } | 988 static bool IsNop(Address addr) { return *addr == 0x90; } |
| 990 | 989 |
| 991 PositionsRecorder* positions_recorder() { return &positions_recorder_; } | 990 PositionsRecorder* positions_recorder() { return &positions_recorder_; } |
| 992 | 991 |
| 992 int relocation_writer_size() { |
| 993 return (buffer_ + buffer_size_) - reloc_info_writer.pos(); |
| 994 } |
| 995 |
| 993 // Avoid overflows for displacements etc. | 996 // Avoid overflows for displacements etc. |
| 994 static const int kMaximalBufferSize = 512*MB; | 997 static const int kMaximalBufferSize = 512*MB; |
| 995 static const int kMinimalBufferSize = 4*KB; | 998 static const int kMinimalBufferSize = 4*KB; |
| 996 | 999 |
| 997 protected: | 1000 protected: |
| 998 void movsd(XMMRegister dst, const Operand& src); | 1001 void movsd(XMMRegister dst, const Operand& src); |
| 999 void movsd(const Operand& dst, XMMRegister src); | 1002 void movsd(const Operand& dst, XMMRegister src); |
| 1000 | 1003 |
| 1001 void emit_sse_operand(XMMRegister reg, const Operand& adr); | 1004 void emit_sse_operand(XMMRegister reg, const Operand& adr); |
| 1002 void emit_sse_operand(XMMRegister dst, XMMRegister src); | 1005 void emit_sse_operand(XMMRegister dst, XMMRegister src); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1095 private: | 1098 private: |
| 1096 Assembler* assembler_; | 1099 Assembler* assembler_; |
| 1097 #ifdef DEBUG | 1100 #ifdef DEBUG |
| 1098 int space_before_; | 1101 int space_before_; |
| 1099 #endif | 1102 #endif |
| 1100 }; | 1103 }; |
| 1101 | 1104 |
| 1102 } } // namespace v8::internal | 1105 } } // namespace v8::internal |
| 1103 | 1106 |
| 1104 #endif // V8_IA32_ASSEMBLER_IA32_H_ | 1107 #endif // V8_IA32_ASSEMBLER_IA32_H_ |
| OLD | NEW |