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" // NOLINT | 5 #include "vm/globals.h" // NOLINT |
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/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 int32_t delta = region.start() + position + sizeof(int32_t); | 28 int32_t delta = region.start() + position + sizeof(int32_t); |
29 region.Store<int32_t>(position, pointer - delta); | 29 region.Store<int32_t>(position, pointer - delta); |
30 } | 30 } |
31 | 31 |
32 virtual bool IsPointerOffset() const { return false; } | 32 virtual bool IsPointerOffset() const { return false; } |
33 }; | 33 }; |
34 | 34 |
35 | 35 |
36 int32_t Assembler::jit_cookie() { | 36 int32_t Assembler::jit_cookie() { |
37 if (jit_cookie_ == 0) { | 37 if (jit_cookie_ == 0) { |
38 jit_cookie_ = static_cast<int32_t>( | 38 jit_cookie_ = |
39 Isolate::Current()->random()->NextUInt32()); | 39 static_cast<int32_t>(Isolate::Current()->random()->NextUInt32()); |
40 } | 40 } |
41 return jit_cookie_; | 41 return jit_cookie_; |
42 } | 42 } |
43 | 43 |
44 | 44 |
45 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { | 45 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { |
46 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); | 46 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); |
47 } | 47 } |
48 | 48 |
49 | 49 |
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 EmitXmmRegisterOperand(dst, src); | 659 EmitXmmRegisterOperand(dst, src); |
660 } | 660 } |
661 | 661 |
662 | 662 |
663 void Assembler::notps(XmmRegister dst) { | 663 void Assembler::notps(XmmRegister dst) { |
664 static const struct ALIGN16 { | 664 static const struct ALIGN16 { |
665 uint32_t a; | 665 uint32_t a; |
666 uint32_t b; | 666 uint32_t b; |
667 uint32_t c; | 667 uint32_t c; |
668 uint32_t d; | 668 uint32_t d; |
669 } float_not_constant = | 669 } float_not_constant = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; |
670 { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; | 670 xorps(dst, Address::Absolute(reinterpret_cast<uword>(&float_not_constant))); |
671 xorps(dst, | |
672 Address::Absolute(reinterpret_cast<uword>(&float_not_constant))); | |
673 } | 671 } |
674 | 672 |
675 | 673 |
676 void Assembler::negateps(XmmRegister dst) { | 674 void Assembler::negateps(XmmRegister dst) { |
677 static const struct ALIGN16 { | 675 static const struct ALIGN16 { |
678 uint32_t a; | 676 uint32_t a; |
679 uint32_t b; | 677 uint32_t b; |
680 uint32_t c; | 678 uint32_t c; |
681 uint32_t d; | 679 uint32_t d; |
682 } float_negate_constant = | 680 } float_negate_constant = {0x80000000, 0x80000000, 0x80000000, 0x80000000}; |
683 { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; | |
684 xorps(dst, | 681 xorps(dst, |
685 Address::Absolute(reinterpret_cast<uword>(&float_negate_constant))); | 682 Address::Absolute(reinterpret_cast<uword>(&float_negate_constant))); |
686 } | 683 } |
687 | 684 |
688 | 685 |
689 void Assembler::absps(XmmRegister dst) { | 686 void Assembler::absps(XmmRegister dst) { |
690 static const struct ALIGN16 { | 687 static const struct ALIGN16 { |
691 uint32_t a; | 688 uint32_t a; |
692 uint32_t b; | 689 uint32_t b; |
693 uint32_t c; | 690 uint32_t c; |
694 uint32_t d; | 691 uint32_t d; |
695 } float_absolute_constant = | 692 } float_absolute_constant = {0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF}; |
696 { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; | |
697 andps(dst, | 693 andps(dst, |
698 Address::Absolute(reinterpret_cast<uword>(&float_absolute_constant))); | 694 Address::Absolute(reinterpret_cast<uword>(&float_absolute_constant))); |
699 } | 695 } |
700 | 696 |
701 | 697 |
702 void Assembler::zerowps(XmmRegister dst) { | 698 void Assembler::zerowps(XmmRegister dst) { |
703 static const struct ALIGN16 { | 699 static const struct ALIGN16 { |
704 uint32_t a; | 700 uint32_t a; |
705 uint32_t b; | 701 uint32_t b; |
706 uint32_t c; | 702 uint32_t c; |
707 uint32_t d; | 703 uint32_t d; |
708 } float_zerow_constant = | 704 } float_zerow_constant = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000}; |
709 { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }; | |
710 andps(dst, Address::Absolute(reinterpret_cast<uword>(&float_zerow_constant))); | 705 andps(dst, Address::Absolute(reinterpret_cast<uword>(&float_zerow_constant))); |
711 } | 706 } |
712 | 707 |
713 | 708 |
714 void Assembler::cmppseq(XmmRegister dst, XmmRegister src) { | 709 void Assembler::cmppseq(XmmRegister dst, XmmRegister src) { |
715 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 710 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
716 EmitUint8(0x0F); | 711 EmitUint8(0x0F); |
717 EmitUint8(0xC2); | 712 EmitUint8(0xC2); |
718 EmitXmmRegisterOperand(dst, src); | 713 EmitXmmRegisterOperand(dst, src); |
719 EmitUint8(0x0); | 714 EmitUint8(0x0); |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
865 EmitUint8(0x0F); | 860 EmitUint8(0x0F); |
866 EmitUint8(0x58); | 861 EmitUint8(0x58); |
867 EmitXmmRegisterOperand(dst, src); | 862 EmitXmmRegisterOperand(dst, src); |
868 } | 863 } |
869 | 864 |
870 | 865 |
871 void Assembler::negatepd(XmmRegister dst) { | 866 void Assembler::negatepd(XmmRegister dst) { |
872 static const struct ALIGN16 { | 867 static const struct ALIGN16 { |
873 uint64_t a; | 868 uint64_t a; |
874 uint64_t b; | 869 uint64_t b; |
875 } double_negate_constant = | 870 } double_negate_constant = {0x8000000000000000LL, 0x8000000000000000LL}; |
876 { 0x8000000000000000LL, 0x8000000000000000LL }; | |
877 xorpd(dst, | 871 xorpd(dst, |
878 Address::Absolute(reinterpret_cast<uword>(&double_negate_constant))); | 872 Address::Absolute(reinterpret_cast<uword>(&double_negate_constant))); |
879 } | 873 } |
880 | 874 |
881 | 875 |
882 void Assembler::subpd(XmmRegister dst, XmmRegister src) { | 876 void Assembler::subpd(XmmRegister dst, XmmRegister src) { |
883 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 877 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
884 EmitUint8(0x66); | 878 EmitUint8(0x66); |
885 EmitUint8(0x0F); | 879 EmitUint8(0x0F); |
886 EmitUint8(0x5C); | 880 EmitUint8(0x5C); |
(...skipping 16 matching lines...) Expand all Loading... |
903 EmitUint8(0x0F); | 897 EmitUint8(0x0F); |
904 EmitUint8(0x5E); | 898 EmitUint8(0x5E); |
905 EmitXmmRegisterOperand(dst, src); | 899 EmitXmmRegisterOperand(dst, src); |
906 } | 900 } |
907 | 901 |
908 | 902 |
909 void Assembler::abspd(XmmRegister dst) { | 903 void Assembler::abspd(XmmRegister dst) { |
910 static const struct ALIGN16 { | 904 static const struct ALIGN16 { |
911 uint64_t a; | 905 uint64_t a; |
912 uint64_t b; | 906 uint64_t b; |
913 } double_absolute_constant = | 907 } double_absolute_constant = {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL}; |
914 { 0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL }; | |
915 andpd(dst, | 908 andpd(dst, |
916 Address::Absolute(reinterpret_cast<uword>(&double_absolute_constant))); | 909 Address::Absolute(reinterpret_cast<uword>(&double_absolute_constant))); |
917 } | 910 } |
918 | 911 |
919 | 912 |
920 void Assembler::minpd(XmmRegister dst, XmmRegister src) { | 913 void Assembler::minpd(XmmRegister dst, XmmRegister src) { |
921 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 914 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
922 EmitUint8(0x66); | 915 EmitUint8(0x66); |
923 EmitUint8(0x0F); | 916 EmitUint8(0x0F); |
924 EmitUint8(0x5D); | 917 EmitUint8(0x5D); |
(...skipping 1320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2245 // For the value we are only interested in the new/old bit and the tag bit. | 2238 // For the value we are only interested in the new/old bit and the tag bit. |
2246 andl(value, Immediate(kNewObjectAlignmentOffset | kHeapObjectTag)); | 2239 andl(value, Immediate(kNewObjectAlignmentOffset | kHeapObjectTag)); |
2247 // Shift the tag bit into the carry. | 2240 // Shift the tag bit into the carry. |
2248 shrl(value, Immediate(1)); | 2241 shrl(value, Immediate(1)); |
2249 // Add the tag bits together, if the value is not a Smi the addition will | 2242 // Add the tag bits together, if the value is not a Smi the addition will |
2250 // overflow into the next bit, leaving us with a zero low bit. | 2243 // overflow into the next bit, leaving us with a zero low bit. |
2251 adcl(value, object); | 2244 adcl(value, object); |
2252 // Mask out higher, uninteresting bits which were polluted by dest. | 2245 // Mask out higher, uninteresting bits which were polluted by dest. |
2253 andl(value, Immediate(kObjectAlignment - 1)); | 2246 andl(value, Immediate(kObjectAlignment - 1)); |
2254 // Compare with the expected bit pattern. | 2247 // Compare with the expected bit pattern. |
2255 cmpl(value, Immediate( | 2248 cmpl(value, Immediate((kNewObjectAlignmentOffset >> 1) + kHeapObjectTag + |
2256 (kNewObjectAlignmentOffset >> 1) + kHeapObjectTag + | 2249 kOldObjectAlignmentOffset + kHeapObjectTag)); |
2257 kOldObjectAlignmentOffset + kHeapObjectTag)); | |
2258 j(NOT_ZERO, no_update, Assembler::kNearJump); | 2250 j(NOT_ZERO, no_update, Assembler::kNearJump); |
2259 } | 2251 } |
2260 | 2252 |
2261 | 2253 |
2262 // Destroys the value register. | 2254 // Destroys the value register. |
2263 void Assembler::StoreIntoObject(Register object, | 2255 void Assembler::StoreIntoObject(Register object, |
2264 const Address& dest, | 2256 const Address& dest, |
2265 Register value, | 2257 Register value, |
2266 bool can_value_be_smi) { | 2258 bool can_value_be_smi) { |
2267 ASSERT(object != value); | 2259 ASSERT(object != value); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2366 addl(ESP, Immediate(2 * kWordSize)); | 2358 addl(ESP, Immediate(2 * kWordSize)); |
2367 } | 2359 } |
2368 | 2360 |
2369 | 2361 |
2370 void Assembler::FloatNegate(XmmRegister f) { | 2362 void Assembler::FloatNegate(XmmRegister f) { |
2371 static const struct ALIGN16 { | 2363 static const struct ALIGN16 { |
2372 uint32_t a; | 2364 uint32_t a; |
2373 uint32_t b; | 2365 uint32_t b; |
2374 uint32_t c; | 2366 uint32_t c; |
2375 uint32_t d; | 2367 uint32_t d; |
2376 } float_negate_constant = | 2368 } float_negate_constant = {0x80000000, 0x00000000, 0x80000000, 0x00000000}; |
2377 { 0x80000000, 0x00000000, 0x80000000, 0x00000000 }; | |
2378 xorps(f, Address::Absolute(reinterpret_cast<uword>(&float_negate_constant))); | 2369 xorps(f, Address::Absolute(reinterpret_cast<uword>(&float_negate_constant))); |
2379 } | 2370 } |
2380 | 2371 |
2381 | 2372 |
2382 void Assembler::DoubleNegate(XmmRegister d) { | 2373 void Assembler::DoubleNegate(XmmRegister d) { |
2383 static const struct ALIGN16 { | 2374 static const struct ALIGN16 { |
2384 uint64_t a; | 2375 uint64_t a; |
2385 uint64_t b; | 2376 uint64_t b; |
2386 } double_negate_constant = | 2377 } double_negate_constant = {0x8000000000000000LL, 0x8000000000000000LL}; |
2387 {0x8000000000000000LL, 0x8000000000000000LL}; | |
2388 xorpd(d, Address::Absolute(reinterpret_cast<uword>(&double_negate_constant))); | 2378 xorpd(d, Address::Absolute(reinterpret_cast<uword>(&double_negate_constant))); |
2389 } | 2379 } |
2390 | 2380 |
2391 | 2381 |
2392 void Assembler::DoubleAbs(XmmRegister reg) { | 2382 void Assembler::DoubleAbs(XmmRegister reg) { |
2393 static const struct ALIGN16 { | 2383 static const struct ALIGN16 { |
2394 uint64_t a; | 2384 uint64_t a; |
2395 uint64_t b; | 2385 uint64_t b; |
2396 } double_abs_constant = | 2386 } double_abs_constant = {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL}; |
2397 {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL}; | |
2398 andpd(reg, Address::Absolute(reinterpret_cast<uword>(&double_abs_constant))); | 2387 andpd(reg, Address::Absolute(reinterpret_cast<uword>(&double_abs_constant))); |
2399 } | 2388 } |
2400 | 2389 |
2401 | 2390 |
2402 void Assembler::EnterFrame(intptr_t frame_size) { | 2391 void Assembler::EnterFrame(intptr_t frame_size) { |
2403 if (prologue_offset_ == -1) { | 2392 if (prologue_offset_ == -1) { |
2404 Comment("PrologueOffset = %" Pd "", CodeSize()); | 2393 Comment("PrologueOffset = %" Pd "", CodeSize()); |
2405 prologue_offset_ = CodeSize(); | 2394 prologue_offset_ = CodeSize(); |
2406 } | 2395 } |
2407 #ifdef DEBUG | 2396 #ifdef DEBUG |
(...skipping 23 matching lines...) Expand all Loading... |
2431 // the C++ world. | 2420 // the C++ world. |
2432 AddImmediate(ESP, Immediate(-frame_space)); | 2421 AddImmediate(ESP, Immediate(-frame_space)); |
2433 if (OS::ActivationFrameAlignment() > 1) { | 2422 if (OS::ActivationFrameAlignment() > 1) { |
2434 andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1))); | 2423 andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1))); |
2435 } | 2424 } |
2436 } | 2425 } |
2437 | 2426 |
2438 | 2427 |
2439 static const intptr_t kNumberOfVolatileCpuRegisters = 3; | 2428 static const intptr_t kNumberOfVolatileCpuRegisters = 3; |
2440 static const Register volatile_cpu_registers[kNumberOfVolatileCpuRegisters] = { | 2429 static const Register volatile_cpu_registers[kNumberOfVolatileCpuRegisters] = { |
2441 EAX, ECX, EDX | 2430 EAX, ECX, EDX}; |
2442 }; | |
2443 | 2431 |
2444 | 2432 |
2445 // XMM0 is used only as a scratch register in the optimized code. No need to | 2433 // XMM0 is used only as a scratch register in the optimized code. No need to |
2446 // save it. | 2434 // save it. |
2447 static const intptr_t kNumberOfVolatileXmmRegisters = | 2435 static const intptr_t kNumberOfVolatileXmmRegisters = kNumberOfXmmRegisters - 1; |
2448 kNumberOfXmmRegisters - 1; | |
2449 | 2436 |
2450 | 2437 |
2451 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { | 2438 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { |
2452 Comment("EnterCallRuntimeFrame"); | 2439 Comment("EnterCallRuntimeFrame"); |
2453 EnterFrame(0); | 2440 EnterFrame(0); |
2454 | 2441 |
2455 // Preserve volatile CPU registers. | 2442 // Preserve volatile CPU registers. |
2456 for (intptr_t i = 0; i < kNumberOfVolatileCpuRegisters; i++) { | 2443 for (intptr_t i = 0; i < kNumberOfVolatileCpuRegisters; i++) { |
2457 pushl(volatile_cpu_registers[i]); | 2444 pushl(volatile_cpu_registers[i]); |
2458 } | 2445 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2539 return; | 2526 return; |
2540 } | 2527 } |
2541 intptr_t bytes_needed = alignment - mod; | 2528 intptr_t bytes_needed = alignment - mod; |
2542 while (bytes_needed > MAX_NOP_SIZE) { | 2529 while (bytes_needed > MAX_NOP_SIZE) { |
2543 nop(MAX_NOP_SIZE); | 2530 nop(MAX_NOP_SIZE); |
2544 bytes_needed -= MAX_NOP_SIZE; | 2531 bytes_needed -= MAX_NOP_SIZE; |
2545 } | 2532 } |
2546 if (bytes_needed) { | 2533 if (bytes_needed) { |
2547 nop(bytes_needed); | 2534 nop(bytes_needed); |
2548 } | 2535 } |
2549 ASSERT(((offset + buffer_.GetPosition()) & (alignment-1)) == 0); | 2536 ASSERT(((offset + buffer_.GetPosition()) & (alignment - 1)) == 0); |
2550 } | 2537 } |
2551 | 2538 |
2552 | 2539 |
2553 void Assembler::Bind(Label* label) { | 2540 void Assembler::Bind(Label* label) { |
2554 intptr_t bound = buffer_.Size(); | 2541 intptr_t bound = buffer_.Size(); |
2555 ASSERT(!label->IsBound()); // Labels can only be bound once. | 2542 ASSERT(!label->IsBound()); // Labels can only be bound once. |
2556 while (label->IsLinked()) { | 2543 while (label->IsLinked()) { |
2557 intptr_t position = label->LinkPosition(); | 2544 intptr_t position = label->LinkPosition(); |
2558 intptr_t next = buffer_.Load<int32_t>(position); | 2545 intptr_t next = buffer_.Load<int32_t>(position); |
2559 buffer_.Store<int32_t>(position, bound - (position + 4)); | 2546 buffer_.Store<int32_t>(position, bound - (position + 4)); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2635 bool near_jump, | 2622 bool near_jump, |
2636 Register instance_reg, | 2623 Register instance_reg, |
2637 Register temp_reg) { | 2624 Register temp_reg) { |
2638 ASSERT(failure != NULL); | 2625 ASSERT(failure != NULL); |
2639 ASSERT(temp_reg != kNoRegister); | 2626 ASSERT(temp_reg != kNoRegister); |
2640 if (FLAG_inline_alloc) { | 2627 if (FLAG_inline_alloc) { |
2641 // If this allocation is traced, program will jump to failure path | 2628 // If this allocation is traced, program will jump to failure path |
2642 // (i.e. the allocation stub) which will allocate the object and trace the | 2629 // (i.e. the allocation stub) which will allocate the object and trace the |
2643 // allocation call site. | 2630 // allocation call site. |
2644 NOT_IN_PRODUCT( | 2631 NOT_IN_PRODUCT( |
2645 MaybeTraceAllocation(cls.id(), temp_reg, failure, near_jump)); | 2632 MaybeTraceAllocation(cls.id(), temp_reg, failure, near_jump)); |
2646 const intptr_t instance_size = cls.instance_size(); | 2633 const intptr_t instance_size = cls.instance_size(); |
2647 Heap::Space space = Heap::kNew; | 2634 Heap::Space space = Heap::kNew; |
2648 movl(temp_reg, Address(THR, Thread::heap_offset())); | 2635 movl(temp_reg, Address(THR, Thread::heap_offset())); |
2649 movl(instance_reg, Address(temp_reg, Heap::TopOffset(space))); | 2636 movl(instance_reg, Address(temp_reg, Heap::TopOffset(space))); |
2650 addl(instance_reg, Immediate(instance_size)); | 2637 addl(instance_reg, Immediate(instance_size)); |
2651 // instance_reg: potential next object start. | 2638 // instance_reg: potential next object start. |
2652 cmpl(instance_reg, Address(temp_reg, Heap::EndOffset(space))); | 2639 cmpl(instance_reg, Address(temp_reg, Heap::EndOffset(space))); |
2653 j(ABOVE_EQUAL, failure, near_jump); | 2640 j(ABOVE_EQUAL, failure, near_jump); |
2654 // Successfully allocated the object, now update top to point to | 2641 // Successfully allocated the object, now update top to point to |
2655 // next object start and store the class in the class field of object. | 2642 // next object start and store the class in the class field of object. |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2753 void Assembler::EnterStubFrame() { | 2740 void Assembler::EnterStubFrame() { |
2754 EnterDartFrame(0); | 2741 EnterDartFrame(0); |
2755 } | 2742 } |
2756 | 2743 |
2757 | 2744 |
2758 void Assembler::Stop(const char* message) { | 2745 void Assembler::Stop(const char* message) { |
2759 if (FLAG_print_stop_message) { | 2746 if (FLAG_print_stop_message) { |
2760 pushl(EAX); // Preserve EAX. | 2747 pushl(EAX); // Preserve EAX. |
2761 movl(EAX, Immediate(reinterpret_cast<int32_t>(message))); | 2748 movl(EAX, Immediate(reinterpret_cast<int32_t>(message))); |
2762 Call(*StubCode::PrintStopMessage_entry()); // Passing message in EAX. | 2749 Call(*StubCode::PrintStopMessage_entry()); // Passing message in EAX. |
2763 popl(EAX); // Restore EAX. | 2750 popl(EAX); // Restore EAX. |
2764 } else { | 2751 } else { |
2765 // Emit the message address as immediate operand in the test instruction. | 2752 // Emit the message address as immediate operand in the test instruction. |
2766 testl(EAX, Immediate(reinterpret_cast<int32_t>(message))); | 2753 testl(EAX, Immediate(reinterpret_cast<int32_t>(message))); |
2767 } | 2754 } |
2768 // Emit the int3 instruction. | 2755 // Emit the int3 instruction. |
2769 int3(); // Execution can be resumed with the 'cont' command in gdb. | 2756 int3(); // Execution can be resumed with the 'cont' command in gdb. |
2770 } | 2757 } |
2771 | 2758 |
2772 | 2759 |
2773 void Assembler::EmitOperand(int rm, const Operand& operand) { | 2760 void Assembler::EmitOperand(int rm, const Operand& operand) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2830 | 2817 |
2831 | 2818 |
2832 void Assembler::EmitNearLabelLink(Label* label) { | 2819 void Assembler::EmitNearLabelLink(Label* label) { |
2833 ASSERT(!label->IsBound()); | 2820 ASSERT(!label->IsBound()); |
2834 intptr_t position = buffer_.Size(); | 2821 intptr_t position = buffer_.Size(); |
2835 EmitUint8(0); | 2822 EmitUint8(0); |
2836 label->NearLinkTo(position); | 2823 label->NearLinkTo(position); |
2837 } | 2824 } |
2838 | 2825 |
2839 | 2826 |
2840 void Assembler::EmitGenericShift(int rm, | 2827 void Assembler::EmitGenericShift(int rm, Register reg, const Immediate& imm) { |
2841 Register reg, | |
2842 const Immediate& imm) { | |
2843 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2828 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2844 ASSERT(imm.is_int8()); | 2829 ASSERT(imm.is_int8()); |
2845 if (imm.value() == 1) { | 2830 if (imm.value() == 1) { |
2846 EmitUint8(0xD1); | 2831 EmitUint8(0xD1); |
2847 EmitOperand(rm, Operand(reg)); | 2832 EmitOperand(rm, Operand(reg)); |
2848 } else { | 2833 } else { |
2849 EmitUint8(0xC1); | 2834 EmitUint8(0xC1); |
2850 EmitOperand(rm, Operand(reg)); | 2835 EmitOperand(rm, Operand(reg)); |
2851 EmitUint8(imm.value() & 0xFF); | 2836 EmitUint8(imm.value() & 0xFF); |
2852 } | 2837 } |
2853 } | 2838 } |
2854 | 2839 |
2855 | 2840 |
2856 void Assembler::EmitGenericShift(int rm, | 2841 void Assembler::EmitGenericShift(int rm, |
2857 const Operand& operand, | 2842 const Operand& operand, |
2858 Register shifter) { | 2843 Register shifter) { |
2859 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2844 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2860 ASSERT(shifter == ECX); | 2845 ASSERT(shifter == ECX); |
2861 EmitUint8(0xD3); | 2846 EmitUint8(0xD3); |
2862 EmitOperand(rm, Operand(operand)); | 2847 EmitOperand(rm, Operand(operand)); |
2863 } | 2848 } |
2864 | 2849 |
2865 | 2850 |
2866 void Assembler::LoadClassId(Register result, Register object) { | 2851 void Assembler::LoadClassId(Register result, Register object) { |
2867 ASSERT(RawObject::kClassIdTagPos == 16); | 2852 ASSERT(RawObject::kClassIdTagPos == 16); |
2868 ASSERT(RawObject::kClassIdTagSize == 16); | 2853 ASSERT(RawObject::kClassIdTagSize == 16); |
2869 const intptr_t class_id_offset = Object::tags_offset() + | 2854 const intptr_t class_id_offset = |
2870 RawObject::kClassIdTagPos / kBitsPerByte; | 2855 Object::tags_offset() + RawObject::kClassIdTagPos / kBitsPerByte; |
2871 movzxw(result, FieldAddress(object, class_id_offset)); | 2856 movzxw(result, FieldAddress(object, class_id_offset)); |
2872 } | 2857 } |
2873 | 2858 |
2874 | 2859 |
2875 void Assembler::LoadClassById(Register result, Register class_id) { | 2860 void Assembler::LoadClassById(Register result, Register class_id) { |
2876 ASSERT(result != class_id); | 2861 ASSERT(result != class_id); |
2877 LoadIsolate(result); | 2862 LoadIsolate(result); |
2878 const intptr_t offset = | 2863 const intptr_t offset = |
2879 Isolate::class_table_offset() + ClassTable::table_offset(); | 2864 Isolate::class_table_offset() + ClassTable::table_offset(); |
2880 movl(result, Address(result, offset)); | 2865 movl(result, Address(result, offset)); |
(...skipping 16 matching lines...) Expand all Loading... |
2897 } | 2882 } |
2898 | 2883 |
2899 | 2884 |
2900 void Assembler::SmiUntagOrCheckClass(Register object, | 2885 void Assembler::SmiUntagOrCheckClass(Register object, |
2901 intptr_t class_id, | 2886 intptr_t class_id, |
2902 Register scratch, | 2887 Register scratch, |
2903 Label* is_smi) { | 2888 Label* is_smi) { |
2904 ASSERT(kSmiTagShift == 1); | 2889 ASSERT(kSmiTagShift == 1); |
2905 ASSERT(RawObject::kClassIdTagPos == 16); | 2890 ASSERT(RawObject::kClassIdTagPos == 16); |
2906 ASSERT(RawObject::kClassIdTagSize == 16); | 2891 ASSERT(RawObject::kClassIdTagSize == 16); |
2907 const intptr_t class_id_offset = Object::tags_offset() + | 2892 const intptr_t class_id_offset = |
2908 RawObject::kClassIdTagPos / kBitsPerByte; | 2893 Object::tags_offset() + RawObject::kClassIdTagPos / kBitsPerByte; |
2909 | 2894 |
2910 // Untag optimistically. Tag bit is shifted into the CARRY. | 2895 // Untag optimistically. Tag bit is shifted into the CARRY. |
2911 SmiUntag(object); | 2896 SmiUntag(object); |
2912 j(NOT_CARRY, is_smi, kNearJump); | 2897 j(NOT_CARRY, is_smi, kNearJump); |
2913 // Load cid: can't use LoadClassId, object is untagged. Use TIMES_2 scale | 2898 // Load cid: can't use LoadClassId, object is untagged. Use TIMES_2 scale |
2914 // factor in the addressing mode to compensate for this. | 2899 // factor in the addressing mode to compensate for this. |
2915 movzxw(scratch, Address(object, TIMES_2, class_id_offset)); | 2900 movzxw(scratch, Address(object, TIMES_2, class_id_offset)); |
2916 cmpl(scratch, Immediate(class_id)); | 2901 cmpl(scratch, Immediate(class_id)); |
2917 } | 2902 } |
2918 | 2903 |
(...skipping 24 matching lines...) Expand all Loading... |
2943 | 2928 |
2944 Address Assembler::ElementAddressForIntIndex(bool is_external, | 2929 Address Assembler::ElementAddressForIntIndex(bool is_external, |
2945 intptr_t cid, | 2930 intptr_t cid, |
2946 intptr_t index_scale, | 2931 intptr_t index_scale, |
2947 Register array, | 2932 Register array, |
2948 intptr_t index) { | 2933 intptr_t index) { |
2949 if (is_external) { | 2934 if (is_external) { |
2950 return Address(array, index * index_scale); | 2935 return Address(array, index * index_scale); |
2951 } else { | 2936 } else { |
2952 const int64_t disp = static_cast<int64_t>(index) * index_scale + | 2937 const int64_t disp = static_cast<int64_t>(index) * index_scale + |
2953 Instance::DataOffsetFor(cid); | 2938 Instance::DataOffsetFor(cid); |
2954 ASSERT(Utils::IsInt(32, disp)); | 2939 ASSERT(Utils::IsInt(32, disp)); |
2955 return FieldAddress(array, static_cast<int32_t>(disp)); | 2940 return FieldAddress(array, static_cast<int32_t>(disp)); |
2956 } | 2941 } |
2957 } | 2942 } |
2958 | 2943 |
2959 | 2944 |
2960 static ScaleFactor ToScaleFactor(intptr_t index_scale) { | 2945 static ScaleFactor ToScaleFactor(intptr_t index_scale) { |
2961 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays with | 2946 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays with |
2962 // index scale factor > 1. E.g., for Uint8Array and OneByteString the index is | 2947 // index scale factor > 1. E.g., for Uint8Array and OneByteString the index is |
2963 // expected to be untagged before accessing. | 2948 // expected to be untagged before accessing. |
2964 ASSERT(kSmiTagShift == 1); | 2949 ASSERT(kSmiTagShift == 1); |
2965 switch (index_scale) { | 2950 switch (index_scale) { |
2966 case 1: return TIMES_1; | 2951 case 1: |
2967 case 2: return TIMES_1; | 2952 return TIMES_1; |
2968 case 4: return TIMES_2; | 2953 case 2: |
2969 case 8: return TIMES_4; | 2954 return TIMES_1; |
2970 case 16: return TIMES_8; | 2955 case 4: |
| 2956 return TIMES_2; |
| 2957 case 8: |
| 2958 return TIMES_4; |
| 2959 case 16: |
| 2960 return TIMES_8; |
2971 default: | 2961 default: |
2972 UNREACHABLE(); | 2962 UNREACHABLE(); |
2973 return TIMES_1; | 2963 return TIMES_1; |
2974 } | 2964 } |
2975 } | 2965 } |
2976 | 2966 |
2977 | 2967 |
2978 Address Assembler::ElementAddressForRegIndex(bool is_external, | 2968 Address Assembler::ElementAddressForRegIndex(bool is_external, |
2979 intptr_t cid, | 2969 intptr_t cid, |
2980 intptr_t index_scale, | 2970 intptr_t index_scale, |
2981 Register array, | 2971 Register array, |
2982 Register index) { | 2972 Register index) { |
2983 if (is_external) { | 2973 if (is_external) { |
2984 return Address(array, index, ToScaleFactor(index_scale), 0); | 2974 return Address(array, index, ToScaleFactor(index_scale), 0); |
2985 } else { | 2975 } else { |
2986 return FieldAddress(array, | 2976 return FieldAddress(array, index, ToScaleFactor(index_scale), |
2987 index, | |
2988 ToScaleFactor(index_scale), | |
2989 Instance::DataOffsetFor(cid)); | 2977 Instance::DataOffsetFor(cid)); |
2990 } | 2978 } |
2991 } | 2979 } |
2992 | 2980 |
2993 | 2981 |
2994 static const char* cpu_reg_names[kNumberOfCpuRegisters] = { | 2982 static const char* cpu_reg_names[kNumberOfCpuRegisters] = { |
2995 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" | 2983 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"}; |
2996 }; | |
2997 | 2984 |
2998 | 2985 |
2999 const char* Assembler::RegisterName(Register reg) { | 2986 const char* Assembler::RegisterName(Register reg) { |
3000 ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters)); | 2987 ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters)); |
3001 return cpu_reg_names[reg]; | 2988 return cpu_reg_names[reg]; |
3002 } | 2989 } |
3003 | 2990 |
3004 | 2991 |
3005 static const char* xmm_reg_names[kNumberOfXmmRegisters] = { | 2992 static const char* xmm_reg_names[kNumberOfXmmRegisters] = { |
3006 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" | 2993 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"}; |
3007 }; | |
3008 | 2994 |
3009 | 2995 |
3010 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 2996 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
3011 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 2997 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
3012 return xmm_reg_names[reg]; | 2998 return xmm_reg_names[reg]; |
3013 } | 2999 } |
3014 | 3000 |
3015 | 3001 |
3016 } // namespace dart | 3002 } // namespace dart |
3017 | 3003 |
3018 #endif // defined TARGET_ARCH_IA32 | 3004 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |