| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/heap.h" | 10 #include "vm/heap.h" |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 #ifdef DEBUG | 67 #ifdef DEBUG |
| 68 initialized_ = true; | 68 initialized_ = true; |
| 69 #endif | 69 #endif |
| 70 } | 70 } |
| 71 | 71 |
| 72 #undef __ | 72 #undef __ |
| 73 | 73 |
| 74 | 74 |
| 75 class DirectCallRelocation : public AssemblerFixup { | 75 class DirectCallRelocation : public AssemblerFixup { |
| 76 public: | 76 public: |
| 77 void Process(const MemoryRegion& region, int position) { | 77 void Process(const MemoryRegion& region, intptr_t position) { |
| 78 // Direct calls are relative to the following instruction on x86. | 78 // Direct calls are relative to the following instruction on x86. |
| 79 int32_t pointer = region.Load<int32_t>(position); | 79 int32_t pointer = region.Load<int32_t>(position); |
| 80 int32_t delta = region.start() + position + sizeof(int32_t); | 80 int32_t delta = region.start() + position + sizeof(int32_t); |
| 81 region.Store<int32_t>(position, pointer - delta); | 81 region.Store<int32_t>(position, pointer - delta); |
| 82 } | 82 } |
| 83 }; | 83 }; |
| 84 | 84 |
| 85 | 85 |
| 86 void Assembler::InitializeMemoryWithBreakpoints(uword data, int length) { | 86 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { |
| 87 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); | 87 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); |
| 88 } | 88 } |
| 89 | 89 |
| 90 | 90 |
| 91 void Assembler::call(Register reg) { | 91 void Assembler::call(Register reg) { |
| 92 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 92 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 93 EmitUint8(0xFF); | 93 EmitUint8(0xFF); |
| 94 EmitRegisterOperand(2, reg); | 94 EmitRegisterOperand(2, reg); |
| 95 } | 95 } |
| 96 | 96 |
| (...skipping 1694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1791 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1791 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1792 EmitUint8(0xF4); | 1792 EmitUint8(0xF4); |
| 1793 } | 1793 } |
| 1794 | 1794 |
| 1795 | 1795 |
| 1796 void Assembler::j(Condition condition, Label* label, bool near) { | 1796 void Assembler::j(Condition condition, Label* label, bool near) { |
| 1797 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1797 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1798 if (label->IsBound()) { | 1798 if (label->IsBound()) { |
| 1799 static const int kShortSize = 2; | 1799 static const int kShortSize = 2; |
| 1800 static const int kLongSize = 6; | 1800 static const int kLongSize = 6; |
| 1801 int offset = label->Position() - buffer_.Size(); | 1801 intptr_t offset = label->Position() - buffer_.Size(); |
| 1802 ASSERT(offset <= 0); | 1802 ASSERT(offset <= 0); |
| 1803 if (Utils::IsInt(8, offset - kShortSize)) { | 1803 if (Utils::IsInt(8, offset - kShortSize)) { |
| 1804 EmitUint8(0x70 + condition); | 1804 EmitUint8(0x70 + condition); |
| 1805 EmitUint8((offset - kShortSize) & 0xFF); | 1805 EmitUint8((offset - kShortSize) & 0xFF); |
| 1806 } else { | 1806 } else { |
| 1807 EmitUint8(0x0F); | 1807 EmitUint8(0x0F); |
| 1808 EmitUint8(0x80 + condition); | 1808 EmitUint8(0x80 + condition); |
| 1809 EmitInt32(offset - kLongSize); | 1809 EmitInt32(offset - kLongSize); |
| 1810 } | 1810 } |
| 1811 } else if (near) { | 1811 } else if (near) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1833 EmitUint8(0xFF); | 1833 EmitUint8(0xFF); |
| 1834 EmitRegisterOperand(4, reg); | 1834 EmitRegisterOperand(4, reg); |
| 1835 } | 1835 } |
| 1836 | 1836 |
| 1837 | 1837 |
| 1838 void Assembler::jmp(Label* label, bool near) { | 1838 void Assembler::jmp(Label* label, bool near) { |
| 1839 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1839 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1840 if (label->IsBound()) { | 1840 if (label->IsBound()) { |
| 1841 static const int kShortSize = 2; | 1841 static const int kShortSize = 2; |
| 1842 static const int kLongSize = 5; | 1842 static const int kLongSize = 5; |
| 1843 int offset = label->Position() - buffer_.Size(); | 1843 intptr_t offset = label->Position() - buffer_.Size(); |
| 1844 ASSERT(offset <= 0); | 1844 ASSERT(offset <= 0); |
| 1845 if (Utils::IsInt(8, offset - kShortSize)) { | 1845 if (Utils::IsInt(8, offset - kShortSize)) { |
| 1846 EmitUint8(0xEB); | 1846 EmitUint8(0xEB); |
| 1847 EmitUint8((offset - kShortSize) & 0xFF); | 1847 EmitUint8((offset - kShortSize) & 0xFF); |
| 1848 } else { | 1848 } else { |
| 1849 EmitUint8(0xE9); | 1849 EmitUint8(0xE9); |
| 1850 EmitInt32(offset - kLongSize); | 1850 EmitInt32(offset - kLongSize); |
| 1851 } | 1851 } |
| 1852 } else if (near) { | 1852 } else if (near) { |
| 1853 EmitUint8(0xEB); | 1853 EmitUint8(0xEB); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1899 } | 1899 } |
| 1900 } | 1900 } |
| 1901 | 1901 |
| 1902 | 1902 |
| 1903 void Assembler::PopRegister(Register r) { | 1903 void Assembler::PopRegister(Register r) { |
| 1904 popl(r); | 1904 popl(r); |
| 1905 } | 1905 } |
| 1906 | 1906 |
| 1907 | 1907 |
| 1908 void Assembler::AddImmediate(Register reg, const Immediate& imm) { | 1908 void Assembler::AddImmediate(Register reg, const Immediate& imm) { |
| 1909 int value = imm.value(); | 1909 intptr_t value = imm.value(); |
| 1910 if (value > 0) { | 1910 if (value > 0) { |
| 1911 if (value == 1) { | 1911 if (value == 1) { |
| 1912 incl(reg); | 1912 incl(reg); |
| 1913 } else if (value != 0) { | 1913 } else if (value != 0) { |
| 1914 addl(reg, imm); | 1914 addl(reg, imm); |
| 1915 } | 1915 } |
| 1916 } else if (value < 0) { | 1916 } else if (value < 0) { |
| 1917 value = -value; | 1917 value = -value; |
| 1918 if (value == 1) { | 1918 if (value == 1) { |
| 1919 decl(reg); | 1919 decl(reg); |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2207 leave(); | 2207 leave(); |
| 2208 } | 2208 } |
| 2209 | 2209 |
| 2210 | 2210 |
| 2211 void Assembler::CallRuntime(const RuntimeEntry& entry, | 2211 void Assembler::CallRuntime(const RuntimeEntry& entry, |
| 2212 intptr_t argument_count) { | 2212 intptr_t argument_count) { |
| 2213 entry.Call(this, argument_count); | 2213 entry.Call(this, argument_count); |
| 2214 } | 2214 } |
| 2215 | 2215 |
| 2216 | 2216 |
| 2217 void Assembler::Align(int alignment, int offset) { | 2217 void Assembler::Align(intptr_t alignment, intptr_t offset) { |
| 2218 ASSERT(Utils::IsPowerOfTwo(alignment)); | 2218 ASSERT(Utils::IsPowerOfTwo(alignment)); |
| 2219 int pos = offset + buffer_.GetPosition(); | 2219 intptr_t pos = offset + buffer_.GetPosition(); |
| 2220 int mod = pos & (alignment - 1); | 2220 intptr_t mod = pos & (alignment - 1); |
| 2221 if (mod == 0) { | 2221 if (mod == 0) { |
| 2222 return; | 2222 return; |
| 2223 } | 2223 } |
| 2224 int bytes_needed = alignment - mod; | 2224 intptr_t bytes_needed = alignment - mod; |
| 2225 while (bytes_needed > MAX_NOP_SIZE) { | 2225 while (bytes_needed > MAX_NOP_SIZE) { |
| 2226 nop(MAX_NOP_SIZE); | 2226 nop(MAX_NOP_SIZE); |
| 2227 bytes_needed -= MAX_NOP_SIZE; | 2227 bytes_needed -= MAX_NOP_SIZE; |
| 2228 } | 2228 } |
| 2229 if (bytes_needed) { | 2229 if (bytes_needed) { |
| 2230 nop(bytes_needed); | 2230 nop(bytes_needed); |
| 2231 } | 2231 } |
| 2232 ASSERT(((offset + buffer_.GetPosition()) & (alignment-1)) == 0); | 2232 ASSERT(((offset + buffer_.GetPosition()) & (alignment-1)) == 0); |
| 2233 } | 2233 } |
| 2234 | 2234 |
| 2235 | 2235 |
| 2236 void Assembler::Bind(Label* label) { | 2236 void Assembler::Bind(Label* label) { |
| 2237 int bound = buffer_.Size(); | 2237 intptr_t bound = buffer_.Size(); |
| 2238 ASSERT(!label->IsBound()); // Labels can only be bound once. | 2238 ASSERT(!label->IsBound()); // Labels can only be bound once. |
| 2239 while (label->IsLinked()) { | 2239 while (label->IsLinked()) { |
| 2240 int position = label->LinkPosition(); | 2240 intptr_t position = label->LinkPosition(); |
| 2241 int next = buffer_.Load<int32_t>(position); | 2241 intptr_t next = buffer_.Load<int32_t>(position); |
| 2242 buffer_.Store<int32_t>(position, bound - (position + 4)); | 2242 buffer_.Store<int32_t>(position, bound - (position + 4)); |
| 2243 label->position_ = next; | 2243 label->position_ = next; |
| 2244 } | 2244 } |
| 2245 while (label->HasNear()) { | 2245 while (label->HasNear()) { |
| 2246 int position = label->NearPosition(); | 2246 intptr_t position = label->NearPosition(); |
| 2247 int offset = bound - (position + 1); | 2247 intptr_t offset = bound - (position + 1); |
| 2248 ASSERT(Utils::IsInt(8, offset)); | 2248 ASSERT(Utils::IsInt(8, offset)); |
| 2249 buffer_.Store<int8_t>(position, offset); | 2249 buffer_.Store<int8_t>(position, offset); |
| 2250 } | 2250 } |
| 2251 label->BindTo(bound); | 2251 label->BindTo(bound); |
| 2252 } | 2252 } |
| 2253 | 2253 |
| 2254 | 2254 |
| 2255 void Assembler::TryAllocate(const Class& cls, | 2255 void Assembler::TryAllocate(const Class& cls, |
| 2256 Label* failure, | 2256 Label* failure, |
| 2257 bool near_jump, | 2257 bool near_jump, |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2339 // Emit the message address as immediate operand in the test instruction. | 2339 // Emit the message address as immediate operand in the test instruction. |
| 2340 testl(EAX, Immediate(reinterpret_cast<int32_t>(message))); | 2340 testl(EAX, Immediate(reinterpret_cast<int32_t>(message))); |
| 2341 } | 2341 } |
| 2342 // Emit the int3 instruction. | 2342 // Emit the int3 instruction. |
| 2343 int3(); // Execution can be resumed with the 'cont' command in gdb. | 2343 int3(); // Execution can be resumed with the 'cont' command in gdb. |
| 2344 } | 2344 } |
| 2345 | 2345 |
| 2346 | 2346 |
| 2347 void Assembler::EmitOperand(int rm, const Operand& operand) { | 2347 void Assembler::EmitOperand(int rm, const Operand& operand) { |
| 2348 ASSERT(rm >= 0 && rm < 8); | 2348 ASSERT(rm >= 0 && rm < 8); |
| 2349 const int length = operand.length_; | 2349 const intptr_t length = operand.length_; |
| 2350 ASSERT(length > 0); | 2350 ASSERT(length > 0); |
| 2351 // Emit the ModRM byte updated with the given RM value. | 2351 // Emit the ModRM byte updated with the given RM value. |
| 2352 ASSERT((operand.encoding_[0] & 0x38) == 0); | 2352 ASSERT((operand.encoding_[0] & 0x38) == 0); |
| 2353 EmitUint8(operand.encoding_[0] + (rm << 3)); | 2353 EmitUint8(operand.encoding_[0] + (rm << 3)); |
| 2354 // Emit the rest of the encoded operand. | 2354 // Emit the rest of the encoded operand. |
| 2355 for (int i = 1; i < length; i++) { | 2355 for (intptr_t i = 1; i < length; i++) { |
| 2356 EmitUint8(operand.encoding_[i]); | 2356 EmitUint8(operand.encoding_[i]); |
| 2357 } | 2357 } |
| 2358 } | 2358 } |
| 2359 | 2359 |
| 2360 | 2360 |
| 2361 void Assembler::EmitImmediate(const Immediate& imm) { | 2361 void Assembler::EmitImmediate(const Immediate& imm) { |
| 2362 EmitInt32(imm.value()); | 2362 EmitInt32(imm.value()); |
| 2363 } | 2363 } |
| 2364 | 2364 |
| 2365 | 2365 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2377 EmitUint8(0x05 + (rm << 3)); | 2377 EmitUint8(0x05 + (rm << 3)); |
| 2378 EmitImmediate(immediate); | 2378 EmitImmediate(immediate); |
| 2379 } else { | 2379 } else { |
| 2380 EmitUint8(0x81); | 2380 EmitUint8(0x81); |
| 2381 EmitOperand(rm, operand); | 2381 EmitOperand(rm, operand); |
| 2382 EmitImmediate(immediate); | 2382 EmitImmediate(immediate); |
| 2383 } | 2383 } |
| 2384 } | 2384 } |
| 2385 | 2385 |
| 2386 | 2386 |
| 2387 void Assembler::EmitLabel(Label* label, int instruction_size) { | 2387 void Assembler::EmitLabel(Label* label, intptr_t instruction_size) { |
| 2388 if (label->IsBound()) { | 2388 if (label->IsBound()) { |
| 2389 int offset = label->Position() - buffer_.Size(); | 2389 intptr_t offset = label->Position() - buffer_.Size(); |
| 2390 ASSERT(offset <= 0); | 2390 ASSERT(offset <= 0); |
| 2391 EmitInt32(offset - instruction_size); | 2391 EmitInt32(offset - instruction_size); |
| 2392 } else { | 2392 } else { |
| 2393 EmitLabelLink(label); | 2393 EmitLabelLink(label); |
| 2394 } | 2394 } |
| 2395 } | 2395 } |
| 2396 | 2396 |
| 2397 | 2397 |
| 2398 void Assembler::EmitLabelLink(Label* label) { | 2398 void Assembler::EmitLabelLink(Label* label) { |
| 2399 ASSERT(!label->IsBound()); | 2399 ASSERT(!label->IsBound()); |
| 2400 int position = buffer_.Size(); | 2400 intptr_t position = buffer_.Size(); |
| 2401 EmitInt32(label->position_); | 2401 EmitInt32(label->position_); |
| 2402 label->LinkTo(position); | 2402 label->LinkTo(position); |
| 2403 } | 2403 } |
| 2404 | 2404 |
| 2405 | 2405 |
| 2406 void Assembler::EmitNearLabelLink(Label* label) { | 2406 void Assembler::EmitNearLabelLink(Label* label) { |
| 2407 ASSERT(!label->IsBound()); | 2407 ASSERT(!label->IsBound()); |
| 2408 int position = buffer_.Size(); | 2408 intptr_t position = buffer_.Size(); |
| 2409 EmitUint8(0); | 2409 EmitUint8(0); |
| 2410 label->NearLinkTo(position); | 2410 label->NearLinkTo(position); |
| 2411 } | 2411 } |
| 2412 | 2412 |
| 2413 | 2413 |
| 2414 void Assembler::EmitGenericShift(int rm, | 2414 void Assembler::EmitGenericShift(int rm, |
| 2415 Register reg, | 2415 Register reg, |
| 2416 const Immediate& imm) { | 2416 const Immediate& imm) { |
| 2417 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2417 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 2418 ASSERT(imm.is_int8()); | 2418 ASSERT(imm.is_int8()); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2496 | 2496 |
| 2497 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 2497 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
| 2498 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 2498 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
| 2499 return xmm_reg_names[reg]; | 2499 return xmm_reg_names[reg]; |
| 2500 } | 2500 } |
| 2501 | 2501 |
| 2502 | 2502 |
| 2503 } // namespace dart | 2503 } // namespace dart |
| 2504 | 2504 |
| 2505 #endif // defined TARGET_ARCH_IA32 | 2505 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |