| 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 <setjmp.h> | 5 #include <setjmp.h> |
| 6 #include <stdlib.h> | 6 #include <stdlib.h> |
| 7 | 7 |
| 8 #include "vm/globals.h" | 8 #include "vm/globals.h" |
| 9 #if defined(TARGET_ARCH_ARM) | 9 #if defined(TARGET_ARCH_ARM) |
| 10 | 10 |
| 11 // Only build the simulator if not compiling for real ARM hardware. | 11 // Only build the simulator if not compiling for real ARM hardware. |
| 12 #if !defined(HOST_ARCH_ARM) | 12 #if !defined(HOST_ARCH_ARM) |
| 13 | 13 |
| 14 #include "vm/simulator.h" | 14 #include "vm/simulator.h" |
| 15 | 15 |
| 16 #include "vm/assembler.h" | 16 #include "vm/assembler.h" |
| 17 #include "vm/constants_arm.h" | 17 #include "vm/constants_arm.h" |
| 18 #include "vm/cpu.h" | 18 #include "vm/cpu.h" |
| 19 #include "vm/disassembler.h" | 19 #include "vm/disassembler.h" |
| 20 #include "vm/lockers.h" |
| 20 #include "vm/native_arguments.h" | 21 #include "vm/native_arguments.h" |
| 21 #include "vm/stack_frame.h" | 22 #include "vm/stack_frame.h" |
| 22 #include "vm/thread.h" | 23 #include "vm/thread.h" |
| 23 | 24 |
| 24 namespace dart { | 25 namespace dart { |
| 25 | 26 |
| 26 DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution."); | 27 DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution."); |
| 27 DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at."); | 28 DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at."); |
| 28 | 29 |
| 29 | 30 |
| (...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 // Copy the newly read line into the result. | 669 // Copy the newly read line into the result. |
| 669 memmove(result + offset, line_buf, len); | 670 memmove(result + offset, line_buf, len); |
| 670 offset += len; | 671 offset += len; |
| 671 } | 672 } |
| 672 ASSERT(result != NULL); | 673 ASSERT(result != NULL); |
| 673 result[offset] = '\0'; | 674 result[offset] = '\0'; |
| 674 return result; | 675 return result; |
| 675 } | 676 } |
| 676 | 677 |
| 677 | 678 |
| 678 void Simulator::InitOnce() {} | 679 // Synchronization primitives support. |
| 680 Mutex* Simulator::exclusive_access_lock_ = NULL; |
| 681 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags]; |
| 682 int Simulator::next_address_tag_; |
| 683 |
| 684 |
| 685 void Simulator::SetExclusiveAccess(uword addr) { |
| 686 Isolate* isolate = Isolate::Current(); |
| 687 ASSERT(isolate != NULL); |
| 688 int i = 0; |
| 689 while ((i < kNumAddressTags) && |
| 690 (exclusive_access_state_[i].isolate != isolate)) { |
| 691 i++; |
| 692 } |
| 693 if (i == kNumAddressTags) { |
| 694 i = next_address_tag_; |
| 695 if (++next_address_tag_ == kNumAddressTags) next_address_tag_ = 0; |
| 696 exclusive_access_state_[i].isolate = isolate; |
| 697 } |
| 698 exclusive_access_state_[i].addr = addr; |
| 699 } |
| 700 |
| 701 |
| 702 bool Simulator::HasExclusiveAccessAndOpen(uword addr) { |
| 703 Isolate* isolate = Isolate::Current(); |
| 704 ASSERT(isolate != NULL); |
| 705 bool result = false; |
| 706 for (int i = 0; i < kNumAddressTags; i++) { |
| 707 if (exclusive_access_state_[i].isolate == isolate) { |
| 708 if (exclusive_access_state_[i].addr == addr) { |
| 709 result = true; |
| 710 } |
| 711 exclusive_access_state_[i].addr = NULL; |
| 712 continue; |
| 713 } |
| 714 if (exclusive_access_state_[i].addr == addr) { |
| 715 exclusive_access_state_[i].addr = NULL; |
| 716 } |
| 717 } |
| 718 return result; |
| 719 } |
| 720 |
| 721 |
| 722 void Simulator::InitOnce() { |
| 723 // Setup exclusive access state. |
| 724 exclusive_access_lock_ = new Mutex(); |
| 725 for (int i = 0; i < kNumAddressTags; i++) { |
| 726 exclusive_access_state_[i].isolate = NULL; |
| 727 exclusive_access_state_[i].addr = NULL; |
| 728 } |
| 729 next_address_tag_ = 0; |
| 730 } |
| 679 | 731 |
| 680 | 732 |
| 681 Simulator::Simulator() { | 733 Simulator::Simulator() { |
| 682 // Setup simulator support first. Some of this information is needed to | 734 // Setup simulator support first. Some of this information is needed to |
| 683 // setup the architecture state. | 735 // setup the architecture state. |
| 684 // We allocate the stack here, the size is computed as the sum of | 736 // We allocate the stack here, the size is computed as the sum of |
| 685 // the size specified by the user and the buffer space needed for | 737 // the size specified by the user and the buffer space needed for |
| 686 // handling stack overflow exceptions. To be safe in potential | 738 // handling stack overflow exceptions. To be safe in potential |
| 687 // stack underflows we also add some underflow buffer space. | 739 // stack underflows we also add some underflow buffer space. |
| 688 stack_ = new char[(Isolate::GetSpecifiedStackSize() + | 740 stack_ = new char[(Isolate::GetSpecifiedStackSize() + |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1052 | 1104 |
| 1053 | 1105 |
| 1054 void Simulator::WriteB(uword addr, uint8_t value) { | 1106 void Simulator::WriteB(uword addr, uint8_t value) { |
| 1055 static StatsCounter counter_write_b("Simulated byte writes"); | 1107 static StatsCounter counter_write_b("Simulated byte writes"); |
| 1056 counter_write_b.Increment(); | 1108 counter_write_b.Increment(); |
| 1057 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); | 1109 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); |
| 1058 *ptr = value; | 1110 *ptr = value; |
| 1059 } | 1111 } |
| 1060 | 1112 |
| 1061 | 1113 |
| 1114 // Synchronization primitives support. |
| 1115 void Simulator::ClearExclusive() { |
| 1116 // This lock is initialized in Simulator::InitOnce(). |
| 1117 MutexLocker ml(exclusive_access_lock_); |
| 1118 // Set exclusive access to open state for this isolate. |
| 1119 HasExclusiveAccessAndOpen(NULL); |
| 1120 } |
| 1121 |
| 1122 |
| 1123 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { |
| 1124 // This lock is initialized in Simulator::InitOnce(). |
| 1125 MutexLocker ml(exclusive_access_lock_); |
| 1126 SetExclusiveAccess(addr); |
| 1127 return ReadW(addr, instr); |
| 1128 } |
| 1129 |
| 1130 |
| 1131 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) { |
| 1132 // This lock is initialized in Simulator::InitOnce(). |
| 1133 MutexLocker ml(exclusive_access_lock_); |
| 1134 bool write_allowed = HasExclusiveAccessAndOpen(addr); |
| 1135 if (write_allowed) { |
| 1136 WriteW(addr, value, instr); |
| 1137 return 0; // Success. |
| 1138 } |
| 1139 return 1; // Failure. |
| 1140 } |
| 1141 |
| 1142 |
| 1143 uword Simulator::CompareExchange(uword* address, |
| 1144 uword compare_value, |
| 1145 uword new_value) { |
| 1146 // This lock is initialized in Simulator::InitOnce(). |
| 1147 MutexLocker ml(exclusive_access_lock_); |
| 1148 uword value = *address; |
| 1149 if (value == compare_value) { |
| 1150 *address = new_value; |
| 1151 // Same effect on exclusive access state as a successful STREX. |
| 1152 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address)); |
| 1153 } else { |
| 1154 // Same effect on exclusive access state as an LDREX. |
| 1155 SetExclusiveAccess(reinterpret_cast<uword>(address)); |
| 1156 } |
| 1157 return value; |
| 1158 } |
| 1159 |
| 1160 |
| 1062 // Returns the top of the stack area to enable checking for stack pointer | 1161 // Returns the top of the stack area to enable checking for stack pointer |
| 1063 // validity. | 1162 // validity. |
| 1064 uword Simulator::StackTop() const { | 1163 uword Simulator::StackTop() const { |
| 1065 // To be safe in potential stack underflows we leave some buffer above and | 1164 // To be safe in potential stack underflows we leave some buffer above and |
| 1066 // set the stack top. | 1165 // set the stack top. |
| 1067 return reinterpret_cast<uword>(stack_) + | 1166 return reinterpret_cast<uword>(stack_) + |
| 1068 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); | 1167 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); |
| 1069 } | 1168 } |
| 1070 | 1169 |
| 1071 | 1170 |
| (...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1732 SetNZFlags(hi_res); | 1831 SetNZFlags(hi_res); |
| 1733 } | 1832 } |
| 1734 break; | 1833 break; |
| 1735 } | 1834 } |
| 1736 default: { | 1835 default: { |
| 1737 UnimplementedInstruction(instr); | 1836 UnimplementedInstruction(instr); |
| 1738 break; | 1837 break; |
| 1739 } | 1838 } |
| 1740 } | 1839 } |
| 1741 } else { | 1840 } else { |
| 1742 UnimplementedInstruction(instr); | 1841 if (TargetCPUFeatures::arm_version() == ARMv5TE) { |
| 1842 UnimplementedInstruction(instr); |
| 1843 return; |
| 1844 } |
| 1845 // synchronization primitives |
| 1846 Register rd = instr->RdField(); |
| 1847 Register rn = instr->RnField(); |
| 1848 uword addr = get_register(rn); |
| 1849 switch (instr->Bits(20, 4)) { |
| 1850 case 8: { |
| 1851 // Format(instr, "strex'cond 'rd, 'rm, ['rn]"); |
| 1852 if (IsIllegalAddress(addr)) { |
| 1853 HandleIllegalAccess(addr, instr); |
| 1854 } else { |
| 1855 Register rm = instr->RmField(); |
| 1856 set_register(rd, WriteExclusiveW(addr, get_register(rm), instr)); |
| 1857 } |
| 1858 break; |
| 1859 } |
| 1860 case 9: { |
| 1861 // Format(instr, "ldrex'cond 'rd, ['rn]"); |
| 1862 if (IsIllegalAddress(addr)) { |
| 1863 HandleIllegalAccess(addr, instr); |
| 1864 } else { |
| 1865 set_register(rd, ReadExclusiveW(addr, instr)); |
| 1866 } |
| 1867 break; |
| 1868 } |
| 1869 default: { |
| 1870 UnimplementedInstruction(instr); |
| 1871 break; |
| 1872 } |
| 1873 } |
| 1743 } | 1874 } |
| 1744 } else if (instr->Bit(25) == 1) { | 1875 } else if (instr->Bit(25) == 1) { |
| 1745 // 16-bit immediate loads, msr (immediate), and hints | 1876 // 16-bit immediate loads, msr (immediate), and hints |
| 1746 switch (instr->Bits(20, 5)) { | 1877 switch (instr->Bits(20, 5)) { |
| 1747 case 16: | 1878 case 16: |
| 1748 case 20: { | 1879 case 20: { |
| 1749 if (TargetCPUFeatures::arm_version() == ARMv7) { | 1880 if (TargetCPUFeatures::arm_version() == ARMv7) { |
| 1750 uint16_t imm16 = instr->MovwField(); | 1881 uint16_t imm16 = instr->MovwField(); |
| 1751 Register rd = instr->RdField(); | 1882 Register rd = instr->RdField(); |
| 1752 if (instr->Bit(22) == 0) { | 1883 if (instr->Bit(22) == 0) { |
| (...skipping 1691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3444 void Simulator::InstructionDecode(Instr* instr) { | 3575 void Simulator::InstructionDecode(Instr* instr) { |
| 3445 pc_modified_ = false; | 3576 pc_modified_ = false; |
| 3446 if (FLAG_trace_sim) { | 3577 if (FLAG_trace_sim) { |
| 3447 const uword start = reinterpret_cast<uword>(instr); | 3578 const uword start = reinterpret_cast<uword>(instr); |
| 3448 const uword end = start + Instr::kInstrSize; | 3579 const uword end = start + Instr::kInstrSize; |
| 3449 Disassembler::Disassemble(start, end); | 3580 Disassembler::Disassemble(start, end); |
| 3450 } | 3581 } |
| 3451 if (instr->ConditionField() == kSpecialCondition) { | 3582 if (instr->ConditionField() == kSpecialCondition) { |
| 3452 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) { | 3583 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) { |
| 3453 // Format(instr, "clrex"); | 3584 // Format(instr, "clrex"); |
| 3454 UnimplementedInstruction(instr); | 3585 ClearExclusive(); |
| 3455 } else { | 3586 } else { |
| 3456 if (instr->IsSIMDDataProcessing()) { | 3587 if (instr->IsSIMDDataProcessing()) { |
| 3457 DecodeSIMDDataProcessing(instr); | 3588 DecodeSIMDDataProcessing(instr); |
| 3458 } else { | 3589 } else { |
| 3459 UnimplementedInstruction(instr); | 3590 UnimplementedInstruction(instr); |
| 3460 } | 3591 } |
| 3461 } | 3592 } |
| 3462 } else if (ConditionallyExecute(instr)) { | 3593 } else if (ConditionallyExecute(instr)) { |
| 3463 switch (instr->TypeField()) { | 3594 switch (instr->TypeField()) { |
| 3464 case 0: | 3595 case 0: |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3735 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); | 3866 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); |
| 3736 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); | 3867 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); |
| 3737 buf->Longjmp(); | 3868 buf->Longjmp(); |
| 3738 } | 3869 } |
| 3739 | 3870 |
| 3740 } // namespace dart | 3871 } // namespace dart |
| 3741 | 3872 |
| 3742 #endif // !defined(HOST_ARCH_ARM) | 3873 #endif // !defined(HOST_ARCH_ARM) |
| 3743 | 3874 |
| 3744 #endif // defined TARGET_ARCH_ARM | 3875 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |