| 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 2006-2008 the V8 project authors. All rights reserved. | 33 // Copyright 2010 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 bool is_valid() const { return 0 <= code_ && code_ < 8; } | 68 static const int kNumAllocatableRegisters = 5; |
| 69 static const int kNumRegisters = 8; |
| 70 |
| 71 static int ToAllocationIndex(Register reg) { |
| 72 ASSERT(reg.code() < 4 || reg.code() == 7); |
| 73 return (reg.code() == 7) ? 4 : reg.code(); |
| 74 } |
| 75 |
| 76 static Register FromAllocationIndex(int index) { |
| 77 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
| 78 return (index == 4) ? from_code(7) : from_code(index); |
| 79 } |
| 80 |
| 81 static const char* AllocationIndexToString(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 |
| 93 static Register from_code(int code) { |
| 94 Register r = { code }; |
| 95 return r; |
| 96 } |
| 97 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } |
| 69 bool is(Register reg) const { return code_ == reg.code_; } | 98 bool is(Register reg) const { return code_ == reg.code_; } |
| 70 // eax, ebx, ecx and edx are byte registers, the rest are not. | 99 // eax, ebx, ecx and edx are byte registers, the rest are not. |
| 71 bool is_byte_register() const { return code_ <= 3; } | 100 bool is_byte_register() const { return code_ <= 3; } |
| 72 int code() const { | 101 int code() const { |
| 73 ASSERT(is_valid()); | 102 ASSERT(is_valid()); |
| 74 return code_; | 103 return code_; |
| 75 } | 104 } |
| 76 int bit() const { | 105 int bit() const { |
| 77 ASSERT(is_valid()); | 106 ASSERT(is_valid()); |
| 78 return 1 << code_; | 107 return 1 << code_; |
| 79 } | 108 } |
| 80 | 109 |
| 81 // Unfortunately we can't make this private in a struct. | 110 // Unfortunately we can't make this private in a struct. |
| 82 int code_; | 111 int code_; |
| 83 }; | 112 }; |
| 84 | 113 |
| 85 const Register eax = { 0 }; | 114 const Register eax = { 0 }; |
| 86 const Register ecx = { 1 }; | 115 const Register ecx = { 1 }; |
| 87 const Register edx = { 2 }; | 116 const Register edx = { 2 }; |
| 88 const Register ebx = { 3 }; | 117 const Register ebx = { 3 }; |
| 89 const Register esp = { 4 }; | 118 const Register esp = { 4 }; |
| 90 const Register ebp = { 5 }; | 119 const Register ebp = { 5 }; |
| 91 const Register esi = { 6 }; | 120 const Register esi = { 6 }; |
| 92 const Register edi = { 7 }; | 121 const Register edi = { 7 }; |
| 93 const Register no_reg = { -1 }; | 122 const Register no_reg = { -1 }; |
| 94 | 123 |
| 95 | 124 |
| 96 struct XMMRegister { | 125 struct XMMRegister { |
| 97 bool is_valid() const { return 0 <= code_ && code_ < 8; } | 126 static const int kNumAllocatableRegisters = 7; |
| 127 static const int kNumRegisters = 8; |
| 128 |
| 129 static int ToAllocationIndex(XMMRegister reg) { |
| 130 ASSERT(reg.code() != 0); |
| 131 return reg.code() - 1; |
| 132 } |
| 133 |
| 134 static XMMRegister FromAllocationIndex(int index) { |
| 135 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
| 136 return from_code(index + 1); |
| 137 } |
| 138 |
| 139 static const char* AllocationIndexToString(int index) { |
| 140 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
| 141 const char* const names[] = { |
| 142 "xmm1", |
| 143 "xmm2", |
| 144 "xmm3", |
| 145 "xmm4", |
| 146 "xmm5", |
| 147 "xmm6", |
| 148 "xmm7" |
| 149 }; |
| 150 return names[index]; |
| 151 } |
| 152 |
| 153 static XMMRegister from_code(int code) { |
| 154 XMMRegister r = { code }; |
| 155 return r; |
| 156 } |
| 157 |
| 158 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } |
| 159 bool is(XMMRegister reg) const { return code_ == reg.code_; } |
| 98 int code() const { | 160 int code() const { |
| 99 ASSERT(is_valid()); | 161 ASSERT(is_valid()); |
| 100 return code_; | 162 return code_; |
| 101 } | 163 } |
| 102 | 164 |
| 103 int code_; | 165 int code_; |
| 104 }; | 166 }; |
| 105 | 167 |
| 168 |
| 106 const XMMRegister xmm0 = { 0 }; | 169 const XMMRegister xmm0 = { 0 }; |
| 107 const XMMRegister xmm1 = { 1 }; | 170 const XMMRegister xmm1 = { 1 }; |
| 108 const XMMRegister xmm2 = { 2 }; | 171 const XMMRegister xmm2 = { 2 }; |
| 109 const XMMRegister xmm3 = { 3 }; | 172 const XMMRegister xmm3 = { 3 }; |
| 110 const XMMRegister xmm4 = { 4 }; | 173 const XMMRegister xmm4 = { 4 }; |
| 111 const XMMRegister xmm5 = { 5 }; | 174 const XMMRegister xmm5 = { 5 }; |
| 112 const XMMRegister xmm6 = { 6 }; | 175 const XMMRegister xmm6 = { 6 }; |
| 113 const XMMRegister xmm7 = { 7 }; | 176 const XMMRegister xmm7 = { 7 }; |
| 114 | 177 |
| 178 |
| 179 typedef XMMRegister DoubleRegister; |
| 180 |
| 181 |
| 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 |
| 115 enum Condition { | 189 enum Condition { |
| 116 // any value < 0 is considered no_condition | 190 // any value < 0 is considered no_condition |
| 117 no_condition = -1, | 191 no_condition = -1, |
| 118 | 192 |
| 119 overflow = 0, | 193 overflow = 0, |
| 120 no_overflow = 1, | 194 no_overflow = 1, |
| 121 below = 2, | 195 below = 2, |
| 122 above_equal = 3, | 196 above_equal = 3, |
| 123 equal = 4, | 197 equal = 4, |
| 124 not_equal = 5, | 198 not_equal = 5, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 | 270 |
| 197 // ----------------------------------------------------------------------------- | 271 // ----------------------------------------------------------------------------- |
| 198 // Machine instruction Immediates | 272 // Machine instruction Immediates |
| 199 | 273 |
| 200 class Immediate BASE_EMBEDDED { | 274 class Immediate BASE_EMBEDDED { |
| 201 public: | 275 public: |
| 202 inline explicit Immediate(int x); | 276 inline explicit Immediate(int x); |
| 203 inline explicit Immediate(const ExternalReference& ext); | 277 inline explicit Immediate(const ExternalReference& ext); |
| 204 inline explicit Immediate(Handle<Object> handle); | 278 inline explicit Immediate(Handle<Object> handle); |
| 205 inline explicit Immediate(Smi* value); | 279 inline explicit Immediate(Smi* value); |
| 280 inline explicit Immediate(Address addr); |
| 206 | 281 |
| 207 static Immediate CodeRelativeOffset(Label* label) { | 282 static Immediate CodeRelativeOffset(Label* label) { |
| 208 return Immediate(label); | 283 return Immediate(label); |
| 209 } | 284 } |
| 210 | 285 |
| 211 bool is_zero() const { return x_ == 0 && rmode_ == RelocInfo::NONE; } | 286 bool is_zero() const { return x_ == 0 && rmode_ == RelocInfo::NONE; } |
| 212 bool is_int8() const { | 287 bool is_int8() const { |
| 213 return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE; | 288 return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE; |
| 214 } | 289 } |
| 215 bool is_int16() const { | 290 bool is_int16() const { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 RelocInfo::EXTERNAL_REFERENCE); | 350 RelocInfo::EXTERNAL_REFERENCE); |
| 276 } | 351 } |
| 277 | 352 |
| 278 static Operand StaticArray(Register index, | 353 static Operand StaticArray(Register index, |
| 279 ScaleFactor scale, | 354 ScaleFactor scale, |
| 280 const ExternalReference& arr) { | 355 const ExternalReference& arr) { |
| 281 return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()), | 356 return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()), |
| 282 RelocInfo::EXTERNAL_REFERENCE); | 357 RelocInfo::EXTERNAL_REFERENCE); |
| 283 } | 358 } |
| 284 | 359 |
| 360 static Operand Cell(Handle<JSGlobalPropertyCell> cell) { |
| 361 return Operand(reinterpret_cast<int32_t>(cell.location()), |
| 362 RelocInfo::GLOBAL_PROPERTY_CELL); |
| 363 } |
| 364 |
| 285 // Returns true if this Operand is a wrapper for the specified register. | 365 // Returns true if this Operand is a wrapper for the specified register. |
| 286 bool is_reg(Register reg) const; | 366 bool is_reg(Register reg) const; |
| 287 | 367 |
| 288 private: | 368 private: |
| 289 byte buf_[6]; | 369 byte buf_[6]; |
| 290 // The number of bytes in buf_. | 370 // The number of bytes in buf_. |
| 291 unsigned int len_; | 371 unsigned int len_; |
| 292 // Only valid if len_ > 4. | 372 // Only valid if len_ > 4. |
| 293 RelocInfo::Mode rmode_; | 373 RelocInfo::Mode rmode_; |
| 294 | 374 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 // Supported features must be enabled by a Scope before use. | 443 // Supported features must be enabled by a Scope before use. |
| 364 // Example: | 444 // Example: |
| 365 // if (CpuFeatures::IsSupported(SSE2)) { | 445 // if (CpuFeatures::IsSupported(SSE2)) { |
| 366 // CpuFeatures::Scope fscope(SSE2); | 446 // CpuFeatures::Scope fscope(SSE2); |
| 367 // // Generate SSE2 floating point code. | 447 // // Generate SSE2 floating point code. |
| 368 // } else { | 448 // } else { |
| 369 // // Generate standard x87 floating point code. | 449 // // Generate standard x87 floating point code. |
| 370 // } | 450 // } |
| 371 class CpuFeatures { | 451 class CpuFeatures { |
| 372 public: | 452 public: |
| 373 // Detect features of the target CPU. Set safe defaults if the serializer | 453 // Detect features of the target CPU. If the portable flag is set, |
| 374 // is enabled (snapshots must be portable). | 454 // the method sets safe defaults if the serializer is enabled |
| 375 void Probe(); | 455 // (snapshots must be portable). |
| 456 void Probe(bool portable); |
| 457 void Clear() { supported_ = 0; } |
| 458 |
| 376 // Check whether a feature is supported by the target CPU. | 459 // Check whether a feature is supported by the target CPU. |
| 377 bool IsSupported(CpuFeature f) const { | 460 bool IsSupported(CpuFeature f) const { |
| 378 if (f == SSE2 && !FLAG_enable_sse2) return false; | 461 if (f == SSE2 && !FLAG_enable_sse2) return false; |
| 379 if (f == SSE3 && !FLAG_enable_sse3) return false; | 462 if (f == SSE3 && !FLAG_enable_sse3) return false; |
| 380 if (f == SSE4_1 && !FLAG_enable_sse4_1) return false; | 463 if (f == SSE4_1 && !FLAG_enable_sse4_1) return false; |
| 381 if (f == CMOV && !FLAG_enable_cmov) return false; | 464 if (f == CMOV && !FLAG_enable_cmov) return false; |
| 382 if (f == RDTSC && !FLAG_enable_rdtsc) return false; | 465 if (f == RDTSC && !FLAG_enable_rdtsc) return false; |
| 383 return (supported_ & (static_cast<uint64_t>(1) << f)) != 0; | 466 return (supported_ & (static_cast<uint64_t>(1) << f)) != 0; |
| 384 } | 467 } |
| 385 // Check whether a feature is currently enabled. | 468 // Check whether a feature is currently enabled. |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 // Distance between start of patched debug break slot and the emitted address | 576 // Distance between start of patched debug break slot and the emitted address |
| 494 // to jump to. | 577 // to jump to. |
| 495 static const int kPatchDebugBreakSlotAddressOffset = 1; // JMP imm32. | 578 static const int kPatchDebugBreakSlotAddressOffset = 1; // JMP imm32. |
| 496 | 579 |
| 497 static const int kCallInstructionLength = 5; | 580 static const int kCallInstructionLength = 5; |
| 498 static const int kJSReturnSequenceLength = 6; | 581 static const int kJSReturnSequenceLength = 6; |
| 499 | 582 |
| 500 // The debug break slot must be able to contain a call instruction. | 583 // The debug break slot must be able to contain a call instruction. |
| 501 static const int kDebugBreakSlotLength = kCallInstructionLength; | 584 static const int kDebugBreakSlotLength = kCallInstructionLength; |
| 502 | 585 |
| 586 // One byte opcode for test eax,0xXXXXXXXX. |
| 587 static const byte kTestEaxByte = 0xA9; |
| 588 // One byte opcode for test al, 0xXX. |
| 589 static const byte kTestAlByte = 0xA8; |
| 590 |
| 503 // --------------------------------------------------------------------------- | 591 // --------------------------------------------------------------------------- |
| 504 // Code generation | 592 // Code generation |
| 505 // | 593 // |
| 506 // - function names correspond one-to-one to ia32 instruction mnemonics | 594 // - function names correspond one-to-one to ia32 instruction mnemonics |
| 507 // - unless specified otherwise, instructions operate on 32bit operands | 595 // - unless specified otherwise, instructions operate on 32bit operands |
| 508 // - instructions on 8bit (byte) operands/registers have a trailing '_b' | 596 // - instructions on 8bit (byte) operands/registers have a trailing '_b' |
| 509 // - instructions on 16bit (word) operands/registers have a trailing '_w' | 597 // - instructions on 16bit (word) operands/registers have a trailing '_w' |
| 510 // - naming conflicts with C++ keywords are resolved via a trailing '_' | 598 // - naming conflicts with C++ keywords are resolved via a trailing '_' |
| 511 | 599 |
| 512 // NOTE ON INTERFACE: Currently, the interface is not very consistent | 600 // NOTE ON INTERFACE: Currently, the interface is not very consistent |
| (...skipping 15 matching lines...) Expand all Loading... |
| 528 void CodeTargetAlign(); | 616 void CodeTargetAlign(); |
| 529 | 617 |
| 530 // Stack | 618 // Stack |
| 531 void pushad(); | 619 void pushad(); |
| 532 void popad(); | 620 void popad(); |
| 533 | 621 |
| 534 void pushfd(); | 622 void pushfd(); |
| 535 void popfd(); | 623 void popfd(); |
| 536 | 624 |
| 537 void push(const Immediate& x); | 625 void push(const Immediate& x); |
| 626 void push_imm32(int32_t imm32); |
| 538 void push(Register src); | 627 void push(Register src); |
| 539 void push(const Operand& src); | 628 void push(const Operand& src); |
| 540 | 629 |
| 541 void pop(Register dst); | 630 void pop(Register dst); |
| 542 void pop(const Operand& dst); | 631 void pop(const Operand& dst); |
| 543 | 632 |
| 544 void enter(const Immediate& size); | 633 void enter(const Immediate& size); |
| 545 void leave(); | 634 void leave(); |
| 546 | 635 |
| 547 // Moves | 636 // Moves |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 void movdqu(XMMRegister dst, const Operand& src); | 916 void movdqu(XMMRegister dst, const Operand& src); |
| 828 void movdqu(const Operand& dst, XMMRegister src); | 917 void movdqu(const Operand& dst, XMMRegister src); |
| 829 | 918 |
| 830 // Use either movsd or movlpd. | 919 // Use either movsd or movlpd. |
| 831 void movdbl(XMMRegister dst, const Operand& src); | 920 void movdbl(XMMRegister dst, const Operand& src); |
| 832 void movdbl(const Operand& dst, XMMRegister src); | 921 void movdbl(const Operand& dst, XMMRegister src); |
| 833 | 922 |
| 834 void movd(XMMRegister dst, const Operand& src); | 923 void movd(XMMRegister dst, const Operand& src); |
| 835 void movsd(XMMRegister dst, XMMRegister src); | 924 void movsd(XMMRegister dst, XMMRegister src); |
| 836 | 925 |
| 926 void pand(XMMRegister dst, XMMRegister src); |
| 837 void pxor(XMMRegister dst, XMMRegister src); | 927 void pxor(XMMRegister dst, XMMRegister src); |
| 838 void ptest(XMMRegister dst, XMMRegister src); | 928 void ptest(XMMRegister dst, XMMRegister src); |
| 839 | 929 |
| 840 void psllq(XMMRegister reg, int8_t imm8); | 930 void psllq(XMMRegister reg, int8_t imm8); |
| 841 | 931 |
| 842 // Parallel XMM operations. | 932 // Parallel XMM operations. |
| 843 void movntdqa(XMMRegister src, const Operand& dst); | 933 void movntdqa(XMMRegister src, const Operand& dst); |
| 844 void movntdq(const Operand& dst, XMMRegister src); | 934 void movntdq(const Operand& dst, XMMRegister src); |
| 845 // Prefetch src position into cache level. | 935 // Prefetch src position into cache level. |
| 846 // Level 1, 2 or 3 specifies CPU cache level. Level 0 specifies a | 936 // Level 1, 2 or 3 specifies CPU cache level. Level 0 specifies a |
| 847 // non-temporal | 937 // non-temporal |
| 848 void prefetch(const Operand& src, int level); | 938 void prefetch(const Operand& src, int level); |
| 849 // TODO(lrn): Need SFENCE for movnt? | 939 // TODO(lrn): Need SFENCE for movnt? |
| 850 | 940 |
| 851 // Debugging | 941 // Debugging |
| 852 void Print(); | 942 void Print(); |
| 853 | 943 |
| 854 // Check the code size generated from label to here. | 944 // Check the code size generated from label to here. |
| 855 int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); } | 945 int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); } |
| 856 | 946 |
| 857 // Mark address of the ExitJSFrame code. | 947 // Mark address of the ExitJSFrame code. |
| 858 void RecordJSReturn(); | 948 void RecordJSReturn(); |
| 859 | 949 |
| 860 // Mark address of a debug break slot. | 950 // Mark address of a debug break slot. |
| 861 void RecordDebugBreakSlot(); | 951 void RecordDebugBreakSlot(); |
| 862 | 952 |
| 863 // Record a comment relocation entry that can be used by a disassembler. | 953 // Record a comment relocation entry that can be used by a disassembler. |
| 864 // Use --debug_code to enable. | 954 // Use --code-comments to enable. |
| 865 void RecordComment(const char* msg); | 955 void RecordComment(const char* msg); |
| 866 | 956 |
| 867 // Writes a single word of data in the code stream. | 957 // Writes a single byte or word of data in the code stream. Used for |
| 868 // Used for inline tables, e.g., jump-tables. | 958 // inline tables, e.g., jump-tables. |
| 869 void dd(uint32_t data, RelocInfo::Mode reloc_info); | 959 void db(uint8_t data); |
| 960 void dd(uint32_t data); |
| 870 | 961 |
| 871 int pc_offset() const { return pc_ - buffer_; } | 962 int pc_offset() const { return pc_ - buffer_; } |
| 872 | 963 |
| 873 // Check if there is less than kGap bytes available in the buffer. | 964 // Check if there is less than kGap bytes available in the buffer. |
| 874 // If this is the case, we need to grow the buffer before emitting | 965 // If this is the case, we need to grow the buffer before emitting |
| 875 // an instruction or relocation information. | 966 // an instruction or relocation information. |
| 876 inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; } | 967 inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; } |
| 877 | 968 |
| 878 // Get the number of bytes available in the buffer. | 969 // Get the number of bytes available in the buffer. |
| 879 inline int available_space() const { return reloc_info_writer.pos() - pc_; } | 970 inline int available_space() const { return reloc_info_writer.pos() - pc_; } |
| 880 | 971 |
| 881 static bool IsNop(Address addr) { return *addr == 0x90; } | 972 static bool IsNop(Address addr) { return *addr == 0x90; } |
| 882 | 973 |
| 883 PositionsRecorder* positions_recorder() { return &positions_recorder_; } | 974 PositionsRecorder* positions_recorder() { return &positions_recorder_; } |
| 884 | 975 |
| 885 // Avoid overflows for displacements etc. | 976 // Avoid overflows for displacements etc. |
| 886 static const int kMaximalBufferSize = 512*MB; | 977 static const int kMaximalBufferSize = 512*MB; |
| 887 static const int kMinimalBufferSize = 4*KB; | 978 static const int kMinimalBufferSize = 4*KB; |
| 888 | 979 |
| 889 protected: | 980 protected: |
| 890 void movsd(XMMRegister dst, const Operand& src); | 981 void movsd(XMMRegister dst, const Operand& src); |
| 891 void movsd(const Operand& dst, XMMRegister src); | 982 void movsd(const Operand& dst, XMMRegister src); |
| 892 | 983 |
| 893 void emit_sse_operand(XMMRegister reg, const Operand& adr); | 984 void emit_sse_operand(XMMRegister reg, const Operand& adr); |
| 894 void emit_sse_operand(XMMRegister dst, XMMRegister src); | 985 void emit_sse_operand(XMMRegister dst, XMMRegister src); |
| 895 void emit_sse_operand(Register dst, XMMRegister src); | 986 void emit_sse_operand(Register dst, XMMRegister src); |
| 896 | 987 |
| 988 byte* addr_at(int pos) { return buffer_ + pos; } |
| 897 private: | 989 private: |
| 898 byte* addr_at(int pos) { return buffer_ + pos; } | |
| 899 byte byte_at(int pos) { return buffer_[pos]; } | 990 byte byte_at(int pos) { return buffer_[pos]; } |
| 900 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } | 991 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } |
| 901 uint32_t long_at(int pos) { | 992 uint32_t long_at(int pos) { |
| 902 return *reinterpret_cast<uint32_t*>(addr_at(pos)); | 993 return *reinterpret_cast<uint32_t*>(addr_at(pos)); |
| 903 } | 994 } |
| 904 void long_at_put(int pos, uint32_t x) { | 995 void long_at_put(int pos, uint32_t x) { |
| 905 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; | 996 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; |
| 906 } | 997 } |
| 907 | 998 |
| 908 // code emission | 999 // code emission |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 private: | 1078 private: |
| 988 Assembler* assembler_; | 1079 Assembler* assembler_; |
| 989 #ifdef DEBUG | 1080 #ifdef DEBUG |
| 990 int space_before_; | 1081 int space_before_; |
| 991 #endif | 1082 #endif |
| 992 }; | 1083 }; |
| 993 | 1084 |
| 994 } } // namespace v8::internal | 1085 } } // namespace v8::internal |
| 995 | 1086 |
| 996 #endif // V8_IA32_ASSEMBLER_IA32_H_ | 1087 #endif // V8_IA32_ASSEMBLER_IA32_H_ |
| OLD | NEW |