| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 // Declares a Simulator for ARM64 instructions if we are not generating a native | 5 // Declares a Simulator for ARM64 instructions if we are not generating a native |
| 6 // ARM64 binary. This Simulator allows us to run and debug ARM64 code generation | 6 // ARM64 binary. This Simulator allows us to run and debug ARM64 code generation |
| 7 // on regular desktop machines. | 7 // on regular desktop machines. |
| 8 // Dart calls into generated code by "calling" the InvokeDartCode stub, | 8 // Dart calls into generated code by "calling" the InvokeDartCode stub, |
| 9 // which will start execution in the Simulator or forwards to the real entry | 9 // which will start execution in the Simulator or forwards to the real entry |
| 10 // on a ARM64 HW platform. | 10 // on a ARM64 HW platform. |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 // result on return. The return value is R0. The parameters are placed in | 94 // result on return. The return value is R0. The parameters are placed in |
| 95 // R0-3. | 95 // R0-3. |
| 96 int64_t Call(int64_t entry, | 96 int64_t Call(int64_t entry, |
| 97 int64_t parameter0, | 97 int64_t parameter0, |
| 98 int64_t parameter1, | 98 int64_t parameter1, |
| 99 int64_t parameter2, | 99 int64_t parameter2, |
| 100 int64_t parameter3, | 100 int64_t parameter3, |
| 101 bool fp_return = false, | 101 bool fp_return = false, |
| 102 bool fp_args = false); | 102 bool fp_args = false); |
| 103 | 103 |
| 104 // Implementation of atomic compare and exchange in the same synchronization | |
| 105 // domain as other synchronization primitive instructions (e.g. ldrex, strex). | |
| 106 static uword CompareExchange(uword* address, | |
| 107 uword compare_value, | |
| 108 uword new_value); | |
| 109 static uint32_t CompareExchangeUint32(uint32_t* address, | |
| 110 uint32_t compare_value, | |
| 111 uint32_t new_value); | |
| 112 | |
| 113 // Runtime and native call support. | 104 // Runtime and native call support. |
| 114 enum CallKind { | 105 enum CallKind { |
| 115 kRuntimeCall, | 106 kRuntimeCall, |
| 116 kLeafRuntimeCall, | 107 kLeafRuntimeCall, |
| 117 kLeafFloatRuntimeCall, | 108 kLeafFloatRuntimeCall, |
| 118 kBootstrapNativeCall, | 109 kBootstrapNativeCall, |
| 119 kNativeCall | 110 kNativeCall |
| 120 }; | 111 }; |
| 121 static uword RedirectExternalReference(uword function, | 112 static uword RedirectExternalReference(uword function, |
| 122 CallKind call_kind, | 113 CallKind call_kind, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 inline int16_t ReadH(uword addr, Instr* instr); | 171 inline int16_t ReadH(uword addr, Instr* instr); |
| 181 inline void WriteH(uword addr, uint16_t value, Instr* instr); | 172 inline void WriteH(uword addr, uint16_t value, Instr* instr); |
| 182 | 173 |
| 183 inline uint32_t ReadWU(uword addr, Instr* instr); | 174 inline uint32_t ReadWU(uword addr, Instr* instr); |
| 184 inline int32_t ReadW(uword addr, Instr* instr); | 175 inline int32_t ReadW(uword addr, Instr* instr); |
| 185 inline void WriteW(uword addr, uint32_t value, Instr* instr); | 176 inline void WriteW(uword addr, uint32_t value, Instr* instr); |
| 186 | 177 |
| 187 inline intptr_t ReadX(uword addr, Instr* instr); | 178 inline intptr_t ReadX(uword addr, Instr* instr); |
| 188 inline void WriteX(uword addr, intptr_t value, Instr* instr); | 179 inline void WriteX(uword addr, intptr_t value, Instr* instr); |
| 189 | 180 |
| 190 // We keep track of 16 exclusive access address tags across all threads. | |
| 191 // Since we cannot simulate a native context switch, which clears | |
| 192 // the exclusive access state of the local monitor (using the CLREX | |
| 193 // instruction), we associate the thread requesting exclusive access to the | |
| 194 // address tag. Multiple threads requesting exclusive access (using the LDREX | |
| 195 // instruction) to the same address will result in multiple address tags being | |
| 196 // created for the same address, one per thread. | |
| 197 // At any given time, each thread is associated to at most one address tag. | |
| 198 static Mutex* exclusive_access_lock_; | |
| 199 static const int kNumAddressTags = 16; | |
| 200 static struct AddressTag { | |
| 201 Thread* thread; | |
| 202 uword addr; | |
| 203 } exclusive_access_state_[kNumAddressTags]; | |
| 204 static int next_address_tag_; | |
| 205 | |
| 206 // Synchronization primitives support. | 181 // Synchronization primitives support. |
| 207 void ClearExclusive(); | 182 void ClearExclusive(); |
| 208 intptr_t ReadExclusiveX(uword addr, Instr* instr); | 183 intptr_t ReadExclusiveX(uword addr, Instr* instr); |
| 209 intptr_t WriteExclusiveX(uword addr, intptr_t value, Instr* instr); | 184 intptr_t WriteExclusiveX(uword addr, intptr_t value, Instr* instr); |
| 210 // 32 bit versions. | 185 // 32 bit versions. |
| 211 intptr_t ReadExclusiveW(uword addr, Instr* instr); | 186 intptr_t ReadExclusiveW(uword addr, Instr* instr); |
| 212 intptr_t WriteExclusiveW(uword addr, intptr_t value, Instr* instr); | 187 intptr_t WriteExclusiveW(uword addr, intptr_t value, Instr* instr); |
| 213 | 188 |
| 214 // Set access to given address to 'exclusive state' for current thread. | 189 // Exclusive access reservation: address and value observed during |
| 215 static void SetExclusiveAccess(uword addr); | 190 // load-exclusive. Store-exclusive verifies that address is the same and |
| 216 | 191 // performs atomic compare-and-swap with remembered value to observe value |
| 217 // Returns true if the current thread has exclusive access to given address, | 192 // changes. This implementation of ldxr/stxr instructions does not detect |
| 218 // returns false otherwise. In either case, set access to given address to | 193 // ABA situation and our uses of ldxr/stxr don't need this detection. |
| 219 // 'open state' for all threads. | 194 uword exclusive_access_addr_; |
| 220 // If given addr is NULL, set access to 'open state' for current | 195 uword exclusive_access_value_; |
| 221 // thread (CLREX). | |
| 222 static bool HasExclusiveAccessAndOpen(uword addr); | |
| 223 | 196 |
| 224 // Helper functions to set the conditional flags in the architecture state. | 197 // Helper functions to set the conditional flags in the architecture state. |
| 225 void SetNZFlagsW(int32_t val); | 198 void SetNZFlagsW(int32_t val); |
| 226 bool CarryFromW(int32_t left, int32_t right, int32_t carry); | 199 bool CarryFromW(int32_t left, int32_t right, int32_t carry); |
| 227 bool OverflowFromW(int32_t left, int32_t right, int32_t carry); | 200 bool OverflowFromW(int32_t left, int32_t right, int32_t carry); |
| 228 | 201 |
| 229 void SetNZFlagsX(int64_t val); | 202 void SetNZFlagsX(int64_t val); |
| 230 bool CarryFromX(int64_t alu_out, int64_t left, int64_t right, bool addition); | 203 bool CarryFromX(int64_t alu_out, int64_t left, int64_t right, bool addition); |
| 231 bool OverflowFromX(int64_t alu_out, | 204 bool OverflowFromX(int64_t alu_out, |
| 232 int64_t left, | 205 int64_t left, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 } | 244 } |
| 272 | 245 |
| 273 friend class SimulatorDebugger; | 246 friend class SimulatorDebugger; |
| 274 friend class SimulatorSetjmpBuffer; | 247 friend class SimulatorSetjmpBuffer; |
| 275 DISALLOW_COPY_AND_ASSIGN(Simulator); | 248 DISALLOW_COPY_AND_ASSIGN(Simulator); |
| 276 }; | 249 }; |
| 277 | 250 |
| 278 } // namespace dart | 251 } // namespace dart |
| 279 | 252 |
| 280 #endif // RUNTIME_VM_SIMULATOR_ARM64_H_ | 253 #endif // RUNTIME_VM_SIMULATOR_ARM64_H_ |
| OLD | NEW |