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