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 |
104 // Runtime and native call support. | 113 // Runtime and native call support. |
105 enum CallKind { | 114 enum CallKind { |
106 kRuntimeCall, | 115 kRuntimeCall, |
107 kLeafRuntimeCall, | 116 kLeafRuntimeCall, |
108 kLeafFloatRuntimeCall, | 117 kLeafFloatRuntimeCall, |
109 kBootstrapNativeCall, | 118 kBootstrapNativeCall, |
110 kNativeCall | 119 kNativeCall |
111 }; | 120 }; |
112 static uword RedirectExternalReference(uword function, | 121 static uword RedirectExternalReference(uword function, |
113 CallKind call_kind, | 122 CallKind call_kind, |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 inline int16_t ReadH(uword addr, Instr* instr); | 180 inline int16_t ReadH(uword addr, Instr* instr); |
172 inline void WriteH(uword addr, uint16_t value, Instr* instr); | 181 inline void WriteH(uword addr, uint16_t value, Instr* instr); |
173 | 182 |
174 inline uint32_t ReadWU(uword addr, Instr* instr); | 183 inline uint32_t ReadWU(uword addr, Instr* instr); |
175 inline int32_t ReadW(uword addr, Instr* instr); | 184 inline int32_t ReadW(uword addr, Instr* instr); |
176 inline void WriteW(uword addr, uint32_t value, Instr* instr); | 185 inline void WriteW(uword addr, uint32_t value, Instr* instr); |
177 | 186 |
178 inline intptr_t ReadX(uword addr, Instr* instr); | 187 inline intptr_t ReadX(uword addr, Instr* instr); |
179 inline void WriteX(uword addr, intptr_t value, Instr* instr); | 188 inline void WriteX(uword addr, intptr_t value, Instr* instr); |
180 | 189 |
| 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 |
181 // Synchronization primitives support. | 206 // Synchronization primitives support. |
182 void ClearExclusive(); | 207 void ClearExclusive(); |
183 intptr_t ReadExclusiveX(uword addr, Instr* instr); | 208 intptr_t ReadExclusiveX(uword addr, Instr* instr); |
184 intptr_t WriteExclusiveX(uword addr, intptr_t value, Instr* instr); | 209 intptr_t WriteExclusiveX(uword addr, intptr_t value, Instr* instr); |
185 // 32 bit versions. | 210 // 32 bit versions. |
186 intptr_t ReadExclusiveW(uword addr, Instr* instr); | 211 intptr_t ReadExclusiveW(uword addr, Instr* instr); |
187 intptr_t WriteExclusiveW(uword addr, intptr_t value, Instr* instr); | 212 intptr_t WriteExclusiveW(uword addr, intptr_t value, Instr* instr); |
188 | 213 |
189 // Exclusive access reservation: address and value observed during | 214 // Set access to given address to 'exclusive state' for current thread. |
190 // load-exclusive. Store-exclusive verifies that address is the same and | 215 static void SetExclusiveAccess(uword addr); |
191 // performs atomic compare-and-swap with remembered value to observe value | 216 |
192 // changes. This implementation of ldxr/stxr instructions does not detect | 217 // Returns true if the current thread has exclusive access to given address, |
193 // ABA situation and our uses of ldxr/stxr don't need this detection. | 218 // returns false otherwise. In either case, set access to given address to |
194 uword exclusive_access_addr_; | 219 // 'open state' for all threads. |
195 uword exclusive_access_value_; | 220 // If given addr is NULL, set access to 'open state' for current |
| 221 // thread (CLREX). |
| 222 static bool HasExclusiveAccessAndOpen(uword addr); |
196 | 223 |
197 // Helper functions to set the conditional flags in the architecture state. | 224 // Helper functions to set the conditional flags in the architecture state. |
198 void SetNZFlagsW(int32_t val); | 225 void SetNZFlagsW(int32_t val); |
199 bool CarryFromW(int32_t left, int32_t right, int32_t carry); | 226 bool CarryFromW(int32_t left, int32_t right, int32_t carry); |
200 bool OverflowFromW(int32_t left, int32_t right, int32_t carry); | 227 bool OverflowFromW(int32_t left, int32_t right, int32_t carry); |
201 | 228 |
202 void SetNZFlagsX(int64_t val); | 229 void SetNZFlagsX(int64_t val); |
203 bool CarryFromX(int64_t alu_out, int64_t left, int64_t right, bool addition); | 230 bool CarryFromX(int64_t alu_out, int64_t left, int64_t right, bool addition); |
204 bool OverflowFromX(int64_t alu_out, | 231 bool OverflowFromX(int64_t alu_out, |
205 int64_t left, | 232 int64_t left, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 } | 271 } |
245 | 272 |
246 friend class SimulatorDebugger; | 273 friend class SimulatorDebugger; |
247 friend class SimulatorSetjmpBuffer; | 274 friend class SimulatorSetjmpBuffer; |
248 DISALLOW_COPY_AND_ASSIGN(Simulator); | 275 DISALLOW_COPY_AND_ASSIGN(Simulator); |
249 }; | 276 }; |
250 | 277 |
251 } // namespace dart | 278 } // namespace dart |
252 | 279 |
253 #endif // RUNTIME_VM_SIMULATOR_ARM64_H_ | 280 #endif // RUNTIME_VM_SIMULATOR_ARM64_H_ |
OLD | NEW |