Flutter Engine
The Flutter Engine
simulator_arm64.h
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
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
7// on regular desktop machines.
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
10// on a ARM64 HW platform.
11
12#ifndef RUNTIME_VM_SIMULATOR_ARM64_H_
13#define RUNTIME_VM_SIMULATOR_ARM64_H_
14
15#ifndef RUNTIME_VM_SIMULATOR_H_
16#error Do not include simulator_arm64.h directly; use simulator.h.
17#endif
18
19#include "vm/constants.h"
20#include "vm/random.h"
21
22namespace dart {
23
24class Isolate;
25class Mutex;
26class SimulatorSetjmpBuffer;
27class Thread;
28
29typedef struct {
30 union {
31 int64_t i64[2];
32 int32_t i32[4];
34} simd_value_t;
35
36class Simulator {
37 public:
38 static constexpr uword kSimulatorStackUnderflowSize = 64;
39
42
43 // The currently executing Simulator instance, which is associated to the
44 // current isolate
45 static Simulator* Current();
46
47 // Accessors for register state.
48 // The default value for R31Type has to be R31IsSP because get_register is
49 // accessed from architecture independent code through SPREG without
50 // specifying the type. We also can't translate a dummy value for SPREG into
51 // a real value because the architecture independent code expects SPREG to
52 // be a real register value.
53 void set_register(Instr* instr,
54 Register reg,
55 int64_t value,
56 R31Type r31t = R31IsSP);
57 int64_t get_register(Register reg, R31Type r31t = R31IsSP) const;
58 void set_wregister(Register reg, int32_t value, R31Type r31t = R31IsSP);
59 int32_t get_wregister(Register reg, R31Type r31t = R31IsSP) const;
60
61 int32_t get_vregisters(VRegister reg, int idx) const;
62 void set_vregisters(VRegister reg, int idx, int32_t value);
63
64 int64_t get_vregisterd(VRegister reg, int idx) const;
65 void set_vregisterd(VRegister reg, int idx, int64_t value);
66
69
70 int64_t get_sp() const { return get_register(SPREG); }
71 int64_t get_lr() const { return get_register(R30); }
72
73 uint64_t get_pc() const;
74 uint64_t get_last_pc() const;
75 void set_pc(uint64_t pc);
76
77 // High address.
78 uword stack_base() const { return stack_base_; }
79 // Limit for StackOverflowError.
80 uword overflow_stack_limit() const { return overflow_stack_limit_; }
81 // Low address.
82 uword stack_limit() const { return stack_limit_; }
83
84 // Accessor to the instruction counter.
85 uint64_t get_icount() const { return icount_; }
86
87 // Call on program start.
88 static void Init();
89
90 // Dart generally calls into generated code with 4 parameters. This is a
91 // convenience function, which sets up the simulator state and grabs the
92 // result on return. The return value is R0. The parameters are placed in
93 // R0-3.
94 int64_t Call(int64_t entry,
95 int64_t parameter0,
96 int64_t parameter1,
97 int64_t parameter2,
98 int64_t parameter3,
99 bool fp_return = false,
100 bool fp_args = false);
101
102 // Runtime and native call support.
103 enum CallKind {
108 };
110 CallKind call_kind,
111 int argument_count);
112
114
115 void JumpToFrame(uword pc, uword sp, uword fp, Thread* thread);
116
117 private:
118 // Known bad pc value to ensure that the simulator does not execute
119 // without being properly setup.
120 static constexpr uword kBadLR = -1;
121 // A pc value used to signal the simulator to stop execution. Generally
122 // the lr is set to this value on transition from native C code to
123 // simulated execution, so that the simulator can "return" to the native
124 // C code.
125 static constexpr uword kEndSimulatingPC = -2;
126
127 // CPU state.
128 int64_t registers_[kNumberOfCpuRegisters];
129 bool n_flag_;
130 bool z_flag_;
131 bool c_flag_;
132 bool v_flag_;
133
135
136 // Simulator support.
137 int64_t last_pc_;
138 int64_t pc_;
139 char* stack_;
140 uword stack_limit_;
141 uword overflow_stack_limit_;
142 uword stack_base_;
143 bool pc_modified_;
144 uint64_t icount_;
145 static int64_t flag_stop_sim_at_;
146 Random random_;
147 SimulatorSetjmpBuffer* last_setjmp_buffer_;
148
149 // Registered breakpoints.
150 Instr* break_pc_;
151 int64_t break_instr_;
152
153 // Illegal memory access support.
154 static bool IsIllegalAddress(uword addr) { return addr < 64 * 1024; }
155 void HandleIllegalAccess(uword addr, Instr* instr);
156
157 // Handles an unaligned memory access.
158 void UnalignedAccess(const char* msg, uword addr, Instr* instr);
159
160 // Handles a legal instruction that the simulator does not implement.
161 void UnimplementedInstruction(Instr* instr);
162
163 // Unsupported instructions use Format to print an error and stop execution.
164 void Format(Instr* instr, const char* format);
165
166 inline uint8_t ReadBU(uword addr);
167 inline int8_t ReadB(uword addr);
168 inline void WriteB(uword addr, uint8_t value);
169
170 inline uint16_t ReadHU(uword addr, Instr* instr);
171 inline int16_t ReadH(uword addr, Instr* instr);
172 inline void WriteH(uword addr, uint16_t value, Instr* instr);
173
174 inline uint32_t ReadWU(uword addr,
175 Instr* instr,
176 bool must_be_aligned = false);
177 inline int32_t ReadW(uword addr, Instr* instr);
178 inline void WriteW(uword addr, uint32_t value, Instr* instr);
179
180 inline intptr_t ReadX(uword addr, Instr* instr, bool must_be_aligned = false);
181 inline void WriteX(uword addr, intptr_t value, Instr* instr);
182
183 // Synchronization primitives support.
184 void ClearExclusive();
185 intptr_t ReadExclusiveX(uword addr, Instr* instr);
186 intptr_t WriteExclusiveX(uword addr, intptr_t value, Instr* instr);
187 // 32 bit versions.
188 intptr_t ReadExclusiveW(uword addr, Instr* instr);
189 intptr_t WriteExclusiveW(uword addr, intptr_t value, Instr* instr);
190
191 // Load Acquire & Store Release.
192 intptr_t ReadAcquire(uword addr, Instr* instr);
193 uint32_t ReadAcquireW(uword addr, Instr* instr);
194 void WriteRelease(uword addr, intptr_t value, Instr* instr);
195 void WriteReleaseW(uword addr, uint32_t value, Instr* instr);
196
197 // Exclusive access reservation: address and value observed during
198 // load-exclusive. Store-exclusive verifies that address is the same and
199 // performs atomic compare-and-swap with remembered value to observe value
200 // changes. This implementation of ldxr/stxr instructions does not detect
201 // ABA situation and our uses of ldxr/stxr don't need this detection.
202 uword exclusive_access_addr_;
203 uword exclusive_access_value_;
204
205 // Helper functions to set the conditional flags in the architecture state.
206 void SetNZFlagsW(int32_t val);
207 bool CarryFromW(int32_t left, int32_t right, int32_t carry);
208 bool OverflowFromW(int32_t left, int32_t right, int32_t carry);
209
210 void SetNZFlagsX(int64_t val);
211 bool CarryFromX(int64_t alu_out, int64_t left, int64_t right, bool addition);
212 bool OverflowFromX(int64_t alu_out,
213 int64_t left,
214 int64_t right,
215 bool addition);
216
217 void SetCFlag(bool val);
218 void SetVFlag(bool val);
219
220 int64_t ShiftOperand(uint8_t reg_size,
221 int64_t value,
222 Shift shift_type,
223 uint8_t amount);
224
225 int64_t ExtendOperand(uint8_t reg_size,
226 int64_t value,
227 Extend extend_type,
228 uint8_t amount);
229
230 int64_t DecodeShiftExtendOperand(Instr* instr);
231
232 bool ConditionallyExecute(Instr* instr);
233
234 void DoRedirectedCall(Instr* instr);
235
236 // Decode instructions.
237 void InstructionDecode(Instr* instr);
238 void InstructionDecodeImpl(Instr* instr);
239#define DECODE_OP(op) void Decode##op(Instr* instr);
241#undef DECODE_OP
242
243 // Executes ARM64 instructions until the PC reaches kEndSimulatingPC.
244 void Execute();
245 void ExecuteNoTrace();
246 void ExecuteTrace();
247
248 void ClobberVolatileRegisters();
249
250 // Returns true if tracing of executed instructions is enabled.
251 bool IsTracingExecution() const;
252
253 // Longjmp support for exceptions.
254 SimulatorSetjmpBuffer* last_setjmp_buffer() { return last_setjmp_buffer_; }
255 void set_last_setjmp_buffer(SimulatorSetjmpBuffer* buffer) {
256 last_setjmp_buffer_ = buffer;
257 }
258
259 friend class SimulatorDebugger;
260 friend class SimulatorSetjmpBuffer;
262};
263
264} // namespace dart
265
266#endif // RUNTIME_VM_SIMULATOR_ARM64_H_
void set_pc(uint64_t pc)
void set_vregisterd(VRegister reg, int idx, int64_t value)
int64_t get_vregisterd(VRegister reg, int idx) const
int64_t get_register(Register reg, R31Type r31t=R31IsSP) const
static uword RedirectExternalReference(uword function, CallKind call_kind, int argument_count)
void JumpToFrame(uword pc, uword sp, uword fp, Thread *thread)
uint64_t get_pc() const
friend class SimulatorSetjmpBuffer
static Simulator * Current()
uword stack_base() const
uint64_t get_icount() const
int32_t get_vregisters(VRegister reg, int idx) const
void get_vregister(VRegister reg, simd_value_t *value) const
uword overflow_stack_limit() const
void set_vregister(VRegister reg, const simd_value_t &value)
static void Init()
void set_vregisters(VRegister reg, int idx, int32_t value)
uword stack_limit() const
friend class SimulatorDebugger
static constexpr uword kSimulatorStackUnderflowSize
Definition: simulator_arm.h:43
uint64_t get_last_pc() const
int64_t Call(int64_t entry, int64_t parameter0, int64_t parameter1, int64_t parameter2, int64_t parameter3, bool fp_return=false, bool fp_args=false)
int32_t get_wregister(Register reg, R31Type r31t=R31IsSP) const
DART_FORCE_INLINE int32_t get_register(Register reg) const
Definition: simulator_arm.h:56
void set_register(Instr *instr, Register reg, int64_t value, R31Type r31t=R31IsSP)
void set_wregister(Register reg, int32_t value, R31Type r31t=R31IsSP)
int64_t get_sp() const
int64_t get_lr() const
static uword FunctionForRedirect(uword redirect)
#define APPLY_OP_LIST(_V)
uint8_t value
uint32_t uint32_t * format
Dart_NativeFunction function
Definition: fuchsia.cc:51
int argument_count
Definition: fuchsia.cc:52
Definition: dart_vm.cc:33
uintptr_t uword
Definition: globals.h:501
const uint32_t fp
@ kNumberOfCpuRegisters
Definition: constants_arm.h:98
@ kNumberOfVRegisters
const Register SPREG
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:581
#define DECODE_OP(op)