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 |