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