Flutter Engine
The Flutter Engine
simulator_riscv.h
Go to the documentation of this file.
1// Copyright (c) 2017, 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#ifndef RUNTIME_VM_SIMULATOR_RISCV_H_
6#define RUNTIME_VM_SIMULATOR_RISCV_H_
7
8#ifndef RUNTIME_VM_SIMULATOR_H_
9#error Do not include simulator_riscv.h directly; use simulator.h.
10#endif
11
12#include "vm/constants.h"
13#include "vm/random.h"
14
15namespace dart {
16
17class Isolate;
18class Mutex;
19class SimulatorSetjmpBuffer;
20class Thread;
21
22// TODO(riscv): Dynamic rounding mode and other FSCR state.
23class Simulator {
24 public:
25 static constexpr uword kSimulatorStackUnderflowSize = 64;
26
29
30 static Simulator* Current();
31
32 intx_t CallX(intx_t function,
33 intx_t arg0 = 0,
34 intx_t arg1 = 0,
35 intx_t arg2 = 0,
36 intx_t arg3 = 0) {
37 PreservedRegisters preserved;
38 PrepareCall(&preserved);
39 set_xreg(A0, arg0);
40 set_xreg(A1, arg1);
41 set_xreg(A2, arg2);
42 set_xreg(A3, arg3);
43 RunCall(function, &preserved);
44 return get_xreg(A0);
45 }
46
47 intx_t CallI(intx_t function, double arg0, double arg1 = 0.0) {
48 PreservedRegisters preserved;
49 PrepareCall(&preserved);
50 set_fregd(FA0, arg0);
51 set_fregd(FA1, arg1);
52 RunCall(function, &preserved);
53 return get_xreg(A0);
54 }
55 intx_t CallI(intx_t function, float arg0, float arg1 = 0.0f) {
56 PreservedRegisters preserved;
57 PrepareCall(&preserved);
58 set_fregs(FA0, arg0);
59 set_fregs(FA1, arg1);
60 RunCall(function, &preserved);
61 return get_xreg(A0);
62 }
63
64 double CallD(intx_t function, intx_t arg0, intx_t arg1 = 0) {
65 PreservedRegisters preserved;
66 PrepareCall(&preserved);
67 set_xreg(A0, arg0);
68 set_xreg(A1, arg1);
69 RunCall(function, &preserved);
70 return get_fregd(FA0);
71 }
72 double CallD(intx_t function,
73 double arg0,
74 double arg1 = 0.0,
75 double arg2 = 0.0) {
76 PreservedRegisters preserved;
77 PrepareCall(&preserved);
78 set_fregd(FA0, arg0);
79 set_fregd(FA1, arg1);
80 set_fregd(FA2, arg2);
81 RunCall(function, &preserved);
82 return get_fregd(FA0);
83 }
84 double CallD(intx_t function, intx_t arg0, double arg1) {
85 PreservedRegisters preserved;
86 PrepareCall(&preserved);
87 set_xreg(A0, arg0);
88 set_fregd(FA0, arg1);
89 RunCall(function, &preserved);
90 return get_fregd(FA0);
91 }
92 double CallD(intx_t function, float arg0) {
93 PreservedRegisters preserved;
94 PrepareCall(&preserved);
95 set_fregs(FA0, arg0);
96 RunCall(function, &preserved);
97 return get_fregd(FA0);
98 }
99
100 float CallF(intx_t function, intx_t arg0, intx_t arg1 = 0) {
101 PreservedRegisters preserved;
102 SavePreservedRegisters(&preserved);
103 set_xreg(A0, arg0);
104 set_xreg(A1, arg1);
105 RunCall(function, &preserved);
106 return get_fregs(FA0);
107 }
108 float CallF(intx_t function,
109 float arg0,
110 float arg1 = 0.0f,
111 float arg2 = 0.0f) {
112 PreservedRegisters preserved;
113 PrepareCall(&preserved);
114 set_fregs(FA0, arg0);
115 set_fregs(FA1, arg1);
116 set_fregs(FA2, arg2);
117 RunCall(function, &preserved);
118 return get_fregs(FA0);
119 }
120 float CallF(intx_t function, intx_t arg0, float arg1) {
121 PreservedRegisters preserved;
122 PrepareCall(&preserved);
123 set_xreg(A0, arg0);
124 set_fregs(FA0, arg1);
125 RunCall(function, &preserved);
126 return get_fregs(FA0);
127 }
128 float CallF(intx_t function, double arg0) {
129 PreservedRegisters preserved;
130 PrepareCall(&preserved);
131 set_fregd(FA0, arg0);
132 RunCall(function, &preserved);
133 return get_fregs(FA0);
134 }
135
136 // Dart generally calls into generated code with 4 parameters. This is a
137 // convenience function, which sets up the simulator state and grabs the
138 // result on return. The return value is A0. The parameters are placed in
139 // A0-3.
140 int64_t Call(intx_t entry,
141 intx_t parameter0,
142 intx_t parameter1,
143 intx_t parameter2,
144 intx_t parameter3,
145 bool fp_return = false,
146 bool fp_args = false);
147
148 // Runtime and native call support.
149 enum CallKind {
154 };
156 CallKind call_kind,
157 int argument_count);
158
160
161 void JumpToFrame(uword pc, uword sp, uword fp, Thread* thread);
162
163 uintx_t get_register(Register rs) const { return get_xreg(rs); }
164 uintx_t get_pc() const { return pc_; }
165 uintx_t get_sp() const { return get_xreg(SP); }
166 uintx_t get_fp() const { return get_xreg(FP); }
167 uintx_t get_lr() const { return get_xreg(RA); }
170
171 // High address.
172 uword stack_base() const { return stack_base_; }
173 // Limit for StackOverflowError.
174 uword overflow_stack_limit() const { return overflow_stack_limit_; }
175 // Low address.
176 uword stack_limit() const { return stack_limit_; }
177
178 // Accessor to the instruction counter.
179 uint64_t get_icount() const { return instret_; }
180
181 // Call on program start.
182 static void Init();
183
184 private:
185 struct PreservedRegisters {
186 uintx_t xregs[kNumberOfCpuRegisters];
187 double fregs[kNumberOfFpuRegisters];
188 };
189 void PrepareCall(PreservedRegisters* preserved);
190 void ClobberVolatileRegisters();
191 void SavePreservedRegisters(PreservedRegisters* preserved);
192 void CheckPreservedRegisters(PreservedRegisters* preserved);
193 void RunCall(intx_t function, PreservedRegisters* preserved);
194
195 void Interpret(Instr instr);
196 void Interpret(CInstr instr);
197 void InterpretLUI(Instr instr);
198 void InterpretAUIPC(Instr instr);
199 void InterpretJAL(Instr instr);
200 void InterpretJALR(Instr instr);
201 void InterpretBRANCH(Instr instr);
202 void InterpretLOAD(Instr instr);
203 void InterpretSTORE(Instr instr);
204 void InterpretOPIMM(Instr instr);
205 void InterpretOPIMM32(Instr instr);
206 void InterpretOP(Instr instr);
207 void InterpretOP_0(Instr instr);
208 void InterpretOP_SUB(Instr instr);
209 void InterpretOP_MULDIV(Instr instr);
210 void InterpretOP_SHADD(Instr instr);
211 void InterpretOP_MINMAXCLMUL(Instr instr);
212 void InterpretOP_ROTATE(Instr instr);
213 void InterpretOP_BCLRBEXT(Instr instr);
214 void InterpretOP32(Instr instr);
215 void InterpretOP32_0(Instr instr);
216 void InterpretOP32_SUB(Instr instr);
217 void InterpretOP32_MULDIV(Instr instr);
218 void InterpretOP32_SHADD(Instr instr);
219 void InterpretOP32_ADDUW(Instr instr);
220 void InterpretOP32_ROTATE(Instr instr);
221 void InterpretMISCMEM(Instr instr);
222 void InterpretSYSTEM(Instr instr);
223 void InterpretECALL(Instr instr);
224 void InterpretEBREAK(Instr instr);
225 void InterpretEBREAK(CInstr instr);
226 void InterpretAMO(Instr instr);
227 void InterpretAMO8(Instr instr);
228 void InterpretAMO16(Instr instr);
229 void InterpretAMO32(Instr instr);
230 void InterpretAMO64(Instr instr);
231 template <typename type>
232 void InterpretLR(Instr instr);
233 template <typename type>
234 void InterpretSC(Instr instr);
235 template <typename type>
236 void InterpretAMOSWAP(Instr instr);
237 template <typename type>
238 void InterpretAMOADD(Instr instr);
239 template <typename type>
240 void InterpretAMOXOR(Instr instr);
241 template <typename type>
242 void InterpretAMOAND(Instr instr);
243 template <typename type>
244 void InterpretAMOOR(Instr instr);
245 template <typename type>
246 void InterpretAMOMIN(Instr instr);
247 template <typename type>
248 void InterpretAMOMAX(Instr instr);
249 template <typename type>
250 void InterpretAMOMINU(Instr instr);
251 template <typename type>
252 void InterpretAMOMAXU(Instr instr);
253 template <typename type>
254 void InterpretLOADORDERED(Instr instr);
255 template <typename type>
256 void InterpretSTOREORDERED(Instr instr);
257 void InterpretLOADFP(Instr instr);
258 void InterpretSTOREFP(Instr instr);
259 void InterpretFMADD(Instr instr);
260 void InterpretFMSUB(Instr instr);
261 void InterpretFNMADD(Instr instr);
262 void InterpretFNMSUB(Instr instr);
263 void InterpretOPFP(Instr instr);
264 DART_NORETURN void IllegalInstruction(Instr instr);
265 DART_NORETURN void IllegalInstruction(CInstr instr);
266
267 template <typename type>
268 type MemoryRead(uintx_t address, Register base);
269 template <typename type>
270 void MemoryWrite(uintx_t address, type value, Register base);
271
272 intx_t CSRRead(uint16_t csr);
273 void CSRWrite(uint16_t csr, intx_t value);
274 void CSRSet(uint16_t csr, intx_t mask);
275 void CSRClear(uint16_t csr, intx_t mask);
276
277 uintx_t get_xreg(Register rs) const { return xregs_[rs]; }
278 void set_xreg(Register rd, uintx_t value) {
279 if (rd != ZR) {
280 xregs_[rd] = value;
281 }
282 }
283
284 double get_fregd(FRegister rs) const { return fregs_[rs]; }
285 void set_fregd(FRegister rd, double value) { fregs_[rd] = value; }
286
287 static constexpr uint64_t kNaNBox = 0xFFFFFFFF00000000;
288
289 float get_fregs(FRegister rs) const {
290 uint64_t bits64 = bit_cast<uint64_t>(fregs_[rs]);
291 if ((bits64 & kNaNBox) != kNaNBox) {
292 // When the register value isn't a valid NaN, the canonical NaN is used
293 // instead.
294 return bit_cast<float>(0x7fc00000);
295 }
296 uint32_t bits32 = static_cast<uint32_t>(bits64);
297 return bit_cast<float>(bits32);
298 }
299 void set_fregs(FRegister rd, float value) {
300 uint32_t bits32 = bit_cast<uint32_t>(value);
301 uint64_t bits64 = static_cast<uint64_t>(bits32);
302 bits64 |= kNaNBox;
303 fregs_[rd] = bit_cast<double>(bits64);
304 }
305
306 // Known bad pc value to ensure that the simulator does not execute
307 // without being properly setup.
308 static constexpr uword kBadLR = -1;
309 // A pc value used to signal the simulator to stop execution. Generally
310 // the lr is set to this value on transition from native C code to
311 // simulated execution, so that the simulator can "return" to the native
312 // C code.
313 static constexpr uword kEndSimulatingPC = -2;
314
315 // I state.
316 uintx_t pc_;
317 uintx_t xregs_[kNumberOfCpuRegisters];
318 uint64_t instret_; // "Instructions retired" - mandatory counter.
319
320 // A state.
321 uintx_t reserved_address_;
322 uintx_t reserved_value_;
323
324 // F/D state.
325 double fregs_[kNumberOfFpuRegisters];
326 uint32_t fcsr_;
327
328 // Simulator support.
329 char* stack_;
330 uword stack_limit_;
331 uword overflow_stack_limit_;
332 uword stack_base_;
333 Random random_;
334 SimulatorSetjmpBuffer* last_setjmp_buffer_;
335
336 static bool IsIllegalAddress(uword addr) { return addr < 64 * 1024; }
337
338 // Executes RISC-V instructions until the PC reaches kEndSimulatingPC.
339 void Execute();
340 void ExecuteNoTrace();
341 void ExecuteTrace();
342
343 // Returns true if tracing of executed instructions is enabled.
344 bool IsTracingExecution() const;
345
346 // Longjmp support for exceptions.
347 SimulatorSetjmpBuffer* last_setjmp_buffer() { return last_setjmp_buffer_; }
348 void set_last_setjmp_buffer(SimulatorSetjmpBuffer* buffer) {
349 last_setjmp_buffer_ = buffer;
350 }
351
352 friend class SimulatorSetjmpBuffer;
354};
355
356} // namespace dart
357
358#endif // RUNTIME_VM_SIMULATOR_RISCV_H_
GLenum type
void PrintRegisters()
uintx_t get_sp() const
double CallD(intx_t function, double arg0, double arg1=0.0, double arg2=0.0)
double CallD(intx_t function, intx_t arg0, intx_t arg1=0)
double CallD(intx_t function, float arg0)
uintx_t get_lr() const
uintx_t get_register(Register rs) const
uintx_t get_fp() const
float CallF(intx_t function, float arg0, float arg1=0.0f, float arg2=0.0f)
static uword RedirectExternalReference(uword function, CallKind call_kind, int argument_count)
void JumpToFrame(uword pc, uword sp, uword fp, Thread *thread)
friend class SimulatorSetjmpBuffer
float CallF(intx_t function, double arg0)
static Simulator * Current()
uword stack_base() const
uint64_t get_icount() const
intx_t CallI(intx_t function, double arg0, double arg1=0.0)
int64_t Call(intx_t entry, intx_t parameter0, intx_t parameter1, intx_t parameter2, intx_t parameter3, bool fp_return=false, bool fp_args=false)
uintx_t get_pc() const
uword overflow_stack_limit() const
static void Init()
intx_t CallX(intx_t function, intx_t arg0=0, intx_t arg1=0, intx_t arg2=0, intx_t arg3=0)
uword stack_limit() const
static constexpr uword kSimulatorStackUnderflowSize
Definition: simulator_arm.h:43
float CallF(intx_t function, intx_t arg0, intx_t arg1=0)
intx_t CallI(intx_t function, float arg0, float arg1=0.0f)
float CallF(intx_t function, intx_t arg0, float arg1)
double CallD(intx_t function, intx_t arg0, double arg1)
static uword FunctionForRedirect(uword redirect)
uint8_t value
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
const int kNumberOfFpuRegisters
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