Flutter Engine
The Flutter Engine
simulator_arm.h
Go to the documentation of this file.
1// Copyright (c) 2013, 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 ARM instructions if we are not generating a native
6// ARM binary. This Simulator allows us to run and debug ARM code generation on
7// 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 ARM HW platform.
11
12#ifndef RUNTIME_VM_SIMULATOR_ARM_H_
13#define RUNTIME_VM_SIMULATOR_ARM_H_
14
15#ifndef RUNTIME_VM_SIMULATOR_H_
16#error Do not include simulator_arm.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 union {
30 int8_t i8[16];
31 uint8_t u8[16];
32 int16_t i16[8];
33 uint16_t u16[8];
34 int32_t i32[4];
35 uint32_t u32[4];
36 float f32[4];
37 int64_t i64[2];
38 uint64_t u64[2];
40
41class Simulator {
42 public:
43 static constexpr uword kSimulatorStackUnderflowSize = 64;
44
47
48 // The currently executing Simulator instance, which is associated to the
49 // current isolate
50 static Simulator* Current();
51
52 // Accessors for register state. Reading the pc value adheres to the ARM
53 // architecture specification and is off by 8 from the currently executing
54 // instruction.
55 void set_register(Register reg, int32_t value);
56 DART_FORCE_INLINE int32_t get_register(Register reg) const {
57 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
58 return registers_[reg] + ((reg == PC) ? Instr::kPCReadOffset : 0);
59 }
60
61 int32_t get_sp() const { return get_register(SPREG); }
62 int32_t get_lr() const { return get_register(R14); }
63
64 // Special case of set_register and get_register to access the raw PC value.
65 void set_pc(int32_t value);
66 DART_FORCE_INLINE int32_t get_pc() const { return registers_[PC]; }
67
68 // Accessors for VFP register state.
69 void set_sregister(SRegister reg, float value);
70 float get_sregister(SRegister reg) const;
71 void set_dregister(DRegister reg, double value);
72 double get_dregister(DRegister reg) const;
75
76 // When moving integer (rather than floating point) values to/from
77 // the FPU registers, use the _bits calls to avoid gcc taking liberties with
78 // integers that map to such things as NaN floating point values.
80 int32_t get_sregister_bits(SRegister reg) const;
82 int64_t get_dregister_bits(DRegister reg) const;
83
84 // High address.
85 uword stack_base() const { return stack_base_; }
86 // Limit for StackOverflowError.
87 uword overflow_stack_limit() const { return overflow_stack_limit_; }
88 // Low address.
89 uword stack_limit() const { return stack_limit_; }
90
91 // Accessor to the instruction counter.
92 uint64_t get_icount() const { return icount_; }
93
94 // Call on program start.
95 static void Init();
96
97 // Dart generally calls into generated code with 4 parameters. This is a
98 // convenience function, which sets up the simulator state and grabs the
99 // result on return. When fp_return is true the return value is the D0
100 // floating point register. Otherwise, the return value is R1:R0.
101 // If fp_args is true, the parameters0-3 are placed in S0-3. Otherwise, they
102 // are placed in R0-3.
103 int64_t Call(int32_t entry,
104 int32_t parameter0,
105 int32_t parameter1,
106 int32_t parameter2,
107 int32_t parameter3,
108 bool fp_return = false,
109 bool fp_args = false);
110
111 // Runtime and native call support.
112 enum CallKind {
117 };
119 CallKind call_kind,
120 int argument_count);
121
123
124 void JumpToFrame(uword pc, uword sp, uword fp, Thread* thread);
125
126 private:
127 // Known bad pc value to ensure that the simulator does not execute
128 // without being properly setup.
129 static constexpr uword kBadLR = -1;
130 // A pc value used to signal the simulator to stop execution. Generally
131 // the lr is set to this value on transition from native C code to
132 // simulated execution, so that the simulator can "return" to the native
133 // C code.
134 static constexpr uword kEndSimulatingPC = -2;
135
136 // CPU state.
137 int32_t registers_[kNumberOfCpuRegisters];
138 bool n_flag_;
139 bool z_flag_;
140 bool c_flag_;
141 bool v_flag_;
142
143 // VFP state.
144 union { // S, D, and Q register banks are overlapping.
148 };
149 bool fp_n_flag_;
150 bool fp_z_flag_;
151 bool fp_c_flag_;
152 bool fp_v_flag_;
153
154 // Simulator support.
155 char* stack_;
156 uword stack_limit_;
157 uword overflow_stack_limit_;
158 uword stack_base_;
159 bool pc_modified_;
160 uint64_t icount_;
161 static int32_t flag_stop_sim_at_;
162 Random random_;
163 SimulatorSetjmpBuffer* last_setjmp_buffer_;
164
165 // Registered breakpoints.
166 Instr* break_pc_;
167 int32_t break_instr_;
168
169 // Illegal memory access support.
170 static bool IsIllegalAddress(uword addr) { return addr < 64 * 1024; }
171 void HandleIllegalAccess(uword addr, Instr* instr);
172
173 // Handles a legal instruction that the simulator does not implement.
174 void UnimplementedInstruction(Instr* instr);
175
176 // Unsupported instructions use Format to print an error and stop execution.
177 void Format(Instr* instr, const char* format);
178
179 // Checks if the current instruction should be executed based on its
180 // condition bits.
181 bool ConditionallyExecute(Instr* instr);
182
183 // Helper functions to set the conditional flags in the architecture state.
184 void SetNZFlags(int32_t val);
185 void SetCFlag(bool val);
186 void SetVFlag(bool val);
187 bool CarryFrom(int32_t left, int32_t right, int32_t carry);
188 bool OverflowFrom(int32_t left, int32_t right, int32_t carry);
189
190 // Helper functions to decode common "addressing" modes.
191 int32_t GetShiftRm(Instr* instr, bool* carry_out);
192 int32_t GetImm(Instr* instr, bool* carry_out);
193 void HandleRList(Instr* instr, bool load);
194 void SupervisorCall(Instr* instr);
195
196 // Read and write memory.
197 void UnalignedAccess(const char* msg, uword addr, Instr* instr);
198
199 // Perform a division.
200 void DoDivision(Instr* instr);
201
202 inline uint8_t ReadBU(uword addr);
203 inline int8_t ReadB(uword addr);
204 inline void WriteB(uword addr, uint8_t value);
205
206 inline uint16_t ReadHU(uword addr, Instr* instr);
207 inline int16_t ReadH(uword addr, Instr* instr);
208 inline void WriteH(uword addr, uint16_t value, Instr* instr);
209
210 inline intptr_t ReadW(uword addr, Instr* instr);
211 inline void WriteW(uword addr, intptr_t value, Instr* instr);
212
213 // Synchronization primitives support.
214 void ClearExclusive();
215 intptr_t ReadExclusiveW(uword addr, Instr* instr);
216 intptr_t WriteExclusiveW(uword addr, intptr_t value, Instr* instr);
217
218 // Exclusive access reservation: address and value observed during
219 // load-exclusive. Store-exclusive verifies that address is the same and
220 // performs atomic compare-and-swap with remembered value to observe value
221 // changes. This implementation of ldrex/strex instructions does not detect
222 // ABA situation and our uses of ldrex/strex don't need this detection.
223 uword exclusive_access_addr_;
224 uword exclusive_access_value_;
225
226 // Executing is handled based on the instruction type.
227 void DecodeType01(Instr* instr); // Both type 0 and type 1 rolled into one.
228 void DecodeType2(Instr* instr);
229 void DecodeType3(Instr* instr);
230 void DecodeType4(Instr* instr);
231 void DecodeType5(Instr* instr);
232 void DecodeType6(Instr* instr);
233 void DecodeType7(Instr* instr);
234 void DecodeSIMDDataProcessing(Instr* instr);
235
236 // Executes one instruction.
237 void InstructionDecode(Instr* instr);
238 void InstructionDecodeImpl(Instr* instr);
239
240 // Executes ARM instructions until the PC reaches kEndSimulatingPC.
241 void Execute();
242 void ExecuteNoTrace();
243 void ExecuteTrace();
244
245 void ClobberVolatileRegisters();
246
247 // Returns true if tracing of executed instructions is enabled.
248 bool IsTracingExecution() const;
249
250 // Longjmp support for exceptions.
251 SimulatorSetjmpBuffer* last_setjmp_buffer() { return last_setjmp_buffer_; }
252 void set_last_setjmp_buffer(SimulatorSetjmpBuffer* buffer) {
253 last_setjmp_buffer_ = buffer;
254 }
255
256 friend class SimulatorDebugger;
259};
260
261} // namespace dart
262
263#endif // RUNTIME_VM_SIMULATOR_ARM_H_
SI T load(const P *ptr)
Definition: Transform_inl.h:98
int64_t dregisters_[kNumberOfDRegisters]
void set_register(Register reg, int32_t value)
simd_value_t qregisters_[kNumberOfQRegisters]
void set_pc(int32_t value)
int32_t get_sp() const
Definition: simulator_arm.h:61
void set_dregister(DRegister reg, double value)
DART_FORCE_INLINE int32_t get_pc() const
Definition: simulator_arm.h:66
static uword RedirectExternalReference(uword function, CallKind call_kind, int argument_count)
int32_t get_lr() const
Definition: simulator_arm.h:62
void JumpToFrame(uword pc, uword sp, uword fp, Thread *thread)
friend class SimulatorSetjmpBuffer
void set_dregister_bits(DRegister reg, int64_t value)
static Simulator * Current()
uword stack_base() const
Definition: simulator_arm.h:85
void set_qregister(QRegister reg, const simd_value_t &value)
uint64_t get_icount() const
Definition: simulator_arm.h:92
float get_sregister(SRegister reg) const
uword overflow_stack_limit() const
Definition: simulator_arm.h:87
static void Init()
int64_t get_dregister_bits(DRegister reg) const
void set_sregister_bits(SRegister reg, int32_t value)
uword stack_limit() const
Definition: simulator_arm.h:89
friend class SimulatorDebugger
static constexpr uword kSimulatorStackUnderflowSize
Definition: simulator_arm.h:43
DART_FORCE_INLINE int32_t get_register(Register reg) const
Definition: simulator_arm.h:56
void set_sregister(SRegister reg, float value)
double get_dregister(DRegister reg) const
void get_qregister(QRegister reg, simd_value_t *value) const
int32_t get_sregister_bits(SRegister reg) const
int32_t sregisters_[kNumberOfSRegisters]
int64_t Call(int32_t entry, int32_t parameter0, int32_t parameter1, int32_t parameter2, int32_t parameter3, bool fp_return=false, bool fp_args=false)
static uword FunctionForRedirect(uword redirect)
#define ASSERT(E)
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
@ kNumberOfSRegisters
@ kNumberOfQRegisters
@ kNumberOfDRegisters
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