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 |