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