11cb0ef41Sopenharmony_ci// Copyright 2021 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci// Copyright(c) 2010 - 2017,
61cb0ef41Sopenharmony_ci//     The Regents of the University of California(Regents).All Rights Reserved.
71cb0ef41Sopenharmony_ci//
81cb0ef41Sopenharmony_ci//     Redistribution and use in source and binary forms,
91cb0ef41Sopenharmony_ci//     with or without modification,
101cb0ef41Sopenharmony_ci//     are permitted provided that the following
111cb0ef41Sopenharmony_ci//     conditions are met : 1. Redistributions of source code must retain the
121cb0ef41Sopenharmony_ci//     above copyright notice, this list of conditions and the following
131cb0ef41Sopenharmony_ci//     disclaimer.2. Redistributions in binary form must reproduce the above
141cb0ef41Sopenharmony_ci//     copyright notice, this list of conditions and the following disclaimer in
151cb0ef41Sopenharmony_ci//     the
161cb0ef41Sopenharmony_ci//             documentation and /
171cb0ef41Sopenharmony_ci//         or
181cb0ef41Sopenharmony_ci//         other materials provided with the distribution.3. Neither the name of
191cb0ef41Sopenharmony_ci//         the Regents nor the names of its contributors may be used to endorse
201cb0ef41Sopenharmony_ci//         or
211cb0ef41Sopenharmony_ci//         promote products derived from
221cb0ef41Sopenharmony_ci//         this software without specific prior written permission.
231cb0ef41Sopenharmony_ci//
241cb0ef41Sopenharmony_ci//         IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT,
251cb0ef41Sopenharmony_ci//     INDIRECT, SPECIAL,
261cb0ef41Sopenharmony_ci//     INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
271cb0ef41Sopenharmony_ci//     ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
281cb0ef41Sopenharmony_ci//     EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
291cb0ef41Sopenharmony_ci//
301cb0ef41Sopenharmony_ci//     REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
311cb0ef41Sopenharmony_ci//     INCLUDING, BUT NOT LIMITED TO,
321cb0ef41Sopenharmony_ci//     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
331cb0ef41Sopenharmony_ci//     PARTICULAR PURPOSE.THE SOFTWARE AND ACCOMPANYING DOCUMENTATION,
341cb0ef41Sopenharmony_ci//     IF ANY,
351cb0ef41Sopenharmony_ci//     PROVIDED HEREUNDER IS PROVIDED
361cb0ef41Sopenharmony_ci//     "AS IS".REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
371cb0ef41Sopenharmony_ci//     SUPPORT, UPDATES, ENHANCEMENTS,
381cb0ef41Sopenharmony_ci//     OR MODIFICATIONS.
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci// The original source code covered by the above license above has been
411cb0ef41Sopenharmony_ci// modified significantly by the v8 project authors.
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci// Declares a Simulator for RISC-V instructions if we are not generating a
441cb0ef41Sopenharmony_ci// native RISC-V binary. This Simulator allows us to run and debug RISC-V code
451cb0ef41Sopenharmony_ci// generation on regular desktop machines. V8 calls into generated code via the
461cb0ef41Sopenharmony_ci// GeneratedCode wrapper, which will start execution in the Simulator or
471cb0ef41Sopenharmony_ci// forwards to the real entry on a RISC-V HW platform.
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci#ifndef V8_EXECUTION_RISCV64_SIMULATOR_RISCV64_H_
501cb0ef41Sopenharmony_ci#define V8_EXECUTION_RISCV64_SIMULATOR_RISCV64_H_
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci// globals.h defines USE_SIMULATOR.
531cb0ef41Sopenharmony_ci#include "src/common/globals.h"
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_citemplate <typename T>
561cb0ef41Sopenharmony_ciint Compare(const T& a, const T& b) {
571cb0ef41Sopenharmony_ci  if (a == b)
581cb0ef41Sopenharmony_ci    return 0;
591cb0ef41Sopenharmony_ci  else if (a < b)
601cb0ef41Sopenharmony_ci    return -1;
611cb0ef41Sopenharmony_ci  else
621cb0ef41Sopenharmony_ci    return 1;
631cb0ef41Sopenharmony_ci}
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci// Returns the negative absolute value of its argument.
661cb0ef41Sopenharmony_citemplate <typename T,
671cb0ef41Sopenharmony_ci          typename = typename std::enable_if<std::is_signed<T>::value>::type>
681cb0ef41Sopenharmony_ciT Nabs(T a) {
691cb0ef41Sopenharmony_ci  return a < 0 ? a : -a;
701cb0ef41Sopenharmony_ci}
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci#if defined(USE_SIMULATOR)
731cb0ef41Sopenharmony_ci// Running with a simulator.
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci#include "src/base/hashmap.h"
761cb0ef41Sopenharmony_ci#include "src/codegen/assembler.h"
771cb0ef41Sopenharmony_ci#include "src/codegen/riscv64/constants-riscv64.h"
781cb0ef41Sopenharmony_ci#include "src/execution/simulator-base.h"
791cb0ef41Sopenharmony_ci#include "src/utils/allocation.h"
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_cinamespace v8 {
821cb0ef41Sopenharmony_cinamespace internal {
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci// -----------------------------------------------------------------------------
851cb0ef41Sopenharmony_ci// Utility types and functions for RISCV
861cb0ef41Sopenharmony_ci#ifdef V8_TARGET_ARCH_32_BIT
871cb0ef41Sopenharmony_ciusing sreg_t = int32_t;
881cb0ef41Sopenharmony_ciusing reg_t = uint32_t;
891cb0ef41Sopenharmony_ci#define xlen 32
901cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_64_BIT
911cb0ef41Sopenharmony_ciusing sreg_t = int64_t;
921cb0ef41Sopenharmony_ciusing reg_t = uint64_t;
931cb0ef41Sopenharmony_ci#define xlen 64
941cb0ef41Sopenharmony_ci#else
951cb0ef41Sopenharmony_ci#error "Cannot detect Riscv's bitwidth"
961cb0ef41Sopenharmony_ci#endif
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci#define sext32(x) ((sreg_t)(int32_t)(x))
991cb0ef41Sopenharmony_ci#define zext32(x) ((reg_t)(uint32_t)(x))
1001cb0ef41Sopenharmony_ci#define sext_xlen(x) (((sreg_t)(x) << (64 - xlen)) >> (64 - xlen))
1011cb0ef41Sopenharmony_ci#define zext_xlen(x) (((reg_t)(x) << (64 - xlen)) >> (64 - xlen))
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci#define BIT(n) (0x1LL << n)
1041cb0ef41Sopenharmony_ci#define QUIET_BIT_S(nan) (bit_cast<int32_t>(nan) & BIT(22))
1051cb0ef41Sopenharmony_ci#define QUIET_BIT_D(nan) (bit_cast<int64_t>(nan) & BIT(51))
1061cb0ef41Sopenharmony_cistatic inline bool isSnan(float fp) { return !QUIET_BIT_S(fp); }
1071cb0ef41Sopenharmony_cistatic inline bool isSnan(double fp) { return !QUIET_BIT_D(fp); }
1081cb0ef41Sopenharmony_ci#undef QUIET_BIT_S
1091cb0ef41Sopenharmony_ci#undef QUIET_BIT_D
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ciinline uint64_t mulhu(uint64_t a, uint64_t b) {
1121cb0ef41Sopenharmony_ci  __uint128_t full_result = ((__uint128_t)a) * ((__uint128_t)b);
1131cb0ef41Sopenharmony_ci  return full_result >> 64;
1141cb0ef41Sopenharmony_ci}
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ciinline int64_t mulh(int64_t a, int64_t b) {
1171cb0ef41Sopenharmony_ci  __int128_t full_result = ((__int128_t)a) * ((__int128_t)b);
1181cb0ef41Sopenharmony_ci  return full_result >> 64;
1191cb0ef41Sopenharmony_ci}
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ciinline int64_t mulhsu(int64_t a, uint64_t b) {
1221cb0ef41Sopenharmony_ci  __int128_t full_result = ((__int128_t)a) * ((__uint128_t)b);
1231cb0ef41Sopenharmony_ci  return full_result >> 64;
1241cb0ef41Sopenharmony_ci}
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ci// Floating point helpers
1271cb0ef41Sopenharmony_ci#define F32_SIGN ((uint32_t)1 << 31)
1281cb0ef41Sopenharmony_ciunion u32_f32 {
1291cb0ef41Sopenharmony_ci  uint32_t u;
1301cb0ef41Sopenharmony_ci  float f;
1311cb0ef41Sopenharmony_ci};
1321cb0ef41Sopenharmony_ciinline float fsgnj32(float rs1, float rs2, bool n, bool x) {
1331cb0ef41Sopenharmony_ci  u32_f32 a = {.f = rs1}, b = {.f = rs2};
1341cb0ef41Sopenharmony_ci  u32_f32 res;
1351cb0ef41Sopenharmony_ci  res.u = (a.u & ~F32_SIGN) | ((((x)   ? a.u
1361cb0ef41Sopenharmony_ci                                 : (n) ? F32_SIGN
1371cb0ef41Sopenharmony_ci                                       : 0) ^
1381cb0ef41Sopenharmony_ci                                b.u) &
1391cb0ef41Sopenharmony_ci                               F32_SIGN);
1401cb0ef41Sopenharmony_ci  return res.f;
1411cb0ef41Sopenharmony_ci}
1421cb0ef41Sopenharmony_ci#define F64_SIGN ((uint64_t)1 << 63)
1431cb0ef41Sopenharmony_ciunion u64_f64 {
1441cb0ef41Sopenharmony_ci  uint64_t u;
1451cb0ef41Sopenharmony_ci  double d;
1461cb0ef41Sopenharmony_ci};
1471cb0ef41Sopenharmony_ciinline double fsgnj64(double rs1, double rs2, bool n, bool x) {
1481cb0ef41Sopenharmony_ci  u64_f64 a = {.d = rs1}, b = {.d = rs2};
1491cb0ef41Sopenharmony_ci  u64_f64 res;
1501cb0ef41Sopenharmony_ci  res.u = (a.u & ~F64_SIGN) | ((((x)   ? a.u
1511cb0ef41Sopenharmony_ci                                 : (n) ? F64_SIGN
1521cb0ef41Sopenharmony_ci                                       : 0) ^
1531cb0ef41Sopenharmony_ci                                b.u) &
1541cb0ef41Sopenharmony_ci                               F64_SIGN);
1551cb0ef41Sopenharmony_ci  return res.d;
1561cb0ef41Sopenharmony_ci}
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ciinline bool is_boxed_float(int64_t v) { return (uint32_t)((v >> 32) + 1) == 0; }
1591cb0ef41Sopenharmony_ciinline int64_t box_float(float v) {
1601cb0ef41Sopenharmony_ci  return (0xFFFFFFFF00000000 | bit_cast<int32_t>(v));
1611cb0ef41Sopenharmony_ci}
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci// -----------------------------------------------------------------------------
1641cb0ef41Sopenharmony_ci// Utility functions
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ciclass CachePage {
1671cb0ef41Sopenharmony_ci public:
1681cb0ef41Sopenharmony_ci  static const int LINE_VALID = 0;
1691cb0ef41Sopenharmony_ci  static const int LINE_INVALID = 1;
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci  static const int kPageShift = 12;
1721cb0ef41Sopenharmony_ci  static const int kPageSize = 1 << kPageShift;
1731cb0ef41Sopenharmony_ci  static const int kPageMask = kPageSize - 1;
1741cb0ef41Sopenharmony_ci  static const int kLineShift = 2;  // The cache line is only 4 bytes right now.
1751cb0ef41Sopenharmony_ci  static const int kLineLength = 1 << kLineShift;
1761cb0ef41Sopenharmony_ci  static const int kLineMask = kLineLength - 1;
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci  CachePage() { memset(&validity_map_, LINE_INVALID, sizeof(validity_map_)); }
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  char* ValidityByte(int offset) {
1811cb0ef41Sopenharmony_ci    return &validity_map_[offset >> kLineShift];
1821cb0ef41Sopenharmony_ci  }
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci  char* CachedData(int offset) { return &data_[offset]; }
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci private:
1871cb0ef41Sopenharmony_ci  char data_[kPageSize];  // The cached data.
1881cb0ef41Sopenharmony_ci  static const int kValidityMapSize = kPageSize >> kLineShift;
1891cb0ef41Sopenharmony_ci  char validity_map_[kValidityMapSize];  // One byte per line.
1901cb0ef41Sopenharmony_ci};
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ciclass SimInstructionBase : public InstructionBase {
1931cb0ef41Sopenharmony_ci public:
1941cb0ef41Sopenharmony_ci  Type InstructionType() const { return type_; }
1951cb0ef41Sopenharmony_ci  inline Instruction* instr() const { return instr_; }
1961cb0ef41Sopenharmony_ci  inline int32_t operand() const { return operand_; }
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci protected:
1991cb0ef41Sopenharmony_ci  SimInstructionBase() : operand_(-1), instr_(nullptr), type_(kUnsupported) {}
2001cb0ef41Sopenharmony_ci  explicit SimInstructionBase(Instruction* instr) {}
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci  int32_t operand_;
2031cb0ef41Sopenharmony_ci  Instruction* instr_;
2041cb0ef41Sopenharmony_ci  Type type_;
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci private:
2071cb0ef41Sopenharmony_ci  DISALLOW_ASSIGN(SimInstructionBase);
2081cb0ef41Sopenharmony_ci};
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_ciclass SimInstruction : public InstructionGetters<SimInstructionBase> {
2111cb0ef41Sopenharmony_ci public:
2121cb0ef41Sopenharmony_ci  SimInstruction() {}
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci  explicit SimInstruction(Instruction* instr) { *this = instr; }
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci  SimInstruction& operator=(Instruction* instr) {
2171cb0ef41Sopenharmony_ci    operand_ = *reinterpret_cast<const int32_t*>(instr);
2181cb0ef41Sopenharmony_ci    instr_ = instr;
2191cb0ef41Sopenharmony_ci    type_ = InstructionBase::InstructionType();
2201cb0ef41Sopenharmony_ci    DCHECK(reinterpret_cast<void*>(&operand_) == this);
2211cb0ef41Sopenharmony_ci    return *this;
2221cb0ef41Sopenharmony_ci  }
2231cb0ef41Sopenharmony_ci};
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ciclass Simulator : public SimulatorBase {
2261cb0ef41Sopenharmony_ci public:
2271cb0ef41Sopenharmony_ci  friend class RiscvDebugger;
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci  // Registers are declared in order. See SMRL chapter 2.
2301cb0ef41Sopenharmony_ci  enum Register {
2311cb0ef41Sopenharmony_ci    no_reg = -1,
2321cb0ef41Sopenharmony_ci    zero_reg = 0,
2331cb0ef41Sopenharmony_ci    ra,
2341cb0ef41Sopenharmony_ci    sp,
2351cb0ef41Sopenharmony_ci    gp,
2361cb0ef41Sopenharmony_ci    tp,
2371cb0ef41Sopenharmony_ci    t0,
2381cb0ef41Sopenharmony_ci    t1,
2391cb0ef41Sopenharmony_ci    t2,
2401cb0ef41Sopenharmony_ci    s0,
2411cb0ef41Sopenharmony_ci    s1,
2421cb0ef41Sopenharmony_ci    a0,
2431cb0ef41Sopenharmony_ci    a1,
2441cb0ef41Sopenharmony_ci    a2,
2451cb0ef41Sopenharmony_ci    a3,
2461cb0ef41Sopenharmony_ci    a4,
2471cb0ef41Sopenharmony_ci    a5,
2481cb0ef41Sopenharmony_ci    a6,
2491cb0ef41Sopenharmony_ci    a7,
2501cb0ef41Sopenharmony_ci    s2,
2511cb0ef41Sopenharmony_ci    s3,
2521cb0ef41Sopenharmony_ci    s4,
2531cb0ef41Sopenharmony_ci    s5,
2541cb0ef41Sopenharmony_ci    s6,
2551cb0ef41Sopenharmony_ci    s7,
2561cb0ef41Sopenharmony_ci    s8,
2571cb0ef41Sopenharmony_ci    s9,
2581cb0ef41Sopenharmony_ci    s10,
2591cb0ef41Sopenharmony_ci    s11,
2601cb0ef41Sopenharmony_ci    t3,
2611cb0ef41Sopenharmony_ci    t4,
2621cb0ef41Sopenharmony_ci    t5,
2631cb0ef41Sopenharmony_ci    t6,
2641cb0ef41Sopenharmony_ci    pc,  // pc must be the last register.
2651cb0ef41Sopenharmony_ci    kNumSimuRegisters,
2661cb0ef41Sopenharmony_ci    // aliases
2671cb0ef41Sopenharmony_ci    fp = s0
2681cb0ef41Sopenharmony_ci  };
2691cb0ef41Sopenharmony_ci
2701cb0ef41Sopenharmony_ci  // Coprocessor registers.
2711cb0ef41Sopenharmony_ci  // Generated code will always use doubles. So we will only use even registers.
2721cb0ef41Sopenharmony_ci  enum FPURegister {
2731cb0ef41Sopenharmony_ci    ft0,
2741cb0ef41Sopenharmony_ci    ft1,
2751cb0ef41Sopenharmony_ci    ft2,
2761cb0ef41Sopenharmony_ci    ft3,
2771cb0ef41Sopenharmony_ci    ft4,
2781cb0ef41Sopenharmony_ci    ft5,
2791cb0ef41Sopenharmony_ci    ft6,
2801cb0ef41Sopenharmony_ci    ft7,
2811cb0ef41Sopenharmony_ci    fs0,
2821cb0ef41Sopenharmony_ci    fs1,
2831cb0ef41Sopenharmony_ci    fa0,
2841cb0ef41Sopenharmony_ci    fa1,
2851cb0ef41Sopenharmony_ci    fa2,
2861cb0ef41Sopenharmony_ci    fa3,
2871cb0ef41Sopenharmony_ci    fa4,
2881cb0ef41Sopenharmony_ci    fa5,
2891cb0ef41Sopenharmony_ci    fa6,
2901cb0ef41Sopenharmony_ci    fa7,
2911cb0ef41Sopenharmony_ci    fs2,
2921cb0ef41Sopenharmony_ci    fs3,
2931cb0ef41Sopenharmony_ci    fs4,
2941cb0ef41Sopenharmony_ci    fs5,
2951cb0ef41Sopenharmony_ci    fs6,
2961cb0ef41Sopenharmony_ci    fs7,
2971cb0ef41Sopenharmony_ci    fs8,
2981cb0ef41Sopenharmony_ci    fs9,
2991cb0ef41Sopenharmony_ci    fs10,
3001cb0ef41Sopenharmony_ci    fs11,
3011cb0ef41Sopenharmony_ci    ft8,
3021cb0ef41Sopenharmony_ci    ft9,
3031cb0ef41Sopenharmony_ci    ft10,
3041cb0ef41Sopenharmony_ci    ft11,
3051cb0ef41Sopenharmony_ci    kNumFPURegisters
3061cb0ef41Sopenharmony_ci  };
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci  enum VRegister {
3091cb0ef41Sopenharmony_ci    v0,
3101cb0ef41Sopenharmony_ci    v1,
3111cb0ef41Sopenharmony_ci    v2,
3121cb0ef41Sopenharmony_ci    v3,
3131cb0ef41Sopenharmony_ci    v4,
3141cb0ef41Sopenharmony_ci    v5,
3151cb0ef41Sopenharmony_ci    v6,
3161cb0ef41Sopenharmony_ci    v7,
3171cb0ef41Sopenharmony_ci    v8,
3181cb0ef41Sopenharmony_ci    v9,
3191cb0ef41Sopenharmony_ci    v10,
3201cb0ef41Sopenharmony_ci    v11,
3211cb0ef41Sopenharmony_ci    v12,
3221cb0ef41Sopenharmony_ci    v13,
3231cb0ef41Sopenharmony_ci    v14,
3241cb0ef41Sopenharmony_ci    v15,
3251cb0ef41Sopenharmony_ci    v16,
3261cb0ef41Sopenharmony_ci    v17,
3271cb0ef41Sopenharmony_ci    v18,
3281cb0ef41Sopenharmony_ci    v19,
3291cb0ef41Sopenharmony_ci    v20,
3301cb0ef41Sopenharmony_ci    v21,
3311cb0ef41Sopenharmony_ci    v22,
3321cb0ef41Sopenharmony_ci    v23,
3331cb0ef41Sopenharmony_ci    v24,
3341cb0ef41Sopenharmony_ci    v25,
3351cb0ef41Sopenharmony_ci    v26,
3361cb0ef41Sopenharmony_ci    v27,
3371cb0ef41Sopenharmony_ci    v28,
3381cb0ef41Sopenharmony_ci    v29,
3391cb0ef41Sopenharmony_ci    v30,
3401cb0ef41Sopenharmony_ci    v31,
3411cb0ef41Sopenharmony_ci    kNumVRegisters
3421cb0ef41Sopenharmony_ci  };
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_ci  explicit Simulator(Isolate* isolate);
3451cb0ef41Sopenharmony_ci  ~Simulator();
3461cb0ef41Sopenharmony_ci
3471cb0ef41Sopenharmony_ci  // The currently executing Simulator instance. Potentially there can be one
3481cb0ef41Sopenharmony_ci  // for each native thread.
3491cb0ef41Sopenharmony_ci  V8_EXPORT_PRIVATE static Simulator* current(v8::internal::Isolate* isolate);
3501cb0ef41Sopenharmony_ci
3511cb0ef41Sopenharmony_ci  // Accessors for register state. Reading the pc value adheres to the RISC-V
3521cb0ef41Sopenharmony_ci  // architecture specification and is off by a 8 from the currently executing
3531cb0ef41Sopenharmony_ci  // instruction.
3541cb0ef41Sopenharmony_ci  void set_register(int reg, int64_t value);
3551cb0ef41Sopenharmony_ci  void set_register_word(int reg, int32_t value);
3561cb0ef41Sopenharmony_ci  void set_dw_register(int dreg, const int* dbl);
3571cb0ef41Sopenharmony_ci  V8_EXPORT_PRIVATE int64_t get_register(int reg) const;
3581cb0ef41Sopenharmony_ci  double get_double_from_register_pair(int reg);
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci  // Same for FPURegisters.
3611cb0ef41Sopenharmony_ci  void set_fpu_register(int fpureg, int64_t value);
3621cb0ef41Sopenharmony_ci  void set_fpu_register_word(int fpureg, int32_t value);
3631cb0ef41Sopenharmony_ci  void set_fpu_register_hi_word(int fpureg, int32_t value);
3641cb0ef41Sopenharmony_ci  void set_fpu_register_float(int fpureg, float value);
3651cb0ef41Sopenharmony_ci  void set_fpu_register_double(int fpureg, double value);
3661cb0ef41Sopenharmony_ci
3671cb0ef41Sopenharmony_ci  int64_t get_fpu_register(int fpureg) const;
3681cb0ef41Sopenharmony_ci  int32_t get_fpu_register_word(int fpureg) const;
3691cb0ef41Sopenharmony_ci  int32_t get_fpu_register_signed_word(int fpureg) const;
3701cb0ef41Sopenharmony_ci  int32_t get_fpu_register_hi_word(int fpureg) const;
3711cb0ef41Sopenharmony_ci  float get_fpu_register_float(int fpureg) const;
3721cb0ef41Sopenharmony_ci  double get_fpu_register_double(int fpureg) const;
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_ci  // RV CSR manipulation
3751cb0ef41Sopenharmony_ci  uint32_t read_csr_value(uint32_t csr);
3761cb0ef41Sopenharmony_ci  void write_csr_value(uint32_t csr, uint64_t value);
3771cb0ef41Sopenharmony_ci  void set_csr_bits(uint32_t csr, uint64_t flags);
3781cb0ef41Sopenharmony_ci  void clear_csr_bits(uint32_t csr, uint64_t flags);
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci  void set_fflags(uint32_t flags) { set_csr_bits(csr_fflags, flags); }
3811cb0ef41Sopenharmony_ci  void clear_fflags(int32_t flags) { clear_csr_bits(csr_fflags, flags); }
3821cb0ef41Sopenharmony_ci
3831cb0ef41Sopenharmony_ci#ifdef CAN_USE_RVV_INSTRUCTIONS
3841cb0ef41Sopenharmony_ci  // RVV CSR
3851cb0ef41Sopenharmony_ci  __int128_t get_vregister(int vreg) const;
3861cb0ef41Sopenharmony_ci  inline uint64_t rvv_vlen() const { return kRvvVLEN; }
3871cb0ef41Sopenharmony_ci  inline uint64_t rvv_vtype() const { return vtype_; }
3881cb0ef41Sopenharmony_ci  inline uint64_t rvv_vl() const { return vl_; }
3891cb0ef41Sopenharmony_ci  inline uint64_t rvv_vstart() const { return vstart_; }
3901cb0ef41Sopenharmony_ci  inline uint64_t rvv_vxsat() const { return vxsat_; }
3911cb0ef41Sopenharmony_ci  inline uint64_t rvv_vxrm() const { return vxrm_; }
3921cb0ef41Sopenharmony_ci  inline uint64_t rvv_vcsr() const { return vcsr_; }
3931cb0ef41Sopenharmony_ci  inline uint64_t rvv_vlenb() const { return vlenb_; }
3941cb0ef41Sopenharmony_ci  inline uint32_t rvv_zimm() const { return instr_.Rvvzimm(); }
3951cb0ef41Sopenharmony_ci  inline uint32_t rvv_vlmul() const { return (rvv_vtype() & 0x7); }
3961cb0ef41Sopenharmony_ci  inline float rvv_vflmul() const {
3971cb0ef41Sopenharmony_ci    if ((rvv_vtype() & 0b100) == 0) {
3981cb0ef41Sopenharmony_ci      return static_cast<float>(0x1 << (rvv_vtype() & 0x7));
3991cb0ef41Sopenharmony_ci    } else {
4001cb0ef41Sopenharmony_ci      return 1.0 / static_cast<float>(0x1 << (4 - rvv_vtype() & 0x3));
4011cb0ef41Sopenharmony_ci    }
4021cb0ef41Sopenharmony_ci  }
4031cb0ef41Sopenharmony_ci  inline uint32_t rvv_vsew() const { return ((rvv_vtype() >> 3) & 0x7); }
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ci  inline const char* rvv_sew_s() const {
4061cb0ef41Sopenharmony_ci    uint32_t vsew = rvv_vsew();
4071cb0ef41Sopenharmony_ci    switch (vsew) {
4081cb0ef41Sopenharmony_ci#define CAST_VSEW(name) \
4091cb0ef41Sopenharmony_ci  case name:            \
4101cb0ef41Sopenharmony_ci    return #name;
4111cb0ef41Sopenharmony_ci      RVV_SEW(CAST_VSEW)
4121cb0ef41Sopenharmony_ci      default:
4131cb0ef41Sopenharmony_ci        return "unknown";
4141cb0ef41Sopenharmony_ci#undef CAST_VSEW
4151cb0ef41Sopenharmony_ci    }
4161cb0ef41Sopenharmony_ci  }
4171cb0ef41Sopenharmony_ci
4181cb0ef41Sopenharmony_ci  inline const char* rvv_lmul_s() const {
4191cb0ef41Sopenharmony_ci    uint32_t vlmul = rvv_vlmul();
4201cb0ef41Sopenharmony_ci    switch (vlmul) {
4211cb0ef41Sopenharmony_ci#define CAST_VLMUL(name) \
4221cb0ef41Sopenharmony_ci  case name:             \
4231cb0ef41Sopenharmony_ci    return #name;
4241cb0ef41Sopenharmony_ci      RVV_LMUL(CAST_VLMUL)
4251cb0ef41Sopenharmony_ci      default:
4261cb0ef41Sopenharmony_ci        return "unknown";
4271cb0ef41Sopenharmony_ci#undef CAST_VLMUL
4281cb0ef41Sopenharmony_ci    }
4291cb0ef41Sopenharmony_ci  }
4301cb0ef41Sopenharmony_ci
4311cb0ef41Sopenharmony_ci  // return size of lane.8 16 32 64
4321cb0ef41Sopenharmony_ci  inline uint32_t rvv_sew() const {
4331cb0ef41Sopenharmony_ci    DCHECK_EQ(rvv_vsew() & (~0x7), 0x0);
4341cb0ef41Sopenharmony_ci    return (0x1 << rvv_vsew()) * 8;
4351cb0ef41Sopenharmony_ci  }
4361cb0ef41Sopenharmony_ci  inline uint64_t rvv_vlmax() const {
4371cb0ef41Sopenharmony_ci    if ((rvv_vlmul() & 0b100) != 0) {
4381cb0ef41Sopenharmony_ci      return (rvv_vlen() / rvv_sew()) >> (4 - (rvv_vlmul() & 0b11));
4391cb0ef41Sopenharmony_ci    } else {
4401cb0ef41Sopenharmony_ci      return ((rvv_vlen() << rvv_vlmul()) / rvv_sew());
4411cb0ef41Sopenharmony_ci    }
4421cb0ef41Sopenharmony_ci  }
4431cb0ef41Sopenharmony_ci#endif
4441cb0ef41Sopenharmony_ci
4451cb0ef41Sopenharmony_ci  inline uint32_t get_dynamic_rounding_mode();
4461cb0ef41Sopenharmony_ci  inline bool test_fflags_bits(uint32_t mask);
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ci  float RoundF2FHelper(float input_val, int rmode);
4491cb0ef41Sopenharmony_ci  double RoundF2FHelper(double input_val, int rmode);
4501cb0ef41Sopenharmony_ci  template <typename I_TYPE, typename F_TYPE>
4511cb0ef41Sopenharmony_ci  I_TYPE RoundF2IHelper(F_TYPE original, int rmode);
4521cb0ef41Sopenharmony_ci
4531cb0ef41Sopenharmony_ci  template <typename T>
4541cb0ef41Sopenharmony_ci  T FMaxMinHelper(T a, T b, MaxMinKind kind);
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  template <typename T>
4571cb0ef41Sopenharmony_ci  bool CompareFHelper(T input1, T input2, FPUCondition cc);
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci  // Special case of set_register and get_register to access the raw PC value.
4601cb0ef41Sopenharmony_ci  void set_pc(int64_t value);
4611cb0ef41Sopenharmony_ci  V8_EXPORT_PRIVATE int64_t get_pc() const;
4621cb0ef41Sopenharmony_ci
4631cb0ef41Sopenharmony_ci  Address get_sp() const { return static_cast<Address>(get_register(sp)); }
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_ci  // Accessor to the internal simulator stack area.
4661cb0ef41Sopenharmony_ci  uintptr_t StackLimit(uintptr_t c_limit) const;
4671cb0ef41Sopenharmony_ci
4681cb0ef41Sopenharmony_ci  // Executes RISC-V instructions until the PC reaches end_sim_pc.
4691cb0ef41Sopenharmony_ci  void Execute();
4701cb0ef41Sopenharmony_ci
4711cb0ef41Sopenharmony_ci  template <typename Return, typename... Args>
4721cb0ef41Sopenharmony_ci  Return Call(Address entry, Args... args) {
4731cb0ef41Sopenharmony_ci    return VariadicCall<Return>(this, &Simulator::CallImpl, entry, args...);
4741cb0ef41Sopenharmony_ci  }
4751cb0ef41Sopenharmony_ci
4761cb0ef41Sopenharmony_ci  // Alternative: call a 2-argument double function.
4771cb0ef41Sopenharmony_ci  double CallFP(Address entry, double d0, double d1);
4781cb0ef41Sopenharmony_ci
4791cb0ef41Sopenharmony_ci  // Push an address onto the JS stack.
4801cb0ef41Sopenharmony_ci  uintptr_t PushAddress(uintptr_t address);
4811cb0ef41Sopenharmony_ci
4821cb0ef41Sopenharmony_ci  // Pop an address from the JS stack.
4831cb0ef41Sopenharmony_ci  uintptr_t PopAddress();
4841cb0ef41Sopenharmony_ci
4851cb0ef41Sopenharmony_ci  // Debugger input.
4861cb0ef41Sopenharmony_ci  void set_last_debugger_input(char* input);
4871cb0ef41Sopenharmony_ci  char* last_debugger_input() { return last_debugger_input_; }
4881cb0ef41Sopenharmony_ci
4891cb0ef41Sopenharmony_ci  // Redirection support.
4901cb0ef41Sopenharmony_ci  static void SetRedirectInstruction(Instruction* instruction);
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ci  // ICache checking.
4931cb0ef41Sopenharmony_ci  static bool ICacheMatch(void* one, void* two);
4941cb0ef41Sopenharmony_ci  static void FlushICache(base::CustomMatcherHashMap* i_cache, void* start,
4951cb0ef41Sopenharmony_ci                          size_t size);
4961cb0ef41Sopenharmony_ci
4971cb0ef41Sopenharmony_ci  // Returns true if pc register contains one of the 'special_values' defined
4981cb0ef41Sopenharmony_ci  // below (bad_ra, end_sim_pc).
4991cb0ef41Sopenharmony_ci  bool has_bad_pc() const;
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_ci private:
5021cb0ef41Sopenharmony_ci  enum special_values {
5031cb0ef41Sopenharmony_ci    // Known bad pc value to ensure that the simulator does not execute
5041cb0ef41Sopenharmony_ci    // without being properly setup.
5051cb0ef41Sopenharmony_ci    bad_ra = -1,
5061cb0ef41Sopenharmony_ci    // A pc value used to signal the simulator to stop execution.  Generally
5071cb0ef41Sopenharmony_ci    // the ra is set to this value on transition from native C code to
5081cb0ef41Sopenharmony_ci    // simulated execution, so that the simulator can "return" to the native
5091cb0ef41Sopenharmony_ci    // C code.
5101cb0ef41Sopenharmony_ci    end_sim_pc = -2,
5111cb0ef41Sopenharmony_ci    // Unpredictable value.
5121cb0ef41Sopenharmony_ci    Unpredictable = 0xbadbeaf
5131cb0ef41Sopenharmony_ci  };
5141cb0ef41Sopenharmony_ci
5151cb0ef41Sopenharmony_ci  V8_EXPORT_PRIVATE intptr_t CallImpl(Address entry, int argument_count,
5161cb0ef41Sopenharmony_ci                                      const intptr_t* arguments);
5171cb0ef41Sopenharmony_ci
5181cb0ef41Sopenharmony_ci  // Unsupported instructions use Format to print an error and stop execution.
5191cb0ef41Sopenharmony_ci  void Format(Instruction* instr, const char* format);
5201cb0ef41Sopenharmony_ci
5211cb0ef41Sopenharmony_ci  // Helpers for data value tracing.
5221cb0ef41Sopenharmony_ci  enum TraceType {
5231cb0ef41Sopenharmony_ci    BYTE,
5241cb0ef41Sopenharmony_ci    HALF,
5251cb0ef41Sopenharmony_ci    WORD,
5261cb0ef41Sopenharmony_ci    DWORD,
5271cb0ef41Sopenharmony_ci    FLOAT,
5281cb0ef41Sopenharmony_ci    DOUBLE,
5291cb0ef41Sopenharmony_ci    // FLOAT_DOUBLE,
5301cb0ef41Sopenharmony_ci    // WORD_DWORD
5311cb0ef41Sopenharmony_ci  };
5321cb0ef41Sopenharmony_ci
5331cb0ef41Sopenharmony_ci  // RISCV Memory read/write methods
5341cb0ef41Sopenharmony_ci  template <typename T>
5351cb0ef41Sopenharmony_ci  T ReadMem(int64_t addr, Instruction* instr);
5361cb0ef41Sopenharmony_ci  template <typename T>
5371cb0ef41Sopenharmony_ci  void WriteMem(int64_t addr, T value, Instruction* instr);
5381cb0ef41Sopenharmony_ci  template <typename T, typename OP>
5391cb0ef41Sopenharmony_ci  T amo(int64_t addr, OP f, Instruction* instr, TraceType t) {
5401cb0ef41Sopenharmony_ci    auto lhs = ReadMem<T>(addr, instr);
5411cb0ef41Sopenharmony_ci    // TODO(RISCV): trace memory read for AMO
5421cb0ef41Sopenharmony_ci    WriteMem<T>(addr, (T)f(lhs), instr);
5431cb0ef41Sopenharmony_ci    return lhs;
5441cb0ef41Sopenharmony_ci  }
5451cb0ef41Sopenharmony_ci
5461cb0ef41Sopenharmony_ci  // Helper for debugging memory access.
5471cb0ef41Sopenharmony_ci  inline void DieOrDebug();
5481cb0ef41Sopenharmony_ci
5491cb0ef41Sopenharmony_ci  void TraceRegWr(int64_t value, TraceType t = DWORD);
5501cb0ef41Sopenharmony_ci  void TraceMemWr(int64_t addr, int64_t value, TraceType t);
5511cb0ef41Sopenharmony_ci  template <typename T>
5521cb0ef41Sopenharmony_ci  void TraceMemRd(int64_t addr, T value, int64_t reg_value);
5531cb0ef41Sopenharmony_ci  template <typename T>
5541cb0ef41Sopenharmony_ci  void TraceMemWr(int64_t addr, T value);
5551cb0ef41Sopenharmony_ci
5561cb0ef41Sopenharmony_ci  SimInstruction instr_;
5571cb0ef41Sopenharmony_ci
5581cb0ef41Sopenharmony_ci  // RISCV utlity API to access register value
5591cb0ef41Sopenharmony_ci  inline int32_t rs1_reg() const { return instr_.Rs1Value(); }
5601cb0ef41Sopenharmony_ci  inline int64_t rs1() const { return get_register(rs1_reg()); }
5611cb0ef41Sopenharmony_ci  inline float frs1() const { return get_fpu_register_float(rs1_reg()); }
5621cb0ef41Sopenharmony_ci  inline double drs1() const { return get_fpu_register_double(rs1_reg()); }
5631cb0ef41Sopenharmony_ci  inline int32_t rs2_reg() const { return instr_.Rs2Value(); }
5641cb0ef41Sopenharmony_ci  inline int64_t rs2() const { return get_register(rs2_reg()); }
5651cb0ef41Sopenharmony_ci  inline float frs2() const { return get_fpu_register_float(rs2_reg()); }
5661cb0ef41Sopenharmony_ci  inline double drs2() const { return get_fpu_register_double(rs2_reg()); }
5671cb0ef41Sopenharmony_ci  inline int32_t rs3_reg() const { return instr_.Rs3Value(); }
5681cb0ef41Sopenharmony_ci  inline int64_t rs3() const { return get_register(rs3_reg()); }
5691cb0ef41Sopenharmony_ci  inline float frs3() const { return get_fpu_register_float(rs3_reg()); }
5701cb0ef41Sopenharmony_ci  inline double drs3() const { return get_fpu_register_double(rs3_reg()); }
5711cb0ef41Sopenharmony_ci  inline int32_t rd_reg() const { return instr_.RdValue(); }
5721cb0ef41Sopenharmony_ci  inline int32_t frd_reg() const { return instr_.RdValue(); }
5731cb0ef41Sopenharmony_ci  inline int32_t rvc_rs1_reg() const { return instr_.RvcRs1Value(); }
5741cb0ef41Sopenharmony_ci  inline int64_t rvc_rs1() const { return get_register(rvc_rs1_reg()); }
5751cb0ef41Sopenharmony_ci  inline int32_t rvc_rs2_reg() const { return instr_.RvcRs2Value(); }
5761cb0ef41Sopenharmony_ci  inline int64_t rvc_rs2() const { return get_register(rvc_rs2_reg()); }
5771cb0ef41Sopenharmony_ci  inline double rvc_drs2() const {
5781cb0ef41Sopenharmony_ci    return get_fpu_register_double(rvc_rs2_reg());
5791cb0ef41Sopenharmony_ci  }
5801cb0ef41Sopenharmony_ci  inline int32_t rvc_rs1s_reg() const { return instr_.RvcRs1sValue(); }
5811cb0ef41Sopenharmony_ci  inline int64_t rvc_rs1s() const { return get_register(rvc_rs1s_reg()); }
5821cb0ef41Sopenharmony_ci  inline int32_t rvc_rs2s_reg() const { return instr_.RvcRs2sValue(); }
5831cb0ef41Sopenharmony_ci  inline int64_t rvc_rs2s() const { return get_register(rvc_rs2s_reg()); }
5841cb0ef41Sopenharmony_ci  inline double rvc_drs2s() const {
5851cb0ef41Sopenharmony_ci    return get_fpu_register_double(rvc_rs2s_reg());
5861cb0ef41Sopenharmony_ci  }
5871cb0ef41Sopenharmony_ci  inline int32_t rvc_rd_reg() const { return instr_.RvcRdValue(); }
5881cb0ef41Sopenharmony_ci  inline int32_t rvc_frd_reg() const { return instr_.RvcRdValue(); }
5891cb0ef41Sopenharmony_ci  inline int16_t boffset() const { return instr_.BranchOffset(); }
5901cb0ef41Sopenharmony_ci  inline int16_t imm12() const { return instr_.Imm12Value(); }
5911cb0ef41Sopenharmony_ci  inline int32_t imm20J() const { return instr_.Imm20JValue(); }
5921cb0ef41Sopenharmony_ci  inline int32_t imm5CSR() const { return instr_.Rs1Value(); }
5931cb0ef41Sopenharmony_ci  inline int16_t csr_reg() const { return instr_.CsrValue(); }
5941cb0ef41Sopenharmony_ci  inline int16_t rvc_imm6() const { return instr_.RvcImm6Value(); }
5951cb0ef41Sopenharmony_ci  inline int16_t rvc_imm6_addi16sp() const {
5961cb0ef41Sopenharmony_ci    return instr_.RvcImm6Addi16spValue();
5971cb0ef41Sopenharmony_ci  }
5981cb0ef41Sopenharmony_ci  inline int16_t rvc_imm8_addi4spn() const {
5991cb0ef41Sopenharmony_ci    return instr_.RvcImm8Addi4spnValue();
6001cb0ef41Sopenharmony_ci  }
6011cb0ef41Sopenharmony_ci  inline int16_t rvc_imm6_lwsp() const { return instr_.RvcImm6LwspValue(); }
6021cb0ef41Sopenharmony_ci  inline int16_t rvc_imm6_ldsp() const { return instr_.RvcImm6LdspValue(); }
6031cb0ef41Sopenharmony_ci  inline int16_t rvc_imm6_swsp() const { return instr_.RvcImm6SwspValue(); }
6041cb0ef41Sopenharmony_ci  inline int16_t rvc_imm6_sdsp() const { return instr_.RvcImm6SdspValue(); }
6051cb0ef41Sopenharmony_ci  inline int16_t rvc_imm5_w() const { return instr_.RvcImm5WValue(); }
6061cb0ef41Sopenharmony_ci  inline int16_t rvc_imm5_d() const { return instr_.RvcImm5DValue(); }
6071cb0ef41Sopenharmony_ci  inline int16_t rvc_imm8_b() const { return instr_.RvcImm8BValue(); }
6081cb0ef41Sopenharmony_ci
6091cb0ef41Sopenharmony_ci  inline void set_rd(int64_t value, bool trace = true) {
6101cb0ef41Sopenharmony_ci    set_register(rd_reg(), value);
6111cb0ef41Sopenharmony_ci    if (trace) TraceRegWr(get_register(rd_reg()), DWORD);
6121cb0ef41Sopenharmony_ci  }
6131cb0ef41Sopenharmony_ci  inline void set_frd(float value, bool trace = true) {
6141cb0ef41Sopenharmony_ci    set_fpu_register_float(rd_reg(), value);
6151cb0ef41Sopenharmony_ci    if (trace) TraceRegWr(get_fpu_register_word(rd_reg()), FLOAT);
6161cb0ef41Sopenharmony_ci  }
6171cb0ef41Sopenharmony_ci  inline void set_drd(double value, bool trace = true) {
6181cb0ef41Sopenharmony_ci    set_fpu_register_double(rd_reg(), value);
6191cb0ef41Sopenharmony_ci    if (trace) TraceRegWr(get_fpu_register(rd_reg()), DOUBLE);
6201cb0ef41Sopenharmony_ci  }
6211cb0ef41Sopenharmony_ci  inline void set_rvc_rd(int64_t value, bool trace = true) {
6221cb0ef41Sopenharmony_ci    set_register(rvc_rd_reg(), value);
6231cb0ef41Sopenharmony_ci    if (trace) TraceRegWr(get_register(rvc_rd_reg()), DWORD);
6241cb0ef41Sopenharmony_ci  }
6251cb0ef41Sopenharmony_ci  inline void set_rvc_rs1s(int64_t value, bool trace = true) {
6261cb0ef41Sopenharmony_ci    set_register(rvc_rs1s_reg(), value);
6271cb0ef41Sopenharmony_ci    if (trace) TraceRegWr(get_register(rvc_rs1s_reg()), DWORD);
6281cb0ef41Sopenharmony_ci  }
6291cb0ef41Sopenharmony_ci  inline void set_rvc_rs2(int64_t value, bool trace = true) {
6301cb0ef41Sopenharmony_ci    set_register(rvc_rs2_reg(), value);
6311cb0ef41Sopenharmony_ci    if (trace) TraceRegWr(get_register(rvc_rs2_reg()), DWORD);
6321cb0ef41Sopenharmony_ci  }
6331cb0ef41Sopenharmony_ci  inline void set_rvc_drd(double value, bool trace = true) {
6341cb0ef41Sopenharmony_ci    set_fpu_register_double(rvc_rd_reg(), value);
6351cb0ef41Sopenharmony_ci    if (trace) TraceRegWr(get_fpu_register(rvc_rd_reg()), DOUBLE);
6361cb0ef41Sopenharmony_ci  }
6371cb0ef41Sopenharmony_ci  inline void set_rvc_rs2s(int64_t value, bool trace = true) {
6381cb0ef41Sopenharmony_ci    set_register(rvc_rs2s_reg(), value);
6391cb0ef41Sopenharmony_ci    if (trace) TraceRegWr(get_register(rvc_rs2s_reg()), DWORD);
6401cb0ef41Sopenharmony_ci  }
6411cb0ef41Sopenharmony_ci  inline void set_rvc_drs2s(double value, bool trace = true) {
6421cb0ef41Sopenharmony_ci    set_fpu_register_double(rvc_rs2s_reg(), value);
6431cb0ef41Sopenharmony_ci    if (trace) TraceRegWr(get_fpu_register(rvc_rs2s_reg()), DOUBLE);
6441cb0ef41Sopenharmony_ci  }
6451cb0ef41Sopenharmony_ci  inline int16_t shamt6() const { return (imm12() & 0x3F); }
6461cb0ef41Sopenharmony_ci  inline int16_t shamt5() const { return (imm12() & 0x1F); }
6471cb0ef41Sopenharmony_ci  inline int16_t rvc_shamt6() const { return instr_.RvcShamt6(); }
6481cb0ef41Sopenharmony_ci  inline int32_t s_imm12() const { return instr_.StoreOffset(); }
6491cb0ef41Sopenharmony_ci  inline int32_t u_imm20() const { return instr_.Imm20UValue() << 12; }
6501cb0ef41Sopenharmony_ci  inline int32_t rvc_u_imm6() const { return instr_.RvcImm6Value() << 12; }
6511cb0ef41Sopenharmony_ci  inline void require(bool check) {
6521cb0ef41Sopenharmony_ci    if (!check) {
6531cb0ef41Sopenharmony_ci      SignalException(kIllegalInstruction);
6541cb0ef41Sopenharmony_ci    }
6551cb0ef41Sopenharmony_ci  }
6561cb0ef41Sopenharmony_ci
6571cb0ef41Sopenharmony_ci#ifdef CAN_USE_RVV_INSTRUCTIONS
6581cb0ef41Sopenharmony_ci  inline void rvv_trace_vd() {
6591cb0ef41Sopenharmony_ci    if (::v8::internal::FLAG_trace_sim) {
6601cb0ef41Sopenharmony_ci      __int128_t value = Vregister_[rvv_vd_reg()];
6611cb0ef41Sopenharmony_ci      SNPrintF(trace_buf_, "%016" PRIx64 "%016" PRIx64 " (%" PRId64 ")",
6621cb0ef41Sopenharmony_ci               *(reinterpret_cast<int64_t*>(&value) + 1),
6631cb0ef41Sopenharmony_ci               *reinterpret_cast<int64_t*>(&value), icount_);
6641cb0ef41Sopenharmony_ci    }
6651cb0ef41Sopenharmony_ci  }
6661cb0ef41Sopenharmony_ci
6671cb0ef41Sopenharmony_ci  inline void rvv_trace_vs1() {
6681cb0ef41Sopenharmony_ci    if (::v8::internal::FLAG_trace_sim) {
6691cb0ef41Sopenharmony_ci      PrintF("\t%s:0x%016" PRIx64 "%016" PRIx64 "\n",
6701cb0ef41Sopenharmony_ci             v8::internal::VRegisters::Name(static_cast<int>(rvv_vs1_reg())),
6711cb0ef41Sopenharmony_ci             (uint64_t)(get_vregister(static_cast<int>(rvv_vs1_reg())) >> 64),
6721cb0ef41Sopenharmony_ci             (uint64_t)get_vregister(static_cast<int>(rvv_vs1_reg())));
6731cb0ef41Sopenharmony_ci    }
6741cb0ef41Sopenharmony_ci  }
6751cb0ef41Sopenharmony_ci
6761cb0ef41Sopenharmony_ci  inline void rvv_trace_vs2() {
6771cb0ef41Sopenharmony_ci    if (::v8::internal::FLAG_trace_sim) {
6781cb0ef41Sopenharmony_ci      PrintF("\t%s:0x%016" PRIx64 "%016" PRIx64 "\n",
6791cb0ef41Sopenharmony_ci             v8::internal::VRegisters::Name(static_cast<int>(rvv_vs2_reg())),
6801cb0ef41Sopenharmony_ci             (uint64_t)(get_vregister(static_cast<int>(rvv_vs2_reg())) >> 64),
6811cb0ef41Sopenharmony_ci             (uint64_t)get_vregister(static_cast<int>(rvv_vs2_reg())));
6821cb0ef41Sopenharmony_ci    }
6831cb0ef41Sopenharmony_ci  }
6841cb0ef41Sopenharmony_ci  inline void rvv_trace_v0() {
6851cb0ef41Sopenharmony_ci    if (::v8::internal::FLAG_trace_sim) {
6861cb0ef41Sopenharmony_ci      PrintF("\t%s:0x%016" PRIx64 "%016" PRIx64 "\n",
6871cb0ef41Sopenharmony_ci             v8::internal::VRegisters::Name(v0),
6881cb0ef41Sopenharmony_ci             (uint64_t)(get_vregister(v0) >> 64), (uint64_t)get_vregister(v0));
6891cb0ef41Sopenharmony_ci    }
6901cb0ef41Sopenharmony_ci  }
6911cb0ef41Sopenharmony_ci
6921cb0ef41Sopenharmony_ci  inline void rvv_trace_rs1() {
6931cb0ef41Sopenharmony_ci    if (::v8::internal::FLAG_trace_sim) {
6941cb0ef41Sopenharmony_ci      PrintF("\t%s:0x%016" PRIx64 "\n",
6951cb0ef41Sopenharmony_ci             v8::internal::Registers::Name(static_cast<int>(rs1_reg())),
6961cb0ef41Sopenharmony_ci             (uint64_t)(get_register(rs1_reg())));
6971cb0ef41Sopenharmony_ci    }
6981cb0ef41Sopenharmony_ci  }
6991cb0ef41Sopenharmony_ci
7001cb0ef41Sopenharmony_ci  inline void rvv_trace_status() {
7011cb0ef41Sopenharmony_ci    if (::v8::internal::FLAG_trace_sim) {
7021cb0ef41Sopenharmony_ci      int i = 0;
7031cb0ef41Sopenharmony_ci      for (; i < trace_buf_.length(); i++) {
7041cb0ef41Sopenharmony_ci        if (trace_buf_[i] == '\0') break;
7051cb0ef41Sopenharmony_ci      }
7061cb0ef41Sopenharmony_ci      SNPrintF(trace_buf_.SubVector(i, trace_buf_.length()),
7071cb0ef41Sopenharmony_ci               "  sew:%s lmul:%s vstart:%lu vl:%lu", rvv_sew_s(), rvv_lmul_s(),
7081cb0ef41Sopenharmony_ci               rvv_vstart(), rvv_vl());
7091cb0ef41Sopenharmony_ci    }
7101cb0ef41Sopenharmony_ci  }
7111cb0ef41Sopenharmony_ci
7121cb0ef41Sopenharmony_ci  template <class T>
7131cb0ef41Sopenharmony_ci  T& Rvvelt(reg_t vReg, uint64_t n, bool is_write = false) {
7141cb0ef41Sopenharmony_ci    CHECK_NE(rvv_sew(), 0);
7151cb0ef41Sopenharmony_ci    CHECK_GT((rvv_vlen() >> 3) / sizeof(T), 0);
7161cb0ef41Sopenharmony_ci    reg_t elts_per_reg = (rvv_vlen() >> 3) / (sizeof(T));
7171cb0ef41Sopenharmony_ci    vReg += n / elts_per_reg;
7181cb0ef41Sopenharmony_ci    n = n % elts_per_reg;
7191cb0ef41Sopenharmony_ci    T* regStart = reinterpret_cast<T*>(reinterpret_cast<char*>(Vregister_) +
7201cb0ef41Sopenharmony_ci                                       vReg * (rvv_vlen() >> 3));
7211cb0ef41Sopenharmony_ci    return regStart[n];
7221cb0ef41Sopenharmony_ci  }
7231cb0ef41Sopenharmony_ci
7241cb0ef41Sopenharmony_ci  inline int32_t rvv_vs1_reg() { return instr_.Vs1Value(); }
7251cb0ef41Sopenharmony_ci  inline reg_t rvv_vs1() { UNIMPLEMENTED(); }
7261cb0ef41Sopenharmony_ci  inline int32_t rvv_vs2_reg() { return instr_.Vs2Value(); }
7271cb0ef41Sopenharmony_ci  inline reg_t rvv_vs2() { UNIMPLEMENTED(); }
7281cb0ef41Sopenharmony_ci  inline int32_t rvv_vd_reg() { return instr_.VdValue(); }
7291cb0ef41Sopenharmony_ci  inline int32_t rvv_vs3_reg() { return instr_.VdValue(); }
7301cb0ef41Sopenharmony_ci  inline reg_t rvv_vd() { UNIMPLEMENTED(); }
7311cb0ef41Sopenharmony_ci  inline int32_t rvv_nf() {
7321cb0ef41Sopenharmony_ci    return (instr_.InstructionBits() & kRvvNfMask) >> kRvvNfShift;
7331cb0ef41Sopenharmony_ci  }
7341cb0ef41Sopenharmony_ci
7351cb0ef41Sopenharmony_ci  inline void set_vrd() { UNIMPLEMENTED(); }
7361cb0ef41Sopenharmony_ci
7371cb0ef41Sopenharmony_ci  inline void set_rvv_vtype(uint64_t value, bool trace = true) {
7381cb0ef41Sopenharmony_ci    vtype_ = value;
7391cb0ef41Sopenharmony_ci  }
7401cb0ef41Sopenharmony_ci  inline void set_rvv_vl(uint64_t value, bool trace = true) { vl_ = value; }
7411cb0ef41Sopenharmony_ci  inline void set_rvv_vstart(uint64_t value, bool trace = true) {
7421cb0ef41Sopenharmony_ci    vstart_ = value;
7431cb0ef41Sopenharmony_ci  }
7441cb0ef41Sopenharmony_ci  inline void set_rvv_vxsat(uint64_t value, bool trace = true) {
7451cb0ef41Sopenharmony_ci    vxsat_ = value;
7461cb0ef41Sopenharmony_ci  }
7471cb0ef41Sopenharmony_ci  inline void set_rvv_vxrm(uint64_t value, bool trace = true) { vxrm_ = value; }
7481cb0ef41Sopenharmony_ci  inline void set_rvv_vcsr(uint64_t value, bool trace = true) { vcsr_ = value; }
7491cb0ef41Sopenharmony_ci  inline void set_rvv_vlenb(uint64_t value, bool trace = true) {
7501cb0ef41Sopenharmony_ci    vlenb_ = value;
7511cb0ef41Sopenharmony_ci  }
7521cb0ef41Sopenharmony_ci#endif
7531cb0ef41Sopenharmony_ci
7541cb0ef41Sopenharmony_ci  template <typename T, typename Func>
7551cb0ef41Sopenharmony_ci  inline T CanonicalizeFPUOpFMA(Func fn, T dst, T src1, T src2) {
7561cb0ef41Sopenharmony_ci    STATIC_ASSERT(std::is_floating_point<T>::value);
7571cb0ef41Sopenharmony_ci    auto alu_out = fn(dst, src1, src2);
7581cb0ef41Sopenharmony_ci    // if any input or result is NaN, the result is quiet_NaN
7591cb0ef41Sopenharmony_ci    if (std::isnan(alu_out) || std::isnan(src1) || std::isnan(src2) ||
7601cb0ef41Sopenharmony_ci        std::isnan(dst)) {
7611cb0ef41Sopenharmony_ci      // signaling_nan sets kInvalidOperation bit
7621cb0ef41Sopenharmony_ci      if (isSnan(alu_out) || isSnan(src1) || isSnan(src2) || isSnan(dst))
7631cb0ef41Sopenharmony_ci        set_fflags(kInvalidOperation);
7641cb0ef41Sopenharmony_ci      alu_out = std::numeric_limits<T>::quiet_NaN();
7651cb0ef41Sopenharmony_ci    }
7661cb0ef41Sopenharmony_ci    return alu_out;
7671cb0ef41Sopenharmony_ci  }
7681cb0ef41Sopenharmony_ci
7691cb0ef41Sopenharmony_ci  template <typename T, typename Func>
7701cb0ef41Sopenharmony_ci  inline T CanonicalizeFPUOp3(Func fn) {
7711cb0ef41Sopenharmony_ci    STATIC_ASSERT(std::is_floating_point<T>::value);
7721cb0ef41Sopenharmony_ci    T src1 = std::is_same<float, T>::value ? frs1() : drs1();
7731cb0ef41Sopenharmony_ci    T src2 = std::is_same<float, T>::value ? frs2() : drs2();
7741cb0ef41Sopenharmony_ci    T src3 = std::is_same<float, T>::value ? frs3() : drs3();
7751cb0ef41Sopenharmony_ci    auto alu_out = fn(src1, src2, src3);
7761cb0ef41Sopenharmony_ci    // if any input or result is NaN, the result is quiet_NaN
7771cb0ef41Sopenharmony_ci    if (std::isnan(alu_out) || std::isnan(src1) || std::isnan(src2) ||
7781cb0ef41Sopenharmony_ci        std::isnan(src3)) {
7791cb0ef41Sopenharmony_ci      // signaling_nan sets kInvalidOperation bit
7801cb0ef41Sopenharmony_ci      if (isSnan(alu_out) || isSnan(src1) || isSnan(src2) || isSnan(src3))
7811cb0ef41Sopenharmony_ci        set_fflags(kInvalidOperation);
7821cb0ef41Sopenharmony_ci      alu_out = std::numeric_limits<T>::quiet_NaN();
7831cb0ef41Sopenharmony_ci    }
7841cb0ef41Sopenharmony_ci    return alu_out;
7851cb0ef41Sopenharmony_ci  }
7861cb0ef41Sopenharmony_ci
7871cb0ef41Sopenharmony_ci  template <typename T, typename Func>
7881cb0ef41Sopenharmony_ci  inline T CanonicalizeFPUOp2(Func fn) {
7891cb0ef41Sopenharmony_ci    STATIC_ASSERT(std::is_floating_point<T>::value);
7901cb0ef41Sopenharmony_ci    T src1 = std::is_same<float, T>::value ? frs1() : drs1();
7911cb0ef41Sopenharmony_ci    T src2 = std::is_same<float, T>::value ? frs2() : drs2();
7921cb0ef41Sopenharmony_ci    auto alu_out = fn(src1, src2);
7931cb0ef41Sopenharmony_ci    // if any input or result is NaN, the result is quiet_NaN
7941cb0ef41Sopenharmony_ci    if (std::isnan(alu_out) || std::isnan(src1) || std::isnan(src2)) {
7951cb0ef41Sopenharmony_ci      // signaling_nan sets kInvalidOperation bit
7961cb0ef41Sopenharmony_ci      if (isSnan(alu_out) || isSnan(src1) || isSnan(src2))
7971cb0ef41Sopenharmony_ci        set_fflags(kInvalidOperation);
7981cb0ef41Sopenharmony_ci      alu_out = std::numeric_limits<T>::quiet_NaN();
7991cb0ef41Sopenharmony_ci    }
8001cb0ef41Sopenharmony_ci    return alu_out;
8011cb0ef41Sopenharmony_ci  }
8021cb0ef41Sopenharmony_ci
8031cb0ef41Sopenharmony_ci  template <typename T, typename Func>
8041cb0ef41Sopenharmony_ci  inline T CanonicalizeFPUOp1(Func fn) {
8051cb0ef41Sopenharmony_ci    STATIC_ASSERT(std::is_floating_point<T>::value);
8061cb0ef41Sopenharmony_ci    T src1 = std::is_same<float, T>::value ? frs1() : drs1();
8071cb0ef41Sopenharmony_ci    auto alu_out = fn(src1);
8081cb0ef41Sopenharmony_ci    // if any input or result is NaN, the result is quiet_NaN
8091cb0ef41Sopenharmony_ci    if (std::isnan(alu_out) || std::isnan(src1)) {
8101cb0ef41Sopenharmony_ci      // signaling_nan sets kInvalidOperation bit
8111cb0ef41Sopenharmony_ci      if (isSnan(alu_out) || isSnan(src1)) set_fflags(kInvalidOperation);
8121cb0ef41Sopenharmony_ci      alu_out = std::numeric_limits<T>::quiet_NaN();
8131cb0ef41Sopenharmony_ci    }
8141cb0ef41Sopenharmony_ci    return alu_out;
8151cb0ef41Sopenharmony_ci  }
8161cb0ef41Sopenharmony_ci
8171cb0ef41Sopenharmony_ci  template <typename Func>
8181cb0ef41Sopenharmony_ci  inline float CanonicalizeDoubleToFloatOperation(Func fn) {
8191cb0ef41Sopenharmony_ci    float alu_out = fn(drs1());
8201cb0ef41Sopenharmony_ci    if (std::isnan(alu_out) || std::isnan(drs1()))
8211cb0ef41Sopenharmony_ci      alu_out = std::numeric_limits<float>::quiet_NaN();
8221cb0ef41Sopenharmony_ci    return alu_out;
8231cb0ef41Sopenharmony_ci  }
8241cb0ef41Sopenharmony_ci
8251cb0ef41Sopenharmony_ci  template <typename Func>
8261cb0ef41Sopenharmony_ci  inline float CanonicalizeDoubleToFloatOperation(Func fn, double frs) {
8271cb0ef41Sopenharmony_ci    float alu_out = fn(frs);
8281cb0ef41Sopenharmony_ci    if (std::isnan(alu_out) || std::isnan(drs1()))
8291cb0ef41Sopenharmony_ci      alu_out = std::numeric_limits<float>::quiet_NaN();
8301cb0ef41Sopenharmony_ci    return alu_out;
8311cb0ef41Sopenharmony_ci  }
8321cb0ef41Sopenharmony_ci
8331cb0ef41Sopenharmony_ci  template <typename Func>
8341cb0ef41Sopenharmony_ci  inline float CanonicalizeFloatToDoubleOperation(Func fn, float frs) {
8351cb0ef41Sopenharmony_ci    double alu_out = fn(frs);
8361cb0ef41Sopenharmony_ci    if (std::isnan(alu_out) || std::isnan(frs1()))
8371cb0ef41Sopenharmony_ci      alu_out = std::numeric_limits<double>::quiet_NaN();
8381cb0ef41Sopenharmony_ci    return alu_out;
8391cb0ef41Sopenharmony_ci  }
8401cb0ef41Sopenharmony_ci
8411cb0ef41Sopenharmony_ci  template <typename Func>
8421cb0ef41Sopenharmony_ci  inline float CanonicalizeFloatToDoubleOperation(Func fn) {
8431cb0ef41Sopenharmony_ci    double alu_out = fn(frs1());
8441cb0ef41Sopenharmony_ci    if (std::isnan(alu_out) || std::isnan(frs1()))
8451cb0ef41Sopenharmony_ci      alu_out = std::numeric_limits<double>::quiet_NaN();
8461cb0ef41Sopenharmony_ci    return alu_out;
8471cb0ef41Sopenharmony_ci  }
8481cb0ef41Sopenharmony_ci
8491cb0ef41Sopenharmony_ci  Builtin LookUp(Address pc);
8501cb0ef41Sopenharmony_ci  // RISCV decoding routine
8511cb0ef41Sopenharmony_ci  void DecodeRVRType();
8521cb0ef41Sopenharmony_ci  void DecodeRVR4Type();
8531cb0ef41Sopenharmony_ci  void DecodeRVRFPType();  // Special routine for R/OP_FP type
8541cb0ef41Sopenharmony_ci  void DecodeRVRAType();   // Special routine for R/AMO type
8551cb0ef41Sopenharmony_ci  void DecodeRVIType();
8561cb0ef41Sopenharmony_ci  void DecodeRVSType();
8571cb0ef41Sopenharmony_ci  void DecodeRVBType();
8581cb0ef41Sopenharmony_ci  void DecodeRVUType();
8591cb0ef41Sopenharmony_ci  void DecodeRVJType();
8601cb0ef41Sopenharmony_ci  void DecodeCRType();
8611cb0ef41Sopenharmony_ci  void DecodeCAType();
8621cb0ef41Sopenharmony_ci  void DecodeCIType();
8631cb0ef41Sopenharmony_ci  void DecodeCIWType();
8641cb0ef41Sopenharmony_ci  void DecodeCSSType();
8651cb0ef41Sopenharmony_ci  void DecodeCLType();
8661cb0ef41Sopenharmony_ci  void DecodeCSType();
8671cb0ef41Sopenharmony_ci  void DecodeCJType();
8681cb0ef41Sopenharmony_ci  void DecodeCBType();
8691cb0ef41Sopenharmony_ci#ifdef CAN_USE_RVV_INSTRUCTIONS
8701cb0ef41Sopenharmony_ci  void DecodeVType();
8711cb0ef41Sopenharmony_ci  void DecodeRvvIVV();
8721cb0ef41Sopenharmony_ci  void DecodeRvvIVI();
8731cb0ef41Sopenharmony_ci  void DecodeRvvIVX();
8741cb0ef41Sopenharmony_ci  void DecodeRvvMVV();
8751cb0ef41Sopenharmony_ci  void DecodeRvvMVX();
8761cb0ef41Sopenharmony_ci  void DecodeRvvFVV();
8771cb0ef41Sopenharmony_ci  void DecodeRvvFVF();
8781cb0ef41Sopenharmony_ci  bool DecodeRvvVL();
8791cb0ef41Sopenharmony_ci  bool DecodeRvvVS();
8801cb0ef41Sopenharmony_ci#endif
8811cb0ef41Sopenharmony_ci
8821cb0ef41Sopenharmony_ci  // Used for breakpoints and traps.
8831cb0ef41Sopenharmony_ci  void SoftwareInterrupt();
8841cb0ef41Sopenharmony_ci
8851cb0ef41Sopenharmony_ci  // Debug helpers
8861cb0ef41Sopenharmony_ci
8871cb0ef41Sopenharmony_ci  // Simulator breakpoints.
8881cb0ef41Sopenharmony_ci  struct Breakpoint {
8891cb0ef41Sopenharmony_ci    Instruction* location;
8901cb0ef41Sopenharmony_ci    bool enabled;
8911cb0ef41Sopenharmony_ci    bool is_tbreak;
8921cb0ef41Sopenharmony_ci  };
8931cb0ef41Sopenharmony_ci  std::vector<Breakpoint> breakpoints_;
8941cb0ef41Sopenharmony_ci  void SetBreakpoint(Instruction* breakpoint, bool is_tbreak);
8951cb0ef41Sopenharmony_ci  void ListBreakpoints();
8961cb0ef41Sopenharmony_ci  void CheckBreakpoints();
8971cb0ef41Sopenharmony_ci
8981cb0ef41Sopenharmony_ci  // Stop helper functions.
8991cb0ef41Sopenharmony_ci  bool IsWatchpoint(uint64_t code);
9001cb0ef41Sopenharmony_ci  void PrintWatchpoint(uint64_t code);
9011cb0ef41Sopenharmony_ci  void HandleStop(uint64_t code);
9021cb0ef41Sopenharmony_ci  bool IsStopInstruction(Instruction* instr);
9031cb0ef41Sopenharmony_ci  bool IsEnabledStop(uint64_t code);
9041cb0ef41Sopenharmony_ci  void EnableStop(uint64_t code);
9051cb0ef41Sopenharmony_ci  void DisableStop(uint64_t code);
9061cb0ef41Sopenharmony_ci  void IncreaseStopCounter(uint64_t code);
9071cb0ef41Sopenharmony_ci  void PrintStopInfo(uint64_t code);
9081cb0ef41Sopenharmony_ci
9091cb0ef41Sopenharmony_ci  // Executes one instruction.
9101cb0ef41Sopenharmony_ci  void InstructionDecode(Instruction* instr);
9111cb0ef41Sopenharmony_ci
9121cb0ef41Sopenharmony_ci  // ICache.
9131cb0ef41Sopenharmony_ci  static void CheckICache(base::CustomMatcherHashMap* i_cache,
9141cb0ef41Sopenharmony_ci                          Instruction* instr);
9151cb0ef41Sopenharmony_ci  static void FlushOnePage(base::CustomMatcherHashMap* i_cache, intptr_t start,
9161cb0ef41Sopenharmony_ci                           size_t size);
9171cb0ef41Sopenharmony_ci  static CachePage* GetCachePage(base::CustomMatcherHashMap* i_cache,
9181cb0ef41Sopenharmony_ci                                 void* page);
9191cb0ef41Sopenharmony_ci
9201cb0ef41Sopenharmony_ci  enum Exception {
9211cb0ef41Sopenharmony_ci    none,
9221cb0ef41Sopenharmony_ci    kIntegerOverflow,
9231cb0ef41Sopenharmony_ci    kIntegerUnderflow,
9241cb0ef41Sopenharmony_ci    kDivideByZero,
9251cb0ef41Sopenharmony_ci    kNumExceptions,
9261cb0ef41Sopenharmony_ci    // RISCV illegual instruction exception
9271cb0ef41Sopenharmony_ci    kIllegalInstruction,
9281cb0ef41Sopenharmony_ci  };
9291cb0ef41Sopenharmony_ci
9301cb0ef41Sopenharmony_ci  // Exceptions.
9311cb0ef41Sopenharmony_ci  void SignalException(Exception e);
9321cb0ef41Sopenharmony_ci
9331cb0ef41Sopenharmony_ci  // Handle arguments and return value for runtime FP functions.
9341cb0ef41Sopenharmony_ci  void GetFpArgs(double* x, double* y, int32_t* z);
9351cb0ef41Sopenharmony_ci  void SetFpResult(const double& result);
9361cb0ef41Sopenharmony_ci
9371cb0ef41Sopenharmony_ci  void CallInternal(Address entry);
9381cb0ef41Sopenharmony_ci
9391cb0ef41Sopenharmony_ci  // Architecture state.
9401cb0ef41Sopenharmony_ci  // Registers.
9411cb0ef41Sopenharmony_ci  int64_t registers_[kNumSimuRegisters];
9421cb0ef41Sopenharmony_ci  // Coprocessor Registers.
9431cb0ef41Sopenharmony_ci  int64_t FPUregisters_[kNumFPURegisters];
9441cb0ef41Sopenharmony_ci  // Floating-point control and status register.
9451cb0ef41Sopenharmony_ci  uint32_t FCSR_;
9461cb0ef41Sopenharmony_ci
9471cb0ef41Sopenharmony_ci#ifdef CAN_USE_RVV_INSTRUCTIONS
9481cb0ef41Sopenharmony_ci  // RVV registers
9491cb0ef41Sopenharmony_ci  __int128_t Vregister_[kNumVRegisters];
9501cb0ef41Sopenharmony_ci  static_assert(sizeof(__int128_t) == kRvvVLEN / 8, "unmatch vlen");
9511cb0ef41Sopenharmony_ci  uint64_t vstart_, vxsat_, vxrm_, vcsr_, vtype_, vl_, vlenb_;
9521cb0ef41Sopenharmony_ci#endif
9531cb0ef41Sopenharmony_ci  // Simulator support.
9541cb0ef41Sopenharmony_ci  // Allocate 1MB for stack.
9551cb0ef41Sopenharmony_ci  size_t stack_size_;
9561cb0ef41Sopenharmony_ci  char* stack_;
9571cb0ef41Sopenharmony_ci  bool pc_modified_;
9581cb0ef41Sopenharmony_ci  int64_t icount_;
9591cb0ef41Sopenharmony_ci  int break_count_;
9601cb0ef41Sopenharmony_ci  base::EmbeddedVector<char, 256> trace_buf_;
9611cb0ef41Sopenharmony_ci
9621cb0ef41Sopenharmony_ci  // Debugger input.
9631cb0ef41Sopenharmony_ci  char* last_debugger_input_;
9641cb0ef41Sopenharmony_ci
9651cb0ef41Sopenharmony_ci  v8::internal::Isolate* isolate_;
9661cb0ef41Sopenharmony_ci  v8::internal::Builtins builtins_;
9671cb0ef41Sopenharmony_ci
9681cb0ef41Sopenharmony_ci  // Stop is disabled if bit 31 is set.
9691cb0ef41Sopenharmony_ci  static const uint32_t kStopDisabledBit = 1 << 31;
9701cb0ef41Sopenharmony_ci
9711cb0ef41Sopenharmony_ci  // A stop is enabled, meaning the simulator will stop when meeting the
9721cb0ef41Sopenharmony_ci  // instruction, if bit 31 of watched_stops_[code].count is unset.
9731cb0ef41Sopenharmony_ci  // The value watched_stops_[code].count & ~(1 << 31) indicates how many times
9741cb0ef41Sopenharmony_ci  // the breakpoint was hit or gone through.
9751cb0ef41Sopenharmony_ci  struct StopCountAndDesc {
9761cb0ef41Sopenharmony_ci    uint32_t count;
9771cb0ef41Sopenharmony_ci    char* desc;
9781cb0ef41Sopenharmony_ci  };
9791cb0ef41Sopenharmony_ci  StopCountAndDesc watched_stops_[kMaxStopCode + 1];
9801cb0ef41Sopenharmony_ci
9811cb0ef41Sopenharmony_ci  // Synchronization primitives.
9821cb0ef41Sopenharmony_ci  enum class MonitorAccess {
9831cb0ef41Sopenharmony_ci    Open,
9841cb0ef41Sopenharmony_ci    RMW,
9851cb0ef41Sopenharmony_ci  };
9861cb0ef41Sopenharmony_ci
9871cb0ef41Sopenharmony_ci  enum class TransactionSize {
9881cb0ef41Sopenharmony_ci    None = 0,
9891cb0ef41Sopenharmony_ci    Word = 4,
9901cb0ef41Sopenharmony_ci    DoubleWord = 8,
9911cb0ef41Sopenharmony_ci  };
9921cb0ef41Sopenharmony_ci
9931cb0ef41Sopenharmony_ci  // The least-significant bits of the address are ignored. The number of bits
9941cb0ef41Sopenharmony_ci  // is implementation-defined, between 3 and minimum page size.
9951cb0ef41Sopenharmony_ci  static const uintptr_t kExclusiveTaggedAddrMask = ~((1 << 3) - 1);
9961cb0ef41Sopenharmony_ci
9971cb0ef41Sopenharmony_ci  class LocalMonitor {
9981cb0ef41Sopenharmony_ci   public:
9991cb0ef41Sopenharmony_ci    LocalMonitor();
10001cb0ef41Sopenharmony_ci
10011cb0ef41Sopenharmony_ci    // These functions manage the state machine for the local monitor, but do
10021cb0ef41Sopenharmony_ci    // not actually perform loads and stores. NotifyStoreConditional only
10031cb0ef41Sopenharmony_ci    // returns true if the store conditional is allowed; the global monitor will
10041cb0ef41Sopenharmony_ci    // still have to be checked to see whether the memory should be updated.
10051cb0ef41Sopenharmony_ci    void NotifyLoad();
10061cb0ef41Sopenharmony_ci    void NotifyLoadLinked(uintptr_t addr, TransactionSize size);
10071cb0ef41Sopenharmony_ci    void NotifyStore();
10081cb0ef41Sopenharmony_ci    bool NotifyStoreConditional(uintptr_t addr, TransactionSize size);
10091cb0ef41Sopenharmony_ci
10101cb0ef41Sopenharmony_ci   private:
10111cb0ef41Sopenharmony_ci    void Clear();
10121cb0ef41Sopenharmony_ci
10131cb0ef41Sopenharmony_ci    MonitorAccess access_state_;
10141cb0ef41Sopenharmony_ci    uintptr_t tagged_addr_;
10151cb0ef41Sopenharmony_ci    TransactionSize size_;
10161cb0ef41Sopenharmony_ci  };
10171cb0ef41Sopenharmony_ci
10181cb0ef41Sopenharmony_ci  class GlobalMonitor {
10191cb0ef41Sopenharmony_ci   public:
10201cb0ef41Sopenharmony_ci    class LinkedAddress {
10211cb0ef41Sopenharmony_ci     public:
10221cb0ef41Sopenharmony_ci      LinkedAddress();
10231cb0ef41Sopenharmony_ci
10241cb0ef41Sopenharmony_ci     private:
10251cb0ef41Sopenharmony_ci      friend class GlobalMonitor;
10261cb0ef41Sopenharmony_ci      // These functions manage the state machine for the global monitor, but do
10271cb0ef41Sopenharmony_ci      // not actually perform loads and stores.
10281cb0ef41Sopenharmony_ci      void Clear_Locked();
10291cb0ef41Sopenharmony_ci      void NotifyLoadLinked_Locked(uintptr_t addr);
10301cb0ef41Sopenharmony_ci      void NotifyStore_Locked();
10311cb0ef41Sopenharmony_ci      bool NotifyStoreConditional_Locked(uintptr_t addr,
10321cb0ef41Sopenharmony_ci                                         bool is_requesting_thread);
10331cb0ef41Sopenharmony_ci
10341cb0ef41Sopenharmony_ci      MonitorAccess access_state_;
10351cb0ef41Sopenharmony_ci      uintptr_t tagged_addr_;
10361cb0ef41Sopenharmony_ci      LinkedAddress* next_;
10371cb0ef41Sopenharmony_ci      LinkedAddress* prev_;
10381cb0ef41Sopenharmony_ci      // A scd can fail due to background cache evictions. Rather than
10391cb0ef41Sopenharmony_ci      // simulating this, we'll just occasionally introduce cases where an
10401cb0ef41Sopenharmony_ci      // store conditional fails. This will happen once after every
10411cb0ef41Sopenharmony_ci      // kMaxFailureCounter exclusive stores.
10421cb0ef41Sopenharmony_ci      static const int kMaxFailureCounter = 5;
10431cb0ef41Sopenharmony_ci      int failure_counter_;
10441cb0ef41Sopenharmony_ci    };
10451cb0ef41Sopenharmony_ci
10461cb0ef41Sopenharmony_ci    // Exposed so it can be accessed by Simulator::{Read,Write}Ex*.
10471cb0ef41Sopenharmony_ci    base::Mutex mutex;
10481cb0ef41Sopenharmony_ci
10491cb0ef41Sopenharmony_ci    void NotifyLoadLinked_Locked(uintptr_t addr, LinkedAddress* linked_address);
10501cb0ef41Sopenharmony_ci    void NotifyStore_Locked(LinkedAddress* linked_address);
10511cb0ef41Sopenharmony_ci    bool NotifyStoreConditional_Locked(uintptr_t addr,
10521cb0ef41Sopenharmony_ci                                       LinkedAddress* linked_address);
10531cb0ef41Sopenharmony_ci
10541cb0ef41Sopenharmony_ci    // Called when the simulator is destroyed.
10551cb0ef41Sopenharmony_ci    void RemoveLinkedAddress(LinkedAddress* linked_address);
10561cb0ef41Sopenharmony_ci
10571cb0ef41Sopenharmony_ci    static GlobalMonitor* Get();
10581cb0ef41Sopenharmony_ci
10591cb0ef41Sopenharmony_ci   private:
10601cb0ef41Sopenharmony_ci    // Private constructor. Call {GlobalMonitor::Get()} to get the singleton.
10611cb0ef41Sopenharmony_ci    GlobalMonitor() = default;
10621cb0ef41Sopenharmony_ci    friend class base::LeakyObject<GlobalMonitor>;
10631cb0ef41Sopenharmony_ci
10641cb0ef41Sopenharmony_ci    bool IsProcessorInLinkedList_Locked(LinkedAddress* linked_address) const;
10651cb0ef41Sopenharmony_ci    void PrependProcessor_Locked(LinkedAddress* linked_address);
10661cb0ef41Sopenharmony_ci
10671cb0ef41Sopenharmony_ci    LinkedAddress* head_ = nullptr;
10681cb0ef41Sopenharmony_ci  };
10691cb0ef41Sopenharmony_ci
10701cb0ef41Sopenharmony_ci  LocalMonitor local_monitor_;
10711cb0ef41Sopenharmony_ci  GlobalMonitor::LinkedAddress global_monitor_thread_;
10721cb0ef41Sopenharmony_ci};
10731cb0ef41Sopenharmony_ci}  // namespace internal
10741cb0ef41Sopenharmony_ci}  // namespace v8
10751cb0ef41Sopenharmony_ci
10761cb0ef41Sopenharmony_ci#endif  // defined(USE_SIMULATOR)
10771cb0ef41Sopenharmony_ci#endif  // V8_EXECUTION_RISCV64_SIMULATOR_RISCV64_H_
1078