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