• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Copyright(c) 2010 - 2017,
6 //     The Regents of the University of California(Regents).All Rights Reserved.
7 //
8 //     Redistribution and use in source and binary forms,
9 //     with or without modification,
10 //     are permitted provided that the following
11 //     conditions are met : 1. Redistributions of source code must retain the
12 //     above copyright notice, this list of conditions and the following
13 //     disclaimer.2. Redistributions in binary form must reproduce the above
14 //     copyright notice, this list of conditions and the following disclaimer in
15 //     the
16 //             documentation and /
17 //         or
18 //         other materials provided with the distribution.3. Neither the name of
19 //         the Regents nor the names of its contributors may be used to endorse
20 //         or
21 //         promote products derived from
22 //         this software without specific prior written permission.
23 //
24 //         IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT,
25 //     INDIRECT, SPECIAL,
26 //     INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
27 //     ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
28 //     EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 //     REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
31 //     INCLUDING, BUT NOT LIMITED TO,
32 //     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
33 //     PARTICULAR PURPOSE.THE SOFTWARE AND ACCOMPANYING DOCUMENTATION,
34 //     IF ANY,
35 //     PROVIDED HEREUNDER IS PROVIDED
36 //     "AS IS".REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
37 //     SUPPORT, UPDATES, ENHANCEMENTS,
38 //     OR MODIFICATIONS.
39 
40 // The original source code covered by the above license above has been
41 // modified significantly by the v8 project authors.
42 
43 // Declares a Simulator for RISC-V instructions if we are not generating a
44 // native RISC-V binary. This Simulator allows us to run and debug RISC-V code
45 // generation on regular desktop machines. V8 calls into generated code via the
46 // GeneratedCode wrapper, which will start execution in the Simulator or
47 // forwards to the real entry on a RISC-V HW platform.
48 
49 #ifndef V8_EXECUTION_RISCV64_SIMULATOR_RISCV64_H_
50 #define V8_EXECUTION_RISCV64_SIMULATOR_RISCV64_H_
51 
52 // globals.h defines USE_SIMULATOR.
53 #include "src/common/globals.h"
54 
55 template <typename T>
Compare(const T & a,const T & b)56 int Compare(const T& a, const T& b) {
57   if (a == b)
58     return 0;
59   else if (a < b)
60     return -1;
61   else
62     return 1;
63 }
64 
65 // Returns the negative absolute value of its argument.
66 template <typename T,
67           typename = typename std::enable_if<std::is_signed<T>::value>::type>
Nabs(T a)68 T Nabs(T a) {
69   return a < 0 ? a : -a;
70 }
71 
72 #if defined(USE_SIMULATOR)
73 // Running with a simulator.
74 
75 #include "src/base/hashmap.h"
76 #include "src/codegen/assembler.h"
77 #include "src/codegen/riscv64/constants-riscv64.h"
78 #include "src/execution/simulator-base.h"
79 #include "src/utils/allocation.h"
80 
81 namespace v8 {
82 namespace internal {
83 
84 // -----------------------------------------------------------------------------
85 // Utility types and functions for RISCV
86 #ifdef V8_TARGET_ARCH_32_BIT
87 using sreg_t = int32_t;
88 using reg_t = uint32_t;
89 #define xlen 32
90 #elif V8_TARGET_ARCH_64_BIT
91 using sreg_t = int64_t;
92 using reg_t = uint64_t;
93 #define xlen 64
94 #else
95 #error "Cannot detect Riscv's bitwidth"
96 #endif
97 
98 #define sext32(x) ((sreg_t)(int32_t)(x))
99 #define zext32(x) ((reg_t)(uint32_t)(x))
100 #define sext_xlen(x) (((sreg_t)(x) << (64 - xlen)) >> (64 - xlen))
101 #define zext_xlen(x) (((reg_t)(x) << (64 - xlen)) >> (64 - xlen))
102 
103 #define BIT(n) (0x1LL << n)
104 #define QUIET_BIT_S(nan) (bit_cast<int32_t>(nan) & BIT(22))
105 #define QUIET_BIT_D(nan) (bit_cast<int64_t>(nan) & BIT(51))
isSnan(float fp)106 static inline bool isSnan(float fp) { return !QUIET_BIT_S(fp); }
isSnan(double fp)107 static inline bool isSnan(double fp) { return !QUIET_BIT_D(fp); }
108 #undef QUIET_BIT_S
109 #undef QUIET_BIT_D
110 
mulhu(uint64_t a,uint64_t b)111 inline uint64_t mulhu(uint64_t a, uint64_t b) {
112   __uint128_t full_result = ((__uint128_t)a) * ((__uint128_t)b);
113   return full_result >> 64;
114 }
115 
mulh(int64_t a,int64_t b)116 inline int64_t mulh(int64_t a, int64_t b) {
117   __int128_t full_result = ((__int128_t)a) * ((__int128_t)b);
118   return full_result >> 64;
119 }
120 
mulhsu(int64_t a,uint64_t b)121 inline int64_t mulhsu(int64_t a, uint64_t b) {
122   __int128_t full_result = ((__int128_t)a) * ((__uint128_t)b);
123   return full_result >> 64;
124 }
125 
126 // Floating point helpers
127 #define F32_SIGN ((uint32_t)1 << 31)
128 union u32_f32 {
129   uint32_t u;
130   float f;
131 };
fsgnj32(float rs1,float rs2,bool n,bool x)132 inline float fsgnj32(float rs1, float rs2, bool n, bool x) {
133   u32_f32 a = {.f = rs1}, b = {.f = rs2};
134   u32_f32 res;
135   res.u = (a.u & ~F32_SIGN) | ((((x)   ? a.u
136                                  : (n) ? F32_SIGN
137                                        : 0) ^
138                                 b.u) &
139                                F32_SIGN);
140   return res.f;
141 }
142 #define F64_SIGN ((uint64_t)1 << 63)
143 union u64_f64 {
144   uint64_t u;
145   double d;
146 };
fsgnj64(double rs1,double rs2,bool n,bool x)147 inline double fsgnj64(double rs1, double rs2, bool n, bool x) {
148   u64_f64 a = {.d = rs1}, b = {.d = rs2};
149   u64_f64 res;
150   res.u = (a.u & ~F64_SIGN) | ((((x)   ? a.u
151                                  : (n) ? F64_SIGN
152                                        : 0) ^
153                                 b.u) &
154                                F64_SIGN);
155   return res.d;
156 }
157 
is_boxed_float(int64_t v)158 inline bool is_boxed_float(int64_t v) { return (uint32_t)((v >> 32) + 1) == 0; }
box_float(float v)159 inline int64_t box_float(float v) {
160   return (0xFFFFFFFF00000000 | bit_cast<int32_t>(v));
161 }
162 
163 // -----------------------------------------------------------------------------
164 // Utility functions
165 
166 class CachePage {
167  public:
168   static const int LINE_VALID = 0;
169   static const int LINE_INVALID = 1;
170 
171   static const int kPageShift = 12;
172   static const int kPageSize = 1 << kPageShift;
173   static const int kPageMask = kPageSize - 1;
174   static const int kLineShift = 2;  // The cache line is only 4 bytes right now.
175   static const int kLineLength = 1 << kLineShift;
176   static const int kLineMask = kLineLength - 1;
177 
CachePage()178   CachePage() { memset(&validity_map_, LINE_INVALID, sizeof(validity_map_)); }
179 
ValidityByte(int offset)180   char* ValidityByte(int offset) {
181     return &validity_map_[offset >> kLineShift];
182   }
183 
CachedData(int offset)184   char* CachedData(int offset) { return &data_[offset]; }
185 
186  private:
187   char data_[kPageSize];  // The cached data.
188   static const int kValidityMapSize = kPageSize >> kLineShift;
189   char validity_map_[kValidityMapSize];  // One byte per line.
190 };
191 
192 class SimInstructionBase : public InstructionBase {
193  public:
InstructionType()194   Type InstructionType() const { return type_; }
instr()195   inline Instruction* instr() const { return instr_; }
operand()196   inline int32_t operand() const { return operand_; }
197 
198  protected:
SimInstructionBase()199   SimInstructionBase() : operand_(-1), instr_(nullptr), type_(kUnsupported) {}
SimInstructionBase(Instruction * instr)200   explicit SimInstructionBase(Instruction* instr) {}
201 
202   int32_t operand_;
203   Instruction* instr_;
204   Type type_;
205 
206  private:
207   DISALLOW_ASSIGN(SimInstructionBase);
208 };
209 
210 class SimInstruction : public InstructionGetters<SimInstructionBase> {
211  public:
SimInstruction()212   SimInstruction() {}
213 
SimInstruction(Instruction * instr)214   explicit SimInstruction(Instruction* instr) { *this = instr; }
215 
216   SimInstruction& operator=(Instruction* instr) {
217     operand_ = *reinterpret_cast<const int32_t*>(instr);
218     instr_ = instr;
219     type_ = InstructionBase::InstructionType();
220     DCHECK(reinterpret_cast<void*>(&operand_) == this);
221     return *this;
222   }
223 };
224 
225 class Simulator : public SimulatorBase {
226  public:
227   friend class RiscvDebugger;
228 
229   // Registers are declared in order. See SMRL chapter 2.
230   enum Register {
231     no_reg = -1,
232     zero_reg = 0,
233     ra,
234     sp,
235     gp,
236     tp,
237     t0,
238     t1,
239     t2,
240     s0,
241     s1,
242     a0,
243     a1,
244     a2,
245     a3,
246     a4,
247     a5,
248     a6,
249     a7,
250     s2,
251     s3,
252     s4,
253     s5,
254     s6,
255     s7,
256     s8,
257     s9,
258     s10,
259     s11,
260     t3,
261     t4,
262     t5,
263     t6,
264     pc,  // pc must be the last register.
265     kNumSimuRegisters,
266     // aliases
267     fp = s0
268   };
269 
270   // Coprocessor registers.
271   // Generated code will always use doubles. So we will only use even registers.
272   enum FPURegister {
273     ft0,
274     ft1,
275     ft2,
276     ft3,
277     ft4,
278     ft5,
279     ft6,
280     ft7,
281     fs0,
282     fs1,
283     fa0,
284     fa1,
285     fa2,
286     fa3,
287     fa4,
288     fa5,
289     fa6,
290     fa7,
291     fs2,
292     fs3,
293     fs4,
294     fs5,
295     fs6,
296     fs7,
297     fs8,
298     fs9,
299     fs10,
300     fs11,
301     ft8,
302     ft9,
303     ft10,
304     ft11,
305     kNumFPURegisters
306   };
307 
308   enum VRegister {
309     v0,
310     v1,
311     v2,
312     v3,
313     v4,
314     v5,
315     v6,
316     v7,
317     v8,
318     v9,
319     v10,
320     v11,
321     v12,
322     v13,
323     v14,
324     v15,
325     v16,
326     v17,
327     v18,
328     v19,
329     v20,
330     v21,
331     v22,
332     v23,
333     v24,
334     v25,
335     v26,
336     v27,
337     v28,
338     v29,
339     v30,
340     v31,
341     kNumVRegisters
342   };
343 
344   explicit Simulator(Isolate* isolate);
345   ~Simulator();
346 
347   // The currently executing Simulator instance. Potentially there can be one
348   // for each native thread.
349   V8_EXPORT_PRIVATE static Simulator* current(v8::internal::Isolate* isolate);
350 
351   // Accessors for register state. Reading the pc value adheres to the RISC-V
352   // architecture specification and is off by a 8 from the currently executing
353   // instruction.
354   void set_register(int reg, int64_t value);
355   void set_register_word(int reg, int32_t value);
356   void set_dw_register(int dreg, const int* dbl);
357   V8_EXPORT_PRIVATE int64_t get_register(int reg) const;
358   double get_double_from_register_pair(int reg);
359 
360   // Same for FPURegisters.
361   void set_fpu_register(int fpureg, int64_t value);
362   void set_fpu_register_word(int fpureg, int32_t value);
363   void set_fpu_register_hi_word(int fpureg, int32_t value);
364   void set_fpu_register_float(int fpureg, float value);
365   void set_fpu_register_double(int fpureg, double value);
366 
367   int64_t get_fpu_register(int fpureg) const;
368   int32_t get_fpu_register_word(int fpureg) const;
369   int32_t get_fpu_register_signed_word(int fpureg) const;
370   int32_t get_fpu_register_hi_word(int fpureg) const;
371   float get_fpu_register_float(int fpureg) const;
372   double get_fpu_register_double(int fpureg) const;
373 
374   // RV CSR manipulation
375   uint32_t read_csr_value(uint32_t csr);
376   void write_csr_value(uint32_t csr, uint64_t value);
377   void set_csr_bits(uint32_t csr, uint64_t flags);
378   void clear_csr_bits(uint32_t csr, uint64_t flags);
379 
set_fflags(uint32_t flags)380   void set_fflags(uint32_t flags) { set_csr_bits(csr_fflags, flags); }
clear_fflags(int32_t flags)381   void clear_fflags(int32_t flags) { clear_csr_bits(csr_fflags, flags); }
382 
383 #ifdef CAN_USE_RVV_INSTRUCTIONS
384   // RVV CSR
385   __int128_t get_vregister(int vreg) const;
rvv_vlen()386   inline uint64_t rvv_vlen() const { return kRvvVLEN; }
rvv_vtype()387   inline uint64_t rvv_vtype() const { return vtype_; }
rvv_vl()388   inline uint64_t rvv_vl() const { return vl_; }
rvv_vstart()389   inline uint64_t rvv_vstart() const { return vstart_; }
rvv_vxsat()390   inline uint64_t rvv_vxsat() const { return vxsat_; }
rvv_vxrm()391   inline uint64_t rvv_vxrm() const { return vxrm_; }
rvv_vcsr()392   inline uint64_t rvv_vcsr() const { return vcsr_; }
rvv_vlenb()393   inline uint64_t rvv_vlenb() const { return vlenb_; }
rvv_zimm()394   inline uint32_t rvv_zimm() const { return instr_.Rvvzimm(); }
rvv_vlmul()395   inline uint32_t rvv_vlmul() const { return (rvv_vtype() & 0x7); }
rvv_vflmul()396   inline float rvv_vflmul() const {
397     if ((rvv_vtype() & 0b100) == 0) {
398       return static_cast<float>(0x1 << (rvv_vtype() & 0x7));
399     } else {
400       return 1.0 / static_cast<float>(0x1 << (4 - rvv_vtype() & 0x3));
401     }
402   }
rvv_vsew()403   inline uint32_t rvv_vsew() const { return ((rvv_vtype() >> 3) & 0x7); }
404 
rvv_sew_s()405   inline const char* rvv_sew_s() const {
406     uint32_t vsew = rvv_vsew();
407     switch (vsew) {
408 #define CAST_VSEW(name) \
409   case name:            \
410     return #name;
411       RVV_SEW(CAST_VSEW)
412       default:
413         return "unknown";
414 #undef CAST_VSEW
415     }
416   }
417 
rvv_lmul_s()418   inline const char* rvv_lmul_s() const {
419     uint32_t vlmul = rvv_vlmul();
420     switch (vlmul) {
421 #define CAST_VLMUL(name) \
422   case name:             \
423     return #name;
424       RVV_LMUL(CAST_VLMUL)
425       default:
426         return "unknown";
427 #undef CAST_VLMUL
428     }
429   }
430 
431   // return size of lane.8 16 32 64
rvv_sew()432   inline uint32_t rvv_sew() const {
433     DCHECK_EQ(rvv_vsew() & (~0x7), 0x0);
434     return (0x1 << rvv_vsew()) * 8;
435   }
rvv_vlmax()436   inline uint64_t rvv_vlmax() const {
437     if ((rvv_vlmul() & 0b100) != 0) {
438       return (rvv_vlen() / rvv_sew()) >> (4 - (rvv_vlmul() & 0b11));
439     } else {
440       return ((rvv_vlen() << rvv_vlmul()) / rvv_sew());
441     }
442   }
443 #endif
444 
445   inline uint32_t get_dynamic_rounding_mode();
446   inline bool test_fflags_bits(uint32_t mask);
447 
448   float RoundF2FHelper(float input_val, int rmode);
449   double RoundF2FHelper(double input_val, int rmode);
450   template <typename I_TYPE, typename F_TYPE>
451   I_TYPE RoundF2IHelper(F_TYPE original, int rmode);
452 
453   template <typename T>
454   T FMaxMinHelper(T a, T b, MaxMinKind kind);
455 
456   template <typename T>
457   bool CompareFHelper(T input1, T input2, FPUCondition cc);
458 
459   // Special case of set_register and get_register to access the raw PC value.
460   void set_pc(int64_t value);
461   V8_EXPORT_PRIVATE int64_t get_pc() const;
462 
get_sp()463   Address get_sp() const { return static_cast<Address>(get_register(sp)); }
464 
465   // Accessor to the internal simulator stack area.
466   uintptr_t StackLimit(uintptr_t c_limit) const;
467 
468   // Executes RISC-V instructions until the PC reaches end_sim_pc.
469   void Execute();
470 
471   template <typename Return, typename... Args>
Call(Address entry,Args...args)472   Return Call(Address entry, Args... args) {
473     return VariadicCall<Return>(this, &Simulator::CallImpl, entry, args...);
474   }
475 
476   // Alternative: call a 2-argument double function.
477   double CallFP(Address entry, double d0, double d1);
478 
479   // Push an address onto the JS stack.
480   uintptr_t PushAddress(uintptr_t address);
481 
482   // Pop an address from the JS stack.
483   uintptr_t PopAddress();
484 
485   // Debugger input.
486   void set_last_debugger_input(char* input);
last_debugger_input()487   char* last_debugger_input() { return last_debugger_input_; }
488 
489   // Redirection support.
490   static void SetRedirectInstruction(Instruction* instruction);
491 
492   // ICache checking.
493   static bool ICacheMatch(void* one, void* two);
494   static void FlushICache(base::CustomMatcherHashMap* i_cache, void* start,
495                           size_t size);
496 
497   // Returns true if pc register contains one of the 'special_values' defined
498   // below (bad_ra, end_sim_pc).
499   bool has_bad_pc() const;
500 
501  private:
502   enum special_values {
503     // Known bad pc value to ensure that the simulator does not execute
504     // without being properly setup.
505     bad_ra = -1,
506     // A pc value used to signal the simulator to stop execution.  Generally
507     // the ra is set to this value on transition from native C code to
508     // simulated execution, so that the simulator can "return" to the native
509     // C code.
510     end_sim_pc = -2,
511     // Unpredictable value.
512     Unpredictable = 0xbadbeaf
513   };
514 
515   V8_EXPORT_PRIVATE intptr_t CallImpl(Address entry, int argument_count,
516                                       const intptr_t* arguments);
517 
518   // Unsupported instructions use Format to print an error and stop execution.
519   void Format(Instruction* instr, const char* format);
520 
521   // Helpers for data value tracing.
522   enum TraceType {
523     BYTE,
524     HALF,
525     WORD,
526     DWORD,
527     FLOAT,
528     DOUBLE,
529     // FLOAT_DOUBLE,
530     // WORD_DWORD
531   };
532 
533   // RISCV Memory read/write methods
534   template <typename T>
535   T ReadMem(int64_t addr, Instruction* instr);
536   template <typename T>
537   void WriteMem(int64_t addr, T value, Instruction* instr);
538   template <typename T, typename OP>
amo(int64_t addr,OP f,Instruction * instr,TraceType t)539   T amo(int64_t addr, OP f, Instruction* instr, TraceType t) {
540     auto lhs = ReadMem<T>(addr, instr);
541     // TODO(RISCV): trace memory read for AMO
542     WriteMem<T>(addr, (T)f(lhs), instr);
543     return lhs;
544   }
545 
546   // Helper for debugging memory access.
547   inline void DieOrDebug();
548 
549   void TraceRegWr(int64_t value, TraceType t = DWORD);
550   void TraceMemWr(int64_t addr, int64_t value, TraceType t);
551   template <typename T>
552   void TraceMemRd(int64_t addr, T value, int64_t reg_value);
553   template <typename T>
554   void TraceMemWr(int64_t addr, T value);
555 
556   SimInstruction instr_;
557 
558   // RISCV utlity API to access register value
rs1_reg()559   inline int32_t rs1_reg() const { return instr_.Rs1Value(); }
rs1()560   inline int64_t rs1() const { return get_register(rs1_reg()); }
frs1()561   inline float frs1() const { return get_fpu_register_float(rs1_reg()); }
drs1()562   inline double drs1() const { return get_fpu_register_double(rs1_reg()); }
rs2_reg()563   inline int32_t rs2_reg() const { return instr_.Rs2Value(); }
rs2()564   inline int64_t rs2() const { return get_register(rs2_reg()); }
frs2()565   inline float frs2() const { return get_fpu_register_float(rs2_reg()); }
drs2()566   inline double drs2() const { return get_fpu_register_double(rs2_reg()); }
rs3_reg()567   inline int32_t rs3_reg() const { return instr_.Rs3Value(); }
rs3()568   inline int64_t rs3() const { return get_register(rs3_reg()); }
frs3()569   inline float frs3() const { return get_fpu_register_float(rs3_reg()); }
drs3()570   inline double drs3() const { return get_fpu_register_double(rs3_reg()); }
rd_reg()571   inline int32_t rd_reg() const { return instr_.RdValue(); }
frd_reg()572   inline int32_t frd_reg() const { return instr_.RdValue(); }
rvc_rs1_reg()573   inline int32_t rvc_rs1_reg() const { return instr_.RvcRs1Value(); }
rvc_rs1()574   inline int64_t rvc_rs1() const { return get_register(rvc_rs1_reg()); }
rvc_rs2_reg()575   inline int32_t rvc_rs2_reg() const { return instr_.RvcRs2Value(); }
rvc_rs2()576   inline int64_t rvc_rs2() const { return get_register(rvc_rs2_reg()); }
rvc_drs2()577   inline double rvc_drs2() const {
578     return get_fpu_register_double(rvc_rs2_reg());
579   }
rvc_rs1s_reg()580   inline int32_t rvc_rs1s_reg() const { return instr_.RvcRs1sValue(); }
rvc_rs1s()581   inline int64_t rvc_rs1s() const { return get_register(rvc_rs1s_reg()); }
rvc_rs2s_reg()582   inline int32_t rvc_rs2s_reg() const { return instr_.RvcRs2sValue(); }
rvc_rs2s()583   inline int64_t rvc_rs2s() const { return get_register(rvc_rs2s_reg()); }
rvc_drs2s()584   inline double rvc_drs2s() const {
585     return get_fpu_register_double(rvc_rs2s_reg());
586   }
rvc_rd_reg()587   inline int32_t rvc_rd_reg() const { return instr_.RvcRdValue(); }
rvc_frd_reg()588   inline int32_t rvc_frd_reg() const { return instr_.RvcRdValue(); }
boffset()589   inline int16_t boffset() const { return instr_.BranchOffset(); }
imm12()590   inline int16_t imm12() const { return instr_.Imm12Value(); }
imm20J()591   inline int32_t imm20J() const { return instr_.Imm20JValue(); }
imm5CSR()592   inline int32_t imm5CSR() const { return instr_.Rs1Value(); }
csr_reg()593   inline int16_t csr_reg() const { return instr_.CsrValue(); }
rvc_imm6()594   inline int16_t rvc_imm6() const { return instr_.RvcImm6Value(); }
rvc_imm6_addi16sp()595   inline int16_t rvc_imm6_addi16sp() const {
596     return instr_.RvcImm6Addi16spValue();
597   }
rvc_imm8_addi4spn()598   inline int16_t rvc_imm8_addi4spn() const {
599     return instr_.RvcImm8Addi4spnValue();
600   }
rvc_imm6_lwsp()601   inline int16_t rvc_imm6_lwsp() const { return instr_.RvcImm6LwspValue(); }
rvc_imm6_ldsp()602   inline int16_t rvc_imm6_ldsp() const { return instr_.RvcImm6LdspValue(); }
rvc_imm6_swsp()603   inline int16_t rvc_imm6_swsp() const { return instr_.RvcImm6SwspValue(); }
rvc_imm6_sdsp()604   inline int16_t rvc_imm6_sdsp() const { return instr_.RvcImm6SdspValue(); }
rvc_imm5_w()605   inline int16_t rvc_imm5_w() const { return instr_.RvcImm5WValue(); }
rvc_imm5_d()606   inline int16_t rvc_imm5_d() const { return instr_.RvcImm5DValue(); }
rvc_imm8_b()607   inline int16_t rvc_imm8_b() const { return instr_.RvcImm8BValue(); }
608 
609   inline void set_rd(int64_t value, bool trace = true) {
610     set_register(rd_reg(), value);
611     if (trace) TraceRegWr(get_register(rd_reg()), DWORD);
612   }
613   inline void set_frd(float value, bool trace = true) {
614     set_fpu_register_float(rd_reg(), value);
615     if (trace) TraceRegWr(get_fpu_register_word(rd_reg()), FLOAT);
616   }
617   inline void set_drd(double value, bool trace = true) {
618     set_fpu_register_double(rd_reg(), value);
619     if (trace) TraceRegWr(get_fpu_register(rd_reg()), DOUBLE);
620   }
621   inline void set_rvc_rd(int64_t value, bool trace = true) {
622     set_register(rvc_rd_reg(), value);
623     if (trace) TraceRegWr(get_register(rvc_rd_reg()), DWORD);
624   }
625   inline void set_rvc_rs1s(int64_t value, bool trace = true) {
626     set_register(rvc_rs1s_reg(), value);
627     if (trace) TraceRegWr(get_register(rvc_rs1s_reg()), DWORD);
628   }
629   inline void set_rvc_rs2(int64_t value, bool trace = true) {
630     set_register(rvc_rs2_reg(), value);
631     if (trace) TraceRegWr(get_register(rvc_rs2_reg()), DWORD);
632   }
633   inline void set_rvc_drd(double value, bool trace = true) {
634     set_fpu_register_double(rvc_rd_reg(), value);
635     if (trace) TraceRegWr(get_fpu_register(rvc_rd_reg()), DOUBLE);
636   }
637   inline void set_rvc_rs2s(int64_t value, bool trace = true) {
638     set_register(rvc_rs2s_reg(), value);
639     if (trace) TraceRegWr(get_register(rvc_rs2s_reg()), DWORD);
640   }
641   inline void set_rvc_drs2s(double value, bool trace = true) {
642     set_fpu_register_double(rvc_rs2s_reg(), value);
643     if (trace) TraceRegWr(get_fpu_register(rvc_rs2s_reg()), DOUBLE);
644   }
shamt6()645   inline int16_t shamt6() const { return (imm12() & 0x3F); }
shamt5()646   inline int16_t shamt5() const { return (imm12() & 0x1F); }
rvc_shamt6()647   inline int16_t rvc_shamt6() const { return instr_.RvcShamt6(); }
s_imm12()648   inline int32_t s_imm12() const { return instr_.StoreOffset(); }
u_imm20()649   inline int32_t u_imm20() const { return instr_.Imm20UValue() << 12; }
rvc_u_imm6()650   inline int32_t rvc_u_imm6() const { return instr_.RvcImm6Value() << 12; }
require(bool check)651   inline void require(bool check) {
652     if (!check) {
653       SignalException(kIllegalInstruction);
654     }
655   }
656 
657 #ifdef CAN_USE_RVV_INSTRUCTIONS
rvv_trace_vd()658   inline void rvv_trace_vd() {
659     if (::v8::internal::FLAG_trace_sim) {
660       __int128_t value = Vregister_[rvv_vd_reg()];
661       SNPrintF(trace_buf_, "%016" PRIx64 "%016" PRIx64 " (%" PRId64 ")",
662                *(reinterpret_cast<int64_t*>(&value) + 1),
663                *reinterpret_cast<int64_t*>(&value), icount_);
664     }
665   }
666 
rvv_trace_vs1()667   inline void rvv_trace_vs1() {
668     if (::v8::internal::FLAG_trace_sim) {
669       PrintF("\t%s:0x%016" PRIx64 "%016" PRIx64 "\n",
670              v8::internal::VRegisters::Name(static_cast<int>(rvv_vs1_reg())),
671              (uint64_t)(get_vregister(static_cast<int>(rvv_vs1_reg())) >> 64),
672              (uint64_t)get_vregister(static_cast<int>(rvv_vs1_reg())));
673     }
674   }
675 
rvv_trace_vs2()676   inline void rvv_trace_vs2() {
677     if (::v8::internal::FLAG_trace_sim) {
678       PrintF("\t%s:0x%016" PRIx64 "%016" PRIx64 "\n",
679              v8::internal::VRegisters::Name(static_cast<int>(rvv_vs2_reg())),
680              (uint64_t)(get_vregister(static_cast<int>(rvv_vs2_reg())) >> 64),
681              (uint64_t)get_vregister(static_cast<int>(rvv_vs2_reg())));
682     }
683   }
rvv_trace_v0()684   inline void rvv_trace_v0() {
685     if (::v8::internal::FLAG_trace_sim) {
686       PrintF("\t%s:0x%016" PRIx64 "%016" PRIx64 "\n",
687              v8::internal::VRegisters::Name(v0),
688              (uint64_t)(get_vregister(v0) >> 64), (uint64_t)get_vregister(v0));
689     }
690   }
691 
rvv_trace_rs1()692   inline void rvv_trace_rs1() {
693     if (::v8::internal::FLAG_trace_sim) {
694       PrintF("\t%s:0x%016" PRIx64 "\n",
695              v8::internal::Registers::Name(static_cast<int>(rs1_reg())),
696              (uint64_t)(get_register(rs1_reg())));
697     }
698   }
699 
rvv_trace_status()700   inline void rvv_trace_status() {
701     if (::v8::internal::FLAG_trace_sim) {
702       int i = 0;
703       for (; i < trace_buf_.length(); i++) {
704         if (trace_buf_[i] == '\0') break;
705       }
706       SNPrintF(trace_buf_.SubVector(i, trace_buf_.length()),
707                "  sew:%s lmul:%s vstart:%lu vl:%lu", rvv_sew_s(), rvv_lmul_s(),
708                rvv_vstart(), rvv_vl());
709     }
710   }
711 
712   template <class T>
713   T& Rvvelt(reg_t vReg, uint64_t n, bool is_write = false) {
714     CHECK_NE(rvv_sew(), 0);
715     CHECK_GT((rvv_vlen() >> 3) / sizeof(T), 0);
716     reg_t elts_per_reg = (rvv_vlen() >> 3) / (sizeof(T));
717     vReg += n / elts_per_reg;
718     n = n % elts_per_reg;
719     T* regStart = reinterpret_cast<T*>(reinterpret_cast<char*>(Vregister_) +
720                                        vReg * (rvv_vlen() >> 3));
721     return regStart[n];
722   }
723 
rvv_vs1_reg()724   inline int32_t rvv_vs1_reg() { return instr_.Vs1Value(); }
rvv_vs1()725   inline reg_t rvv_vs1() { UNIMPLEMENTED(); }
rvv_vs2_reg()726   inline int32_t rvv_vs2_reg() { return instr_.Vs2Value(); }
rvv_vs2()727   inline reg_t rvv_vs2() { UNIMPLEMENTED(); }
rvv_vd_reg()728   inline int32_t rvv_vd_reg() { return instr_.VdValue(); }
rvv_vs3_reg()729   inline int32_t rvv_vs3_reg() { return instr_.VdValue(); }
rvv_vd()730   inline reg_t rvv_vd() { UNIMPLEMENTED(); }
rvv_nf()731   inline int32_t rvv_nf() {
732     return (instr_.InstructionBits() & kRvvNfMask) >> kRvvNfShift;
733   }
734 
set_vrd()735   inline void set_vrd() { UNIMPLEMENTED(); }
736 
737   inline void set_rvv_vtype(uint64_t value, bool trace = true) {
738     vtype_ = value;
739   }
740   inline void set_rvv_vl(uint64_t value, bool trace = true) { vl_ = value; }
741   inline void set_rvv_vstart(uint64_t value, bool trace = true) {
742     vstart_ = value;
743   }
744   inline void set_rvv_vxsat(uint64_t value, bool trace = true) {
745     vxsat_ = value;
746   }
747   inline void set_rvv_vxrm(uint64_t value, bool trace = true) { vxrm_ = value; }
748   inline void set_rvv_vcsr(uint64_t value, bool trace = true) { vcsr_ = value; }
749   inline void set_rvv_vlenb(uint64_t value, bool trace = true) {
750     vlenb_ = value;
751   }
752 #endif
753 
754   template <typename T, typename Func>
CanonicalizeFPUOpFMA(Func fn,T dst,T src1,T src2)755   inline T CanonicalizeFPUOpFMA(Func fn, T dst, T src1, T src2) {
756     STATIC_ASSERT(std::is_floating_point<T>::value);
757     auto alu_out = fn(dst, src1, src2);
758     // if any input or result is NaN, the result is quiet_NaN
759     if (std::isnan(alu_out) || std::isnan(src1) || std::isnan(src2) ||
760         std::isnan(dst)) {
761       // signaling_nan sets kInvalidOperation bit
762       if (isSnan(alu_out) || isSnan(src1) || isSnan(src2) || isSnan(dst))
763         set_fflags(kInvalidOperation);
764       alu_out = std::numeric_limits<T>::quiet_NaN();
765     }
766     return alu_out;
767   }
768 
769   template <typename T, typename Func>
CanonicalizeFPUOp3(Func fn)770   inline T CanonicalizeFPUOp3(Func fn) {
771     STATIC_ASSERT(std::is_floating_point<T>::value);
772     T src1 = std::is_same<float, T>::value ? frs1() : drs1();
773     T src2 = std::is_same<float, T>::value ? frs2() : drs2();
774     T src3 = std::is_same<float, T>::value ? frs3() : drs3();
775     auto alu_out = fn(src1, src2, src3);
776     // if any input or result is NaN, the result is quiet_NaN
777     if (std::isnan(alu_out) || std::isnan(src1) || std::isnan(src2) ||
778         std::isnan(src3)) {
779       // signaling_nan sets kInvalidOperation bit
780       if (isSnan(alu_out) || isSnan(src1) || isSnan(src2) || isSnan(src3))
781         set_fflags(kInvalidOperation);
782       alu_out = std::numeric_limits<T>::quiet_NaN();
783     }
784     return alu_out;
785   }
786 
787   template <typename T, typename Func>
CanonicalizeFPUOp2(Func fn)788   inline T CanonicalizeFPUOp2(Func fn) {
789     STATIC_ASSERT(std::is_floating_point<T>::value);
790     T src1 = std::is_same<float, T>::value ? frs1() : drs1();
791     T src2 = std::is_same<float, T>::value ? frs2() : drs2();
792     auto alu_out = fn(src1, src2);
793     // if any input or result is NaN, the result is quiet_NaN
794     if (std::isnan(alu_out) || std::isnan(src1) || std::isnan(src2)) {
795       // signaling_nan sets kInvalidOperation bit
796       if (isSnan(alu_out) || isSnan(src1) || isSnan(src2))
797         set_fflags(kInvalidOperation);
798       alu_out = std::numeric_limits<T>::quiet_NaN();
799     }
800     return alu_out;
801   }
802 
803   template <typename T, typename Func>
CanonicalizeFPUOp1(Func fn)804   inline T CanonicalizeFPUOp1(Func fn) {
805     STATIC_ASSERT(std::is_floating_point<T>::value);
806     T src1 = std::is_same<float, T>::value ? frs1() : drs1();
807     auto alu_out = fn(src1);
808     // if any input or result is NaN, the result is quiet_NaN
809     if (std::isnan(alu_out) || std::isnan(src1)) {
810       // signaling_nan sets kInvalidOperation bit
811       if (isSnan(alu_out) || isSnan(src1)) set_fflags(kInvalidOperation);
812       alu_out = std::numeric_limits<T>::quiet_NaN();
813     }
814     return alu_out;
815   }
816 
817   template <typename Func>
CanonicalizeDoubleToFloatOperation(Func fn)818   inline float CanonicalizeDoubleToFloatOperation(Func fn) {
819     float alu_out = fn(drs1());
820     if (std::isnan(alu_out) || std::isnan(drs1()))
821       alu_out = std::numeric_limits<float>::quiet_NaN();
822     return alu_out;
823   }
824 
825   template <typename Func>
CanonicalizeDoubleToFloatOperation(Func fn,double frs)826   inline float CanonicalizeDoubleToFloatOperation(Func fn, double frs) {
827     float alu_out = fn(frs);
828     if (std::isnan(alu_out) || std::isnan(drs1()))
829       alu_out = std::numeric_limits<float>::quiet_NaN();
830     return alu_out;
831   }
832 
833   template <typename Func>
CanonicalizeFloatToDoubleOperation(Func fn,float frs)834   inline float CanonicalizeFloatToDoubleOperation(Func fn, float frs) {
835     double alu_out = fn(frs);
836     if (std::isnan(alu_out) || std::isnan(frs1()))
837       alu_out = std::numeric_limits<double>::quiet_NaN();
838     return alu_out;
839   }
840 
841   template <typename Func>
CanonicalizeFloatToDoubleOperation(Func fn)842   inline float CanonicalizeFloatToDoubleOperation(Func fn) {
843     double alu_out = fn(frs1());
844     if (std::isnan(alu_out) || std::isnan(frs1()))
845       alu_out = std::numeric_limits<double>::quiet_NaN();
846     return alu_out;
847   }
848 
849   Builtin LookUp(Address pc);
850   // RISCV decoding routine
851   void DecodeRVRType();
852   void DecodeRVR4Type();
853   void DecodeRVRFPType();  // Special routine for R/OP_FP type
854   void DecodeRVRAType();   // Special routine for R/AMO type
855   void DecodeRVIType();
856   void DecodeRVSType();
857   void DecodeRVBType();
858   void DecodeRVUType();
859   void DecodeRVJType();
860   void DecodeCRType();
861   void DecodeCAType();
862   void DecodeCIType();
863   void DecodeCIWType();
864   void DecodeCSSType();
865   void DecodeCLType();
866   void DecodeCSType();
867   void DecodeCJType();
868   void DecodeCBType();
869 #ifdef CAN_USE_RVV_INSTRUCTIONS
870   void DecodeVType();
871   void DecodeRvvIVV();
872   void DecodeRvvIVI();
873   void DecodeRvvIVX();
874   void DecodeRvvMVV();
875   void DecodeRvvMVX();
876   void DecodeRvvFVV();
877   void DecodeRvvFVF();
878   bool DecodeRvvVL();
879   bool DecodeRvvVS();
880 #endif
881 
882   // Used for breakpoints and traps.
883   void SoftwareInterrupt();
884 
885   // Debug helpers
886 
887   // Simulator breakpoints.
888   struct Breakpoint {
889     Instruction* location;
890     bool enabled;
891     bool is_tbreak;
892   };
893   std::vector<Breakpoint> breakpoints_;
894   void SetBreakpoint(Instruction* breakpoint, bool is_tbreak);
895   void ListBreakpoints();
896   void CheckBreakpoints();
897 
898   // Stop helper functions.
899   bool IsWatchpoint(uint64_t code);
900   void PrintWatchpoint(uint64_t code);
901   void HandleStop(uint64_t code);
902   bool IsStopInstruction(Instruction* instr);
903   bool IsEnabledStop(uint64_t code);
904   void EnableStop(uint64_t code);
905   void DisableStop(uint64_t code);
906   void IncreaseStopCounter(uint64_t code);
907   void PrintStopInfo(uint64_t code);
908 
909   // Executes one instruction.
910   void InstructionDecode(Instruction* instr);
911 
912   // ICache.
913   static void CheckICache(base::CustomMatcherHashMap* i_cache,
914                           Instruction* instr);
915   static void FlushOnePage(base::CustomMatcherHashMap* i_cache, intptr_t start,
916                            size_t size);
917   static CachePage* GetCachePage(base::CustomMatcherHashMap* i_cache,
918                                  void* page);
919 
920   enum Exception {
921     none,
922     kIntegerOverflow,
923     kIntegerUnderflow,
924     kDivideByZero,
925     kNumExceptions,
926     // RISCV illegual instruction exception
927     kIllegalInstruction,
928   };
929 
930   // Exceptions.
931   void SignalException(Exception e);
932 
933   // Handle arguments and return value for runtime FP functions.
934   void GetFpArgs(double* x, double* y, int32_t* z);
935   void SetFpResult(const double& result);
936 
937   void CallInternal(Address entry);
938 
939   // Architecture state.
940   // Registers.
941   int64_t registers_[kNumSimuRegisters];
942   // Coprocessor Registers.
943   int64_t FPUregisters_[kNumFPURegisters];
944   // Floating-point control and status register.
945   uint32_t FCSR_;
946 
947 #ifdef CAN_USE_RVV_INSTRUCTIONS
948   // RVV registers
949   __int128_t Vregister_[kNumVRegisters];
950   static_assert(sizeof(__int128_t) == kRvvVLEN / 8, "unmatch vlen");
951   uint64_t vstart_, vxsat_, vxrm_, vcsr_, vtype_, vl_, vlenb_;
952 #endif
953   // Simulator support.
954   // Allocate 1MB for stack.
955   size_t stack_size_;
956   char* stack_;
957   bool pc_modified_;
958   int64_t icount_;
959   int break_count_;
960   base::EmbeddedVector<char, 256> trace_buf_;
961 
962   // Debugger input.
963   char* last_debugger_input_;
964 
965   v8::internal::Isolate* isolate_;
966   v8::internal::Builtins builtins_;
967 
968   // Stop is disabled if bit 31 is set.
969   static const uint32_t kStopDisabledBit = 1 << 31;
970 
971   // A stop is enabled, meaning the simulator will stop when meeting the
972   // instruction, if bit 31 of watched_stops_[code].count is unset.
973   // The value watched_stops_[code].count & ~(1 << 31) indicates how many times
974   // the breakpoint was hit or gone through.
975   struct StopCountAndDesc {
976     uint32_t count;
977     char* desc;
978   };
979   StopCountAndDesc watched_stops_[kMaxStopCode + 1];
980 
981   // Synchronization primitives.
982   enum class MonitorAccess {
983     Open,
984     RMW,
985   };
986 
987   enum class TransactionSize {
988     None = 0,
989     Word = 4,
990     DoubleWord = 8,
991   };
992 
993   // The least-significant bits of the address are ignored. The number of bits
994   // is implementation-defined, between 3 and minimum page size.
995   static const uintptr_t kExclusiveTaggedAddrMask = ~((1 << 3) - 1);
996 
997   class LocalMonitor {
998    public:
999     LocalMonitor();
1000 
1001     // These functions manage the state machine for the local monitor, but do
1002     // not actually perform loads and stores. NotifyStoreConditional only
1003     // returns true if the store conditional is allowed; the global monitor will
1004     // still have to be checked to see whether the memory should be updated.
1005     void NotifyLoad();
1006     void NotifyLoadLinked(uintptr_t addr, TransactionSize size);
1007     void NotifyStore();
1008     bool NotifyStoreConditional(uintptr_t addr, TransactionSize size);
1009 
1010    private:
1011     void Clear();
1012 
1013     MonitorAccess access_state_;
1014     uintptr_t tagged_addr_;
1015     TransactionSize size_;
1016   };
1017 
1018   class GlobalMonitor {
1019    public:
1020     class LinkedAddress {
1021      public:
1022       LinkedAddress();
1023 
1024      private:
1025       friend class GlobalMonitor;
1026       // These functions manage the state machine for the global monitor, but do
1027       // not actually perform loads and stores.
1028       void Clear_Locked();
1029       void NotifyLoadLinked_Locked(uintptr_t addr);
1030       void NotifyStore_Locked();
1031       bool NotifyStoreConditional_Locked(uintptr_t addr,
1032                                          bool is_requesting_thread);
1033 
1034       MonitorAccess access_state_;
1035       uintptr_t tagged_addr_;
1036       LinkedAddress* next_;
1037       LinkedAddress* prev_;
1038       // A scd can fail due to background cache evictions. Rather than
1039       // simulating this, we'll just occasionally introduce cases where an
1040       // store conditional fails. This will happen once after every
1041       // kMaxFailureCounter exclusive stores.
1042       static const int kMaxFailureCounter = 5;
1043       int failure_counter_;
1044     };
1045 
1046     // Exposed so it can be accessed by Simulator::{Read,Write}Ex*.
1047     base::Mutex mutex;
1048 
1049     void NotifyLoadLinked_Locked(uintptr_t addr, LinkedAddress* linked_address);
1050     void NotifyStore_Locked(LinkedAddress* linked_address);
1051     bool NotifyStoreConditional_Locked(uintptr_t addr,
1052                                        LinkedAddress* linked_address);
1053 
1054     // Called when the simulator is destroyed.
1055     void RemoveLinkedAddress(LinkedAddress* linked_address);
1056 
1057     static GlobalMonitor* Get();
1058 
1059    private:
1060     // Private constructor. Call {GlobalMonitor::Get()} to get the singleton.
1061     GlobalMonitor() = default;
1062     friend class base::LeakyObject<GlobalMonitor>;
1063 
1064     bool IsProcessorInLinkedList_Locked(LinkedAddress* linked_address) const;
1065     void PrependProcessor_Locked(LinkedAddress* linked_address);
1066 
1067     LinkedAddress* head_ = nullptr;
1068   };
1069 
1070   LocalMonitor local_monitor_;
1071   GlobalMonitor::LinkedAddress global_monitor_thread_;
1072 };
1073 }  // namespace internal
1074 }  // namespace v8
1075 
1076 #endif  // defined(USE_SIMULATOR)
1077 #endif  // V8_EXECUTION_RISCV64_SIMULATOR_RISCV64_H_
1078