diff options
Diffstat (limited to '')
-rw-r--r-- | js/src/jit/riscv64/constant/Base-constant-riscv.cpp | 247 | ||||
-rw-r--r-- | js/src/jit/riscv64/constant/Base-constant-riscv.h | 1057 | ||||
-rw-r--r-- | js/src/jit/riscv64/constant/Constant-riscv-a.h | 43 | ||||
-rw-r--r-- | js/src/jit/riscv64/constant/Constant-riscv-c.h | 61 | ||||
-rw-r--r-- | js/src/jit/riscv64/constant/Constant-riscv-d.h | 55 | ||||
-rw-r--r-- | js/src/jit/riscv64/constant/Constant-riscv-f.h | 51 | ||||
-rw-r--r-- | js/src/jit/riscv64/constant/Constant-riscv-i.h | 73 | ||||
-rw-r--r-- | js/src/jit/riscv64/constant/Constant-riscv-m.h | 34 | ||||
-rw-r--r-- | js/src/jit/riscv64/constant/Constant-riscv-v.h | 508 | ||||
-rw-r--r-- | js/src/jit/riscv64/constant/Constant-riscv-zicsr.h | 30 | ||||
-rw-r--r-- | js/src/jit/riscv64/constant/Constant-riscv-zifencei.h | 15 | ||||
-rw-r--r-- | js/src/jit/riscv64/constant/Constant-riscv64.h | 68 | ||||
-rw-r--r-- | js/src/jit/riscv64/constant/util-riscv64.h | 82 |
13 files changed, 2324 insertions, 0 deletions
diff --git a/js/src/jit/riscv64/constant/Base-constant-riscv.cpp b/js/src/jit/riscv64/constant/Base-constant-riscv.cpp new file mode 100644 index 0000000000..9658689775 --- /dev/null +++ b/js/src/jit/riscv64/constant/Base-constant-riscv.cpp @@ -0,0 +1,247 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "jit/riscv64/constant/Base-constant-riscv.h" + +#include "mozilla/Assertions.h" +#include "mozilla/Types.h" + +#include <stdio.h> + +#include "jit/riscv64/constant/Constant-riscv-c.h" +#include "jit/riscv64/constant/Constant-riscv-d.h" +#include "jit/riscv64/constant/Constant-riscv-f.h" +#include "jit/riscv64/constant/Constant-riscv-i.h" +#include "jit/riscv64/constant/Constant-riscv-m.h" +#include "jit/riscv64/constant/Constant-riscv-v.h" +#include "jit/riscv64/constant/Constant-riscv-zicsr.h" +#include "jit/riscv64/constant/Constant-riscv-zifencei.h" +#include "jit/riscv64/Simulator-riscv64.h" +namespace js { +namespace jit { + +int32_t ImmBranchMaxForwardOffset(OffsetSize bits) { + return (1 << (bits - 1)) - 1; +} + +bool InstructionBase::IsShortInstruction() const { + uint8_t FirstByte = *reinterpret_cast<const uint8_t*>(this); + return (FirstByte & 0x03) <= C2; +} + +template <class T> +int InstructionGetters<T>::RvcRdValue() const { + MOZ_ASSERT(this->IsShortInstruction()); + return this->Bits(kRvcRdShift + kRvcRdBits - 1, kRvcRdShift); +} + +template <class T> +int InstructionGetters<T>::RvcRs2Value() const { + MOZ_ASSERT(this->IsShortInstruction()); + return this->Bits(kRvcRs2Shift + kRvcRs2Bits - 1, kRvcRs2Shift); +} + +template <class T> +int InstructionGetters<T>::RvcRs1sValue() const { + MOZ_ASSERT(this->IsShortInstruction()); + return 0b1000 + this->Bits(kRvcRs1sShift + kRvcRs1sBits - 1, kRvcRs1sShift); +} + +template <class T> +int InstructionGetters<T>::RvcRs2sValue() const { + MOZ_ASSERT(this->IsShortInstruction()); + return 0b1000 + this->Bits(kRvcRs2sShift + kRvcRs2sBits - 1, kRvcRs2sShift); +} + +template <class T> +inline int InstructionGetters<T>::RvcFunct6Value() const { + MOZ_ASSERT(this->IsShortInstruction()); + return this->Bits(kRvcFunct6Shift + kRvcFunct6Bits - 1, kRvcFunct6Shift); +} + +template <class T> +inline int InstructionGetters<T>::RvcFunct4Value() const { + MOZ_ASSERT(this->IsShortInstruction()); + return this->Bits(kRvcFunct4Shift + kRvcFunct4Bits - 1, kRvcFunct4Shift); +} + +template <class T> +inline int InstructionGetters<T>::RvcFunct3Value() const { + MOZ_ASSERT(this->IsShortInstruction()); + return this->Bits(kRvcFunct3Shift + kRvcFunct3Bits - 1, kRvcFunct3Shift); +} + +template <class T> +inline int InstructionGetters<T>::RvcFunct2Value() const { + MOZ_ASSERT(this->IsShortInstruction()); + return this->Bits(kRvcFunct2Shift + kRvcFunct2Bits - 1, kRvcFunct2Shift); +} + +template <class T> +inline int InstructionGetters<T>::RvcFunct2BValue() const { + MOZ_ASSERT(this->IsShortInstruction()); + return this->Bits(kRvcFunct2BShift + kRvcFunct2Bits - 1, kRvcFunct2BShift); +} + +template <class T> +uint32_t InstructionGetters<T>::Rvvzimm() const { + if ((this->InstructionBits() & + (kBaseOpcodeMask | kFunct3Mask | 0x80000000)) == RO_V_VSETVLI) { + uint32_t Bits = this->InstructionBits(); + uint32_t zimm = Bits & kRvvZimmMask; + return zimm >> kRvvZimmShift; + } else { + MOZ_ASSERT((this->InstructionBits() & + (kBaseOpcodeMask | kFunct3Mask | 0xC0000000)) == RO_V_VSETIVLI); + uint32_t Bits = this->InstructionBits(); + uint32_t zimm = Bits & kRvvZimmMask; + return (zimm >> kRvvZimmShift) & 0x3FF; + } +} + +template <class T> +uint32_t InstructionGetters<T>::Rvvuimm() const { + MOZ_ASSERT((this->InstructionBits() & + (kBaseOpcodeMask | kFunct3Mask | 0xC0000000)) == RO_V_VSETIVLI); + uint32_t Bits = this->InstructionBits(); + uint32_t uimm = Bits & kRvvUimmMask; + return uimm >> kRvvUimmShift; +} + +template class InstructionGetters<InstructionBase>; +#ifdef JS_SIMULATOR_RISCV64 +template class InstructionGetters<SimInstructionBase>; +#endif + +OffsetSize InstructionBase::GetOffsetSize() const { + if (IsIllegalInstruction()) { + MOZ_CRASH("IllegalInstruction"); + } + if (IsShortInstruction()) { + switch (InstructionBits() & kRvcOpcodeMask) { + case RO_C_J: + return kOffset11; + case RO_C_BEQZ: + case RO_C_BNEZ: + return kOffset9; + default: + MOZ_CRASH("IllegalInstruction"); + } + } else { + switch (InstructionBits() & kBaseOpcodeMask) { + case BRANCH: + return kOffset13; + case JAL: + return kOffset21; + default: + MOZ_CRASH("IllegalInstruction"); + } + } +} + +InstructionBase::Type InstructionBase::InstructionType() const { + if (IsIllegalInstruction()) { + return kUnsupported; + } + // RV64C Instruction + if (IsShortInstruction()) { + switch (InstructionBits() & kRvcOpcodeMask) { + case RO_C_ADDI4SPN: + return kCIWType; + case RO_C_FLD: + case RO_C_LW: +#ifdef JS_CODEGEN_RISCV64 + case RO_C_LD: +#endif + return kCLType; + case RO_C_FSD: + case RO_C_SW: +#ifdef JS_CODEGEN_RISCV64 + case RO_C_SD: +#endif + return kCSType; + case RO_C_NOP_ADDI: + case RO_C_LI: +#ifdef JS_CODEGEN_RISCV64 + case RO_C_ADDIW: +#endif + case RO_C_LUI_ADD: + return kCIType; + case RO_C_MISC_ALU: + if (Bits(11, 10) != 0b11) + return kCBType; + else + return kCAType; + case RO_C_J: + return kCJType; + case RO_C_BEQZ: + case RO_C_BNEZ: + return kCBType; + case RO_C_SLLI: + case RO_C_FLDSP: + case RO_C_LWSP: +#ifdef JS_CODEGEN_RISCV64 + case RO_C_LDSP: +#endif + return kCIType; + case RO_C_JR_MV_ADD: + return kCRType; + case RO_C_FSDSP: + case RO_C_SWSP: +#ifdef JS_CODEGEN_RISCV64 + case RO_C_SDSP: +#endif + return kCSSType; + default: + break; + } + } else { + // RISCV routine + switch (InstructionBits() & kBaseOpcodeMask) { + case LOAD: + return kIType; + case LOAD_FP: + return kIType; + case MISC_MEM: + return kIType; + case OP_IMM: + return kIType; + case AUIPC: + return kUType; + case OP_IMM_32: + return kIType; + case STORE: + return kSType; + case STORE_FP: + return kSType; + case AMO: + return kRType; + case OP: + return kRType; + case LUI: + return kUType; + case OP_32: + return kRType; + case MADD: + case MSUB: + case NMSUB: + case NMADD: + return kR4Type; + case OP_FP: + return kRType; + case BRANCH: + return kBType; + case JALR: + return kIType; + case JAL: + return kJType; + case SYSTEM: + return kIType; + case OP_V: + return kVType; + } + } + return kUnsupported; +} +} // namespace jit +} // namespace js diff --git a/js/src/jit/riscv64/constant/Base-constant-riscv.h b/js/src/jit/riscv64/constant/Base-constant-riscv.h new file mode 100644 index 0000000000..929ccd67b5 --- /dev/null +++ b/js/src/jit/riscv64/constant/Base-constant-riscv.h @@ -0,0 +1,1057 @@ +// Copyright 2022 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef jit_riscv64_constant_Base_constant_riscv__h_ +#define jit_riscv64_constant_Base_constant_riscv__h_ +namespace js { +namespace jit { + +// On RISC-V Simulator breakpoints can have different codes: +// - Breaks between 0 and kMaxWatchpointCode are treated as simple watchpoints, +// the simulator will run through them and print the registers. +// - Breaks between kMaxWatchpointCode and kMaxStopCode are treated as stop() +// instructions (see Assembler::stop()). +// - Breaks larger than kMaxStopCode are simple breaks, dropping you into the +// debugger. +const uint32_t kMaxTracepointCode = 63; +const uint32_t kMaxWatchpointCode = 31; +const uint32_t kMaxStopCode = 127; +const uint32_t kWasmTrapCode = 6; +static_assert(kMaxWatchpointCode < kMaxStopCode); +static_assert(kMaxTracepointCode < kMaxStopCode); + +// Debug parameters. +// +// For example: +// +// __ Debug(TRACE_ENABLE | LOG_TRACE); +// starts tracing: set v8_flags.trace-sim is true. +// __ Debug(TRACE_ENABLE | LOG_REGS); +// PrintAllregs. +// __ Debug(TRACE_DISABLE | LOG_TRACE); +// stops tracing: set v8_flags.trace-sim is false. +const uint32_t kDebuggerTracingDirectivesMask = 0b111 << 3; +enum DebugParameters : uint32_t { + NO_PARAM = 1 << 5, + BREAK = 1 << 0, + LOG_TRACE = 1 << 1, + LOG_REGS = 1 << 2, + LOG_ALL = LOG_TRACE, + // Trace control. + TRACE_ENABLE = 1 << 3 | NO_PARAM, + TRACE_DISABLE = 1 << 4 | NO_PARAM, +}; +// On RISCV all instructions are 32 bits, except for RVC. +using Instr = int32_t; +using ShortInstr = int16_t; +typedef unsigned char byte; +// ----- Fields offset and length. +// RISCV constants +const int kBaseOpcodeShift = 0; +const int kBaseOpcodeBits = 7; +const int kFunct7Shift = 25; +const int kFunct7Bits = 7; +const int kFunct5Shift = 27; +const int kFunct5Bits = 5; +const int kFunct3Shift = 12; +const int kFunct3Bits = 3; +const int kFunct2Shift = 25; +const int kFunct2Bits = 2; +const int kRs1Shift = 15; +const int kRs1Bits = 5; +const int kVs1Shift = 15; +const int kVs1Bits = 5; +const int kVs2Shift = 20; +const int kVs2Bits = 5; +const int kVdShift = 7; +const int kVdBits = 5; +const int kRs2Shift = 20; +const int kRs2Bits = 5; +const int kRs3Shift = 27; +const int kRs3Bits = 5; +const int kRdShift = 7; +const int kRdBits = 5; +const int kRlShift = 25; +const int kAqShift = 26; +const int kImm12Shift = 20; +const int kImm12Bits = 12; +const int kImm11Shift = 2; +const int kImm11Bits = 11; +const int kShamtShift = 20; +const int kShamtBits = 5; +const int kShamtWShift = 20; +// FIXME: remove this once we have a proper way to handle the wide shift amount +const int kShamtWBits = 6; +const int kArithShiftShift = 30; +const int kImm20Shift = 12; +const int kImm20Bits = 20; +const int kCsrShift = 20; +const int kCsrBits = 12; +const int kMemOrderBits = 4; +const int kPredOrderShift = 24; +const int kSuccOrderShift = 20; + +// for C extension +const int kRvcFunct4Shift = 12; +const int kRvcFunct4Bits = 4; +const int kRvcFunct3Shift = 13; +const int kRvcFunct3Bits = 3; +const int kRvcRs1Shift = 7; +const int kRvcRs1Bits = 5; +const int kRvcRs2Shift = 2; +const int kRvcRs2Bits = 5; +const int kRvcRdShift = 7; +const int kRvcRdBits = 5; +const int kRvcRs1sShift = 7; +const int kRvcRs1sBits = 3; +const int kRvcRs2sShift = 2; +const int kRvcRs2sBits = 3; +const int kRvcFunct2Shift = 5; +const int kRvcFunct2BShift = 10; +const int kRvcFunct2Bits = 2; +const int kRvcFunct6Shift = 10; +const int kRvcFunct6Bits = 6; + +const uint32_t kRvcOpcodeMask = + 0b11 | (((1 << kRvcFunct3Bits) - 1) << kRvcFunct3Shift); +const uint32_t kRvcFunct3Mask = + (((1 << kRvcFunct3Bits) - 1) << kRvcFunct3Shift); +const uint32_t kRvcFunct4Mask = + (((1 << kRvcFunct4Bits) - 1) << kRvcFunct4Shift); +const uint32_t kRvcFunct6Mask = + (((1 << kRvcFunct6Bits) - 1) << kRvcFunct6Shift); +const uint32_t kRvcFunct2Mask = + (((1 << kRvcFunct2Bits) - 1) << kRvcFunct2Shift); +const uint32_t kRvcFunct2BMask = + (((1 << kRvcFunct2Bits) - 1) << kRvcFunct2BShift); +const uint32_t kCRTypeMask = kRvcOpcodeMask | kRvcFunct4Mask; +const uint32_t kCSTypeMask = kRvcOpcodeMask | kRvcFunct6Mask; +const uint32_t kCATypeMask = kRvcOpcodeMask | kRvcFunct6Mask | kRvcFunct2Mask; +const uint32_t kRvcBImm8Mask = (((1 << 5) - 1) << 2) | (((1 << 3) - 1) << 10); + +// RISCV Instruction bit masks +const uint32_t kBaseOpcodeMask = ((1 << kBaseOpcodeBits) - 1) + << kBaseOpcodeShift; +const uint32_t kFunct3Mask = ((1 << kFunct3Bits) - 1) << kFunct3Shift; +const uint32_t kFunct5Mask = ((1 << kFunct5Bits) - 1) << kFunct5Shift; +const uint32_t kFunct7Mask = ((1 << kFunct7Bits) - 1) << kFunct7Shift; +const uint32_t kFunct2Mask = 0b11 << kFunct7Shift; +const uint32_t kRTypeMask = kBaseOpcodeMask | kFunct3Mask | kFunct7Mask; +const uint32_t kRATypeMask = kBaseOpcodeMask | kFunct3Mask | kFunct5Mask; +const uint32_t kRFPTypeMask = kBaseOpcodeMask | kFunct7Mask; +const uint32_t kR4TypeMask = kBaseOpcodeMask | kFunct3Mask | kFunct2Mask; +const uint32_t kITypeMask = kBaseOpcodeMask | kFunct3Mask; +const uint32_t kSTypeMask = kBaseOpcodeMask | kFunct3Mask; +const uint32_t kBTypeMask = kBaseOpcodeMask | kFunct3Mask; +const uint32_t kUTypeMask = kBaseOpcodeMask; +const uint32_t kJTypeMask = kBaseOpcodeMask; +const uint32_t kRs1FieldMask = ((1 << kRs1Bits) - 1) << kRs1Shift; +const uint32_t kRs2FieldMask = ((1 << kRs2Bits) - 1) << kRs2Shift; +const uint32_t kRs3FieldMask = ((1 << kRs3Bits) - 1) << kRs3Shift; +const uint32_t kRdFieldMask = ((1 << kRdBits) - 1) << kRdShift; +const uint32_t kBImm12Mask = kFunct7Mask | kRdFieldMask; +const uint32_t kImm20Mask = ((1 << kImm20Bits) - 1) << kImm20Shift; +const uint32_t kImm12Mask = ((1 << kImm12Bits) - 1) << kImm12Shift; +const uint32_t kImm11Mask = ((1 << kImm11Bits) - 1) << kImm11Shift; +const uint32_t kImm31_12Mask = ((1 << 20) - 1) << 12; +const uint32_t kImm19_0Mask = ((1 << 20) - 1); + +// for RVV extension +#define RVV_LMUL(V) \ + V(m1) \ + V(m2) \ + V(m4) \ + V(m8) \ + V(RESERVERD) \ + V(mf8) \ + V(mf4) \ + V(mf2) + +enum Vlmul { +#define DEFINE_FLAG(name) name, + RVV_LMUL(DEFINE_FLAG) +#undef DEFINE_FLAG +}; + +#define RVV_SEW(V) \ + V(E8) \ + V(E16) \ + V(E32) \ + V(E64) + +#define DEFINE_FLAG(name) name, +enum VSew { + RVV_SEW(DEFINE_FLAG) +#undef DEFINE_FLAG +}; + +constexpr int kRvvELEN = 64; +constexpr int kRvvVLEN = 128; +constexpr int kRvvSLEN = kRvvVLEN; +const int kRvvFunct6Shift = 26; +const int kRvvFunct6Bits = 6; +const uint32_t kRvvFunct6Mask = + (((1 << kRvvFunct6Bits) - 1) << kRvvFunct6Shift); + +const int kRvvVmBits = 1; +const int kRvvVmShift = 25; +const uint32_t kRvvVmMask = (((1 << kRvvVmBits) - 1) << kRvvVmShift); + +const int kRvvVs2Bits = 5; +const int kRvvVs2Shift = 20; +const uint32_t kRvvVs2Mask = (((1 << kRvvVs2Bits) - 1) << kRvvVs2Shift); + +const int kRvvVs1Bits = 5; +const int kRvvVs1Shift = 15; +const uint32_t kRvvVs1Mask = (((1 << kRvvVs1Bits) - 1) << kRvvVs1Shift); + +const int kRvvRs1Bits = kRvvVs1Bits; +const int kRvvRs1Shift = kRvvVs1Shift; +const uint32_t kRvvRs1Mask = (((1 << kRvvRs1Bits) - 1) << kRvvRs1Shift); + +const int kRvvRs2Bits = 5; +const int kRvvRs2Shift = 20; +const uint32_t kRvvRs2Mask = (((1 << kRvvRs2Bits) - 1) << kRvvRs2Shift); + +const int kRvvImm5Bits = kRvvVs1Bits; +const int kRvvImm5Shift = kRvvVs1Shift; +const uint32_t kRvvImm5Mask = (((1 << kRvvImm5Bits) - 1) << kRvvImm5Shift); + +const int kRvvVdBits = 5; +const int kRvvVdShift = 7; +const uint32_t kRvvVdMask = (((1 << kRvvVdBits) - 1) << kRvvVdShift); + +const int kRvvRdBits = kRvvVdBits; +const int kRvvRdShift = kRvvVdShift; +const uint32_t kRvvRdMask = (((1 << kRvvRdBits) - 1) << kRvvRdShift); + +const int kRvvZimmBits = 11; +const int kRvvZimmShift = 20; +const uint32_t kRvvZimmMask = (((1 << kRvvZimmBits) - 1) << kRvvZimmShift); + +const int kRvvUimmShift = kRvvRs1Shift; +const int kRvvUimmBits = kRvvRs1Bits; +const uint32_t kRvvUimmMask = (((1 << kRvvUimmBits) - 1) << kRvvUimmShift); + +const int kRvvWidthBits = 3; +const int kRvvWidthShift = 12; +const uint32_t kRvvWidthMask = (((1 << kRvvWidthBits) - 1) << kRvvWidthShift); + +const int kRvvMopBits = 2; +const int kRvvMopShift = 26; +const uint32_t kRvvMopMask = (((1 << kRvvMopBits) - 1) << kRvvMopShift); + +const int kRvvMewBits = 1; +const int kRvvMewShift = 28; +const uint32_t kRvvMewMask = (((1 << kRvvMewBits) - 1) << kRvvMewShift); + +const int kRvvNfBits = 3; +const int kRvvNfShift = 29; +const uint32_t kRvvNfMask = (((1 << kRvvNfBits) - 1) << kRvvNfShift); + +const int kNopByte = 0x00000013; + +enum BaseOpcode : uint32_t { + LOAD = 0b0000011, // I form: LB LH LW LBU LHU + LOAD_FP = 0b0000111, // I form: FLW FLD FLQ + MISC_MEM = 0b0001111, // I special form: FENCE FENCE.I + OP_IMM = 0b0010011, // I form: ADDI SLTI SLTIU XORI ORI ANDI SLLI SRLI SRAI + // Note: SLLI/SRLI/SRAI I form first, then func3 001/101 => R type + AUIPC = 0b0010111, // U form: AUIPC + OP_IMM_32 = 0b0011011, // I form: ADDIW SLLIW SRLIW SRAIW + // Note: SRLIW SRAIW I form first, then func3 101 special shift encoding + STORE = 0b0100011, // S form: SB SH SW SD + STORE_FP = 0b0100111, // S form: FSW FSD FSQ + AMO = 0b0101111, // R form: All A instructions + OP = 0b0110011, // R: ADD SUB SLL SLT SLTU XOR SRL SRA OR AND and 32M set + LUI = 0b0110111, // U form: LUI + OP_32 = 0b0111011, // R: ADDW SUBW SLLW SRLW SRAW MULW DIVW DIVUW REMW REMUW + MADD = 0b1000011, // R4 type: FMADD.S FMADD.D FMADD.Q + MSUB = 0b1000111, // R4 type: FMSUB.S FMSUB.D FMSUB.Q + NMSUB = 0b1001011, // R4 type: FNMSUB.S FNMSUB.D FNMSUB.Q + NMADD = 0b1001111, // R4 type: FNMADD.S FNMADD.D FNMADD.Q + OP_FP = 0b1010011, // R type: Q ext + BRANCH = 0b1100011, // B form: BEQ BNE, BLT, BGE, BLTU BGEU + JALR = 0b1100111, // I form: JALR + JAL = 0b1101111, // J form: JAL + SYSTEM = 0b1110011, // I form: ECALL EBREAK Zicsr ext + OP_V = 0b1010111, // V form: RVV + + // C extension + C0 = 0b00, + C1 = 0b01, + C2 = 0b10, + FUNCT2_0 = 0b00, + FUNCT2_1 = 0b01, + FUNCT2_2 = 0b10, + FUNCT2_3 = 0b11, +}; + +// ----- Emulated conditions. +// On RISC-V we use this enum to abstract from conditional branch instructions. +// The 'U' prefix is used to specify unsigned comparisons. +// Opposite conditions must be paired as odd/even numbers +// because 'NegateCondition' function flips LSB to negate condition. +enum RiscvCondition { // Any value < 0 is considered no_condition. + overflow = 0, + no_overflow = 1, + Uless = 2, + Ugreater_equal = 3, + Uless_equal = 4, + Ugreater = 5, + equal = 6, + not_equal = 7, // Unordered or Not Equal. + less = 8, + greater_equal = 9, + less_equal = 10, + greater = 11, + cc_always = 12, + + // Aliases. + eq = equal, + ne = not_equal, + ge = greater_equal, + lt = less, + gt = greater, + le = less_equal, + al = cc_always, + ult = Uless, + uge = Ugreater_equal, + ule = Uless_equal, + ugt = Ugreater, +}; + +// ----- Coprocessor conditions. +enum FPUCondition { + kNoFPUCondition = -1, + EQ = 0x02, // Ordered and Equal + NE = 0x03, // Unordered or Not Equal + LT = 0x04, // Ordered and Less Than + GE = 0x05, // Ordered and Greater Than or Equal + LE = 0x06, // Ordered and Less Than or Equal + GT = 0x07, // Ordered and Greater Than +}; + +enum CheckForInexactConversion { + kCheckForInexactConversion, + kDontCheckForInexactConversion +}; + +enum class MaxMinKind : int { kMin = 0, kMax = 1 }; + +// ---------------------------------------------------------------------------- +// RISCV flags + +enum ControlStatusReg { + csr_fflags = 0x001, // Floating-Point Accrued Exceptions (RW) + csr_frm = 0x002, // Floating-Point Dynamic Rounding Mode (RW) + csr_fcsr = 0x003, // Floating-Point Control and Status Register (RW) + csr_cycle = 0xc00, // Cycle counter for RDCYCLE instruction (RO) + csr_time = 0xc01, // Timer for RDTIME instruction (RO) + csr_instret = 0xc02, // Insns-retired counter for RDINSTRET instruction (RO) + csr_cycleh = 0xc80, // Upper 32 bits of cycle, RV32I only (RO) + csr_timeh = 0xc81, // Upper 32 bits of time, RV32I only (RO) + csr_instreth = 0xc82 // Upper 32 bits of instret, RV32I only (RO) +}; + +enum FFlagsMask { + kInvalidOperation = 0b10000, // NV: Invalid + kDivideByZero = 0b1000, // DZ: Divide by Zero + kOverflow = 0b100, // OF: Overflow + kUnderflow = 0b10, // UF: Underflow + kInexact = 0b1 // NX: Inexact +}; + +enum FPURoundingMode { + RNE = 0b000, // Round to Nearest, ties to Even + RTZ = 0b001, // Round towards Zero + RDN = 0b010, // Round Down (towards -infinity) + RUP = 0b011, // Round Up (towards +infinity) + RMM = 0b100, // Round to Nearest, tiest to Max Magnitude + DYN = 0b111 // In instruction's rm field, selects dynamic rounding mode; + // In Rounding Mode register, Invalid +}; + +enum MemoryOdering { + PSI = 0b1000, // PI or SI + PSO = 0b0100, // PO or SO + PSR = 0b0010, // PR or SR + PSW = 0b0001, // PW or SW + PSIORW = PSI | PSO | PSR | PSW +}; + +const int kFloat32ExponentBias = 127; +const int kFloat32MantissaBits = 23; +const int kFloat32ExponentBits = 8; +const int kFloat64ExponentBias = 1023; +const int kFloat64MantissaBits = 52; +const int kFloat64ExponentBits = 11; + +enum FClassFlag { + kNegativeInfinity = 1, + kNegativeNormalNumber = 1 << 1, + kNegativeSubnormalNumber = 1 << 2, + kNegativeZero = 1 << 3, + kPositiveZero = 1 << 4, + kPositiveSubnormalNumber = 1 << 5, + kPositiveNormalNumber = 1 << 6, + kPositiveInfinity = 1 << 7, + kSignalingNaN = 1 << 8, + kQuietNaN = 1 << 9 +}; + +enum OffsetSize : uint32_t { + kOffset21 = 21, // RISCV jal + kOffset12 = 12, // RISCV imm12 + kOffset20 = 20, // RISCV imm20 + kOffset13 = 13, // RISCV branch + kOffset32 = 32, // RISCV auipc + instr_I + kOffset11 = 11, // RISCV C_J + kOffset9 = 9, // RISCV compressed branch +}; + +// The classes of immediate branch ranges, in order of increasing range. +// Note that CondBranchType and CompareBranchType have the same range. +enum ImmBranchRangeType { + CondBranchRangeType, // + UncondBranchRangeType, // + UnknownBranchRangeType, + + // Number of 'short-range' branch range types. + // We don't consider unconditional branches 'short-range'. + NumShortBranchRangeTypes = UnknownBranchRangeType +}; + +inline ImmBranchRangeType OffsetSizeToImmBranchRangeType(OffsetSize bits) { + switch (bits) { + case kOffset21: + return UncondBranchRangeType; + case kOffset13: + return CondBranchRangeType; + default: + MOZ_CRASH("Unimplement"); + } +} + +inline OffsetSize ImmBranchRangeTypeToOffsetSize(ImmBranchRangeType type) { + switch (type) { + case CondBranchRangeType: + return kOffset13; + case UncondBranchRangeType: + return kOffset21; + default: + MOZ_CRASH("Unimplement"); + } +} + +int32_t ImmBranchMaxForwardOffset(OffsetSize bits); + +inline int32_t ImmBranchMaxForwardOffset(ImmBranchRangeType type) { + return ImmBranchMaxForwardOffset(ImmBranchRangeTypeToOffsetSize(type)); +} +// ----------------------------------------------------------------------------- +// Specific instructions, constants, and masks. +// These constants are declared in assembler-riscv64.cc, as they use named +// registers and other constants. + +// An Illegal instruction +const Instr kIllegalInstr = 0; // All other bits are 0s (i.e., ecall) +// An ECALL instruction, used for redirected real time call +const Instr rtCallRedirInstr = SYSTEM; // All other bits are 0s (i.e., ecall) +// An EBreak instruction, used for debugging and semi-hosting +const Instr kBreakInstr = SYSTEM | 1 << kImm12Shift; // ebreak + +constexpr uint8_t kInstrSize = 4; +constexpr uint8_t kShortInstrSize = 2; +constexpr uint8_t kInstrSizeLog2 = 2; + +class InstructionBase { + public: + enum { + // On RISC-V, PC cannot actually be directly accessed. We behave as if PC + // was always the value of the current instruction being executed. + kPCReadOffset = 0 + }; + + // Instruction type. + enum Type { + kRType, + kR4Type, // Special R4 for Q extension + kIType, + kSType, + kBType, + kUType, + kJType, + // C extension + kCRType, + kCIType, + kCSSType, + kCIWType, + kCLType, + kCSType, + kCAType, + kCBType, + kCJType, + // V extension + kVType, + kVLType, + kVSType, + kVAMOType, + kVIVVType, + kVFVVType, + kVMVVType, + kVIVIType, + kVIVXType, + kVFVFType, + kVMVXType, + kVSETType, + kUnsupported = -1 + }; + + inline bool IsIllegalInstruction() const { + uint16_t FirstHalfWord = *reinterpret_cast<const uint16_t*>(this); + return FirstHalfWord == 0; + } + + bool IsShortInstruction() const; + + inline uint8_t InstructionSize() const { + return (this->IsShortInstruction()) ? kShortInstrSize : kInstrSize; + } + + // Get the raw instruction bits. + inline Instr InstructionBits() const { + if (this->IsShortInstruction()) { + return 0x0000FFFF & (*reinterpret_cast<const ShortInstr*>(this)); + } + return *reinterpret_cast<const Instr*>(this); + } + + // Set the raw instruction bits to value. + inline void SetInstructionBits(Instr value) { + *reinterpret_cast<Instr*>(this) = value; + } + + // Read one particular bit out of the instruction bits. + inline int Bit(int nr) const { return (InstructionBits() >> nr) & 1; } + + // Read a bit field out of the instruction bits. + inline int Bits(int hi, int lo) const { + return (InstructionBits() >> lo) & ((2U << (hi - lo)) - 1); + } + + // Accessors for the different named fields used in the RISC-V encoding. + inline BaseOpcode BaseOpcodeValue() const { + return static_cast<BaseOpcode>( + Bits(kBaseOpcodeShift + kBaseOpcodeBits - 1, kBaseOpcodeShift)); + } + + // Return the fields at their original place in the instruction encoding. + inline BaseOpcode BaseOpcodeFieldRaw() const { + return static_cast<BaseOpcode>(InstructionBits() & kBaseOpcodeMask); + } + + // Safe to call within R-type instructions + inline int Funct7FieldRaw() const { return InstructionBits() & kFunct7Mask; } + + // Safe to call within R-, I-, S-, or B-type instructions + inline int Funct3FieldRaw() const { return InstructionBits() & kFunct3Mask; } + + // Safe to call within R-, I-, S-, or B-type instructions + inline int Rs1FieldRawNoAssert() const { + return InstructionBits() & kRs1FieldMask; + } + + // Safe to call within R-, S-, or B-type instructions + inline int Rs2FieldRawNoAssert() const { + return InstructionBits() & kRs2FieldMask; + } + + // Safe to call within R4-type instructions + inline int Rs3FieldRawNoAssert() const { + return InstructionBits() & kRs3FieldMask; + } + + inline int32_t ITypeBits() const { return InstructionBits() & kITypeMask; } + + inline int32_t InstructionOpcodeType() const { + if (IsShortInstruction()) { + return InstructionBits() & kRvcOpcodeMask; + } else { + return InstructionBits() & kBaseOpcodeMask; + } + } + + // Get the encoding type of the instruction. + Type InstructionType() const; + OffsetSize GetOffsetSize() const; + inline ImmBranchRangeType GetImmBranchRangeType() const { + return OffsetSizeToImmBranchRangeType(GetOffsetSize()); + } + + protected: + InstructionBase() {} +}; + +template <class T> +class InstructionGetters : public T { + public: + // Say if the instruction is a break or a trap. + bool IsTrap() const; + + inline int BaseOpcode() const { + return this->InstructionBits() & kBaseOpcodeMask; + } + + inline int RvcOpcode() const { + MOZ_ASSERT(this->IsShortInstruction()); + return this->InstructionBits() & kRvcOpcodeMask; + } + + inline int Rs1Value() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kRType || + this->InstructionType() == InstructionBase::kR4Type || + this->InstructionType() == InstructionBase::kIType || + this->InstructionType() == InstructionBase::kSType || + this->InstructionType() == InstructionBase::kBType || + this->InstructionType() == InstructionBase::kIType || + this->InstructionType() == InstructionBase::kVType); + return this->Bits(kRs1Shift + kRs1Bits - 1, kRs1Shift); + } + + inline int Rs2Value() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kRType || + this->InstructionType() == InstructionBase::kR4Type || + this->InstructionType() == InstructionBase::kSType || + this->InstructionType() == InstructionBase::kBType || + this->InstructionType() == InstructionBase::kIType || + this->InstructionType() == InstructionBase::kVType); + return this->Bits(kRs2Shift + kRs2Bits - 1, kRs2Shift); + } + + inline int Rs3Value() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kR4Type); + return this->Bits(kRs3Shift + kRs3Bits - 1, kRs3Shift); + } + + inline int Vs1Value() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kVType || + this->InstructionType() == InstructionBase::kIType || + this->InstructionType() == InstructionBase::kSType); + return this->Bits(kVs1Shift + kVs1Bits - 1, kVs1Shift); + } + + inline int Vs2Value() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kVType || + this->InstructionType() == InstructionBase::kIType || + this->InstructionType() == InstructionBase::kSType); + return this->Bits(kVs2Shift + kVs2Bits - 1, kVs2Shift); + } + + inline int VdValue() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kVType || + this->InstructionType() == InstructionBase::kIType || + this->InstructionType() == InstructionBase::kSType); + return this->Bits(kVdShift + kVdBits - 1, kVdShift); + } + + inline int RdValue() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kRType || + this->InstructionType() == InstructionBase::kR4Type || + this->InstructionType() == InstructionBase::kIType || + this->InstructionType() == InstructionBase::kSType || + this->InstructionType() == InstructionBase::kUType || + this->InstructionType() == InstructionBase::kJType || + this->InstructionType() == InstructionBase::kVType); + return this->Bits(kRdShift + kRdBits - 1, kRdShift); + } + + inline int RvcRs1Value() const { return this->RvcRdValue(); } + + int RvcRdValue() const; + + int RvcRs2Value() const; + + int RvcRs1sValue() const; + + int RvcRs2sValue() const; + + int Funct7Value() const; + + inline int Funct3Value() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kRType || + this->InstructionType() == InstructionBase::kIType || + this->InstructionType() == InstructionBase::kSType || + this->InstructionType() == InstructionBase::kBType); + return this->Bits(kFunct3Shift + kFunct3Bits - 1, kFunct3Shift); + } + + inline int Funct5Value() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kRType && + this->BaseOpcode() == OP_FP); + return this->Bits(kFunct5Shift + kFunct5Bits - 1, kFunct5Shift); + } + + int RvcFunct6Value() const; + + int RvcFunct4Value() const; + + int RvcFunct3Value() const; + + int RvcFunct2Value() const; + + int RvcFunct2BValue() const; + + inline int CsrValue() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kIType && + this->BaseOpcode() == SYSTEM); + return (this->Bits(kCsrShift + kCsrBits - 1, kCsrShift)); + } + + inline int RoundMode() const { + MOZ_ASSERT((this->InstructionType() == InstructionBase::kRType || + this->InstructionType() == InstructionBase::kR4Type) && + this->BaseOpcode() == OP_FP); + return this->Bits(kFunct3Shift + kFunct3Bits - 1, kFunct3Shift); + } + + inline int MemoryOrder(bool is_pred) const { + MOZ_ASSERT((this->InstructionType() == InstructionBase::kIType && + this->BaseOpcode() == MISC_MEM)); + if (is_pred) { + return this->Bits(kPredOrderShift + kMemOrderBits - 1, kPredOrderShift); + } else { + return this->Bits(kSuccOrderShift + kMemOrderBits - 1, kSuccOrderShift); + } + } + + inline int Imm12Value() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kIType); + int Value = this->Bits(kImm12Shift + kImm12Bits - 1, kImm12Shift); + return Value << 20 >> 20; + } + + inline int32_t Imm12SExtValue() const { + int32_t Value = this->Imm12Value() << 20 >> 20; + return Value; + } + + inline int BranchOffset() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kBType); + // | imm[12|10:5] | rs2 | rs1 | funct3 | imm[4:1|11] | opcode | + // 31 25 11 7 + uint32_t Bits = this->InstructionBits(); + int16_t imm13 = ((Bits & 0xf00) >> 7) | ((Bits & 0x7e000000) >> 20) | + ((Bits & 0x80) << 4) | ((Bits & 0x80000000) >> 19); + return imm13 << 19 >> 19; + } + + inline int StoreOffset() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kSType); + // | imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode | + // 31 25 11 7 + uint32_t Bits = this->InstructionBits(); + int16_t imm12 = ((Bits & 0xf80) >> 7) | ((Bits & 0xfe000000) >> 20); + return imm12 << 20 >> 20; + } + + inline int Imm20UValue() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kUType); + // | imm[31:12] | rd | opcode | + // 31 12 + int32_t Bits = this->InstructionBits(); + return Bits >> 12; + } + + inline int Imm20JValue() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kJType); + // | imm[20|10:1|11|19:12] | rd | opcode | + // 31 12 + uint32_t Bits = this->InstructionBits(); + int32_t imm20 = ((Bits & 0x7fe00000) >> 20) | ((Bits & 0x100000) >> 9) | + (Bits & 0xff000) | ((Bits & 0x80000000) >> 11); + return imm20 << 11 >> 11; + } + + inline bool IsArithShift() const { + // Valid only for right shift operations + MOZ_ASSERT((this->BaseOpcode() == OP || this->BaseOpcode() == OP_32 || + this->BaseOpcode() == OP_IMM || + this->BaseOpcode() == OP_IMM_32) && + this->Funct3Value() == 0b101); + return this->InstructionBits() & 0x40000000; + } + + inline int Shamt() const { + // Valid only for shift instructions (SLLI, SRLI, SRAI) + MOZ_ASSERT((this->InstructionBits() & kBaseOpcodeMask) == OP_IMM && + (this->Funct3Value() == 0b001 || this->Funct3Value() == 0b101)); + // | 0A0000 | shamt | rs1 | funct3 | rd | opcode | + // 31 25 20 + return this->Bits(kImm12Shift + 5, kImm12Shift); + } + + inline int Shamt32() const { + // Valid only for shift instructions (SLLIW, SRLIW, SRAIW) + MOZ_ASSERT((this->InstructionBits() & kBaseOpcodeMask) == OP_IMM_32 && + (this->Funct3Value() == 0b001 || this->Funct3Value() == 0b101)); + // | 0A00000 | shamt | rs1 | funct3 | rd | opcode | + // 31 24 20 + return this->Bits(kImm12Shift + 4, kImm12Shift); + } + + inline int RvcImm6Value() const { + MOZ_ASSERT(this->IsShortInstruction()); + // | funct3 | imm[5] | rs1/rd | imm[4:0] | opcode | + // 15 12 6 2 + uint32_t Bits = this->InstructionBits(); + int32_t imm6 = ((Bits & 0x1000) >> 7) | ((Bits & 0x7c) >> 2); + return imm6 << 26 >> 26; + } + + inline int RvcImm6Addi16spValue() const { + MOZ_ASSERT(this->IsShortInstruction()); + // | funct3 | nzimm[9] | 2 | nzimm[4|6|8:7|5] | opcode | + // 15 12 6 2 + uint32_t Bits = this->InstructionBits(); + int32_t imm10 = ((Bits & 0x1000) >> 3) | ((Bits & 0x40) >> 2) | + ((Bits & 0x20) << 1) | ((Bits & 0x18) << 4) | + ((Bits & 0x4) << 3); + MOZ_ASSERT(imm10 != 0); + return imm10 << 22 >> 22; + } + + inline int RvcImm8Addi4spnValue() const { + MOZ_ASSERT(this->IsShortInstruction()); + // | funct3 | nzimm[11] | rd' | opcode | + // 15 13 5 2 + uint32_t Bits = this->InstructionBits(); + int32_t uimm10 = ((Bits & 0x20) >> 2) | ((Bits & 0x40) >> 4) | + ((Bits & 0x780) >> 1) | ((Bits & 0x1800) >> 7); + MOZ_ASSERT(uimm10 != 0); + return uimm10; + } + + inline int RvcShamt6() const { + MOZ_ASSERT(this->IsShortInstruction()); + // | funct3 | nzuimm[5] | rs1/rd | nzuimm[4:0] | opcode | + // 15 12 6 2 + int32_t imm6 = this->RvcImm6Value(); + return imm6 & 0x3f; + } + + inline int RvcImm6LwspValue() const { + MOZ_ASSERT(this->IsShortInstruction()); + // | funct3 | uimm[5] | rs1 | uimm[4:2|7:6] | opcode | + // 15 12 6 2 + uint32_t Bits = this->InstructionBits(); + int32_t imm8 = + ((Bits & 0x1000) >> 7) | ((Bits & 0x70) >> 2) | ((Bits & 0xc) << 4); + return imm8; + } + + inline int RvcImm6LdspValue() const { + MOZ_ASSERT(this->IsShortInstruction()); + // | funct3 | uimm[5] | rs1 | uimm[4:3|8:6] | opcode | + // 15 12 6 2 + uint32_t Bits = this->InstructionBits(); + int32_t imm9 = + ((Bits & 0x1000) >> 7) | ((Bits & 0x60) >> 2) | ((Bits & 0x1c) << 4); + return imm9; + } + + inline int RvcImm6SwspValue() const { + MOZ_ASSERT(this->IsShortInstruction()); + // | funct3 | uimm[5:2|7:6] | rs2 | opcode | + // 15 12 7 + uint32_t Bits = this->InstructionBits(); + int32_t imm8 = ((Bits & 0x1e00) >> 7) | ((Bits & 0x180) >> 1); + return imm8; + } + + inline int RvcImm6SdspValue() const { + MOZ_ASSERT(this->IsShortInstruction()); + // | funct3 | uimm[5:3|8:6] | rs2 | opcode | + // 15 12 7 + uint32_t Bits = this->InstructionBits(); + int32_t imm9 = ((Bits & 0x1c00) >> 7) | ((Bits & 0x380) >> 1); + return imm9; + } + + inline int RvcImm5WValue() const { + MOZ_ASSERT(this->IsShortInstruction()); + // | funct3 | imm[5:3] | rs1 | imm[2|6] | rd | opcode | + // 15 12 10 6 4 2 + uint32_t Bits = this->InstructionBits(); + int32_t imm7 = + ((Bits & 0x1c00) >> 7) | ((Bits & 0x40) >> 4) | ((Bits & 0x20) << 1); + return imm7; + } + + inline int RvcImm5DValue() const { + MOZ_ASSERT(this->IsShortInstruction()); + // | funct3 | imm[5:3] | rs1 | imm[7:6] | rd | opcode | + // 15 12 10 6 4 2 + uint32_t Bits = this->InstructionBits(); + int32_t imm8 = ((Bits & 0x1c00) >> 7) | ((Bits & 0x60) << 1); + return imm8; + } + + inline int RvcImm11CJValue() const { + MOZ_ASSERT(this->IsShortInstruction()); + // | funct3 | [11|4|9:8|10|6|7|3:1|5] | opcode | + // 15 12 2 + uint32_t Bits = this->InstructionBits(); + int32_t imm12 = ((Bits & 0x4) << 3) | ((Bits & 0x38) >> 2) | + ((Bits & 0x40) << 1) | ((Bits & 0x80) >> 1) | + ((Bits & 0x100) << 2) | ((Bits & 0x600) >> 1) | + ((Bits & 0x800) >> 7) | ((Bits & 0x1000) >> 1); + return imm12 << 20 >> 20; + } + + inline int RvcImm8BValue() const { + MOZ_ASSERT(this->IsShortInstruction()); + // | funct3 | imm[8|4:3] | rs1` | imm[7:6|2:1|5] | opcode | + // 15 12 10 7 2 + uint32_t Bits = this->InstructionBits(); + int32_t imm9 = ((Bits & 0x4) << 3) | ((Bits & 0x18) >> 2) | + ((Bits & 0x60) << 1) | ((Bits & 0xc00) >> 7) | + ((Bits & 0x1000) >> 4); + return imm9 << 23 >> 23; + } + + inline int vl_vs_width() { + int width = 0; + if ((this->InstructionBits() & kBaseOpcodeMask) != LOAD_FP && + (this->InstructionBits() & kBaseOpcodeMask) != STORE_FP) + return -1; + switch (this->InstructionBits() & (kRvvWidthMask | kRvvMewMask)) { + case 0x0: + width = 8; + break; + case 0x00005000: + width = 16; + break; + case 0x00006000: + width = 32; + break; + case 0x00007000: + width = 64; + break; + case 0x10000000: + width = 128; + break; + case 0x10005000: + width = 256; + break; + case 0x10006000: + width = 512; + break; + case 0x10007000: + width = 1024; + break; + default: + width = -1; + break; + } + return width; + } + + uint32_t Rvvzimm() const; + + uint32_t Rvvuimm() const; + + inline uint32_t RvvVsew() const { + uint32_t zimm = this->Rvvzimm(); + uint32_t vsew = (zimm >> 3) & 0x7; + return vsew; + } + + inline uint32_t RvvVlmul() const { + uint32_t zimm = this->Rvvzimm(); + uint32_t vlmul = zimm & 0x7; + return vlmul; + } + + inline uint8_t RvvVM() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kVType || + this->InstructionType() == InstructionBase::kIType || + this->InstructionType() == InstructionBase::kSType); + return this->Bits(kRvvVmShift + kRvvVmBits - 1, kRvvVmShift); + } + + inline const char* RvvSEW() const { + uint32_t vsew = this->RvvVsew(); + switch (vsew) { +#define CAST_VSEW(name) \ + case name: \ + return #name; + RVV_SEW(CAST_VSEW) + default: + return "unknown"; +#undef CAST_VSEW + } + } + + inline const char* RvvLMUL() const { + uint32_t vlmul = this->RvvVlmul(); + switch (vlmul) { +#define CAST_VLMUL(name) \ + case name: \ + return #name; + RVV_LMUL(CAST_VLMUL) + default: + return "unknown"; +#undef CAST_VLMUL + } + } + +#define sext(x, len) (((int32_t)(x) << (32 - len)) >> (32 - len)) +#define zext(x, len) (((uint32_t)(x) << (32 - len)) >> (32 - len)) + + inline int32_t RvvSimm5() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kVType); + return sext(this->Bits(kRvvImm5Shift + kRvvImm5Bits - 1, kRvvImm5Shift), + kRvvImm5Bits); + } + + inline uint32_t RvvUimm5() const { + MOZ_ASSERT(this->InstructionType() == InstructionBase::kVType); + uint32_t imm = this->Bits(kRvvImm5Shift + kRvvImm5Bits - 1, kRvvImm5Shift); + return zext(imm, kRvvImm5Bits); + } +#undef sext +#undef zext + inline bool AqValue() const { return this->Bits(kAqShift, kAqShift); } + + inline bool RlValue() const { return this->Bits(kRlShift, kRlShift); } +}; + +class Instruction : public InstructionGetters<InstructionBase> { + public: + // Instructions are read of out a code stream. The only way to get a + // reference to an instruction is to convert a pointer. There is no way + // to allocate or create instances of class Instruction. + // Use the At(pc) function to create references to Instruction. + static Instruction* At(byte* pc) { + return reinterpret_cast<Instruction*>(pc); + } + + private: + // We need to prevent the creation of instances of class Instruction. + Instruction() = delete; + Instruction(const Instruction&) = delete; + Instruction& operator=(const Instruction&) = delete; +}; + +// ----------------------------------------------------------------------------- +// Instructions. + +template <class P> +bool InstructionGetters<P>::IsTrap() const { + return (this->InstructionBits() == kBreakInstr); +} + +} // namespace jit +} // namespace js +#endif // jit_riscv64_constant_Base_constant_riscv__h_ diff --git a/js/src/jit/riscv64/constant/Constant-riscv-a.h b/js/src/jit/riscv64/constant/Constant-riscv-a.h new file mode 100644 index 0000000000..718e607240 --- /dev/null +++ b/js/src/jit/riscv64/constant/Constant-riscv-a.h @@ -0,0 +1,43 @@ +// Copyright 2022 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef jit_riscv64_constant_Constant_riscv64_a_h_ +#define jit_riscv64_constant_Constant_riscv64_a_h_ + +#include "jit/riscv64/constant/Base-constant-riscv.h" +namespace js { +namespace jit { + +enum OpcodeRISCVA : uint32_t { + // RV32A Standard Extension + RO_LR_W = AMO | (0b010 << kFunct3Shift) | (0b00010 << kFunct5Shift), + RO_SC_W = AMO | (0b010 << kFunct3Shift) | (0b00011 << kFunct5Shift), + RO_AMOSWAP_W = AMO | (0b010 << kFunct3Shift) | (0b00001 << kFunct5Shift), + RO_AMOADD_W = AMO | (0b010 << kFunct3Shift) | (0b00000 << kFunct5Shift), + RO_AMOXOR_W = AMO | (0b010 << kFunct3Shift) | (0b00100 << kFunct5Shift), + RO_AMOAND_W = AMO | (0b010 << kFunct3Shift) | (0b01100 << kFunct5Shift), + RO_AMOOR_W = AMO | (0b010 << kFunct3Shift) | (0b01000 << kFunct5Shift), + RO_AMOMIN_W = AMO | (0b010 << kFunct3Shift) | (0b10000 << kFunct5Shift), + RO_AMOMAX_W = AMO | (0b010 << kFunct3Shift) | (0b10100 << kFunct5Shift), + RO_AMOMINU_W = AMO | (0b010 << kFunct3Shift) | (0b11000 << kFunct5Shift), + RO_AMOMAXU_W = AMO | (0b010 << kFunct3Shift) | (0b11100 << kFunct5Shift), + +#ifdef JS_CODEGEN_RISCV64 + // RV64A Standard Extension (in addition to RV32A) + RO_LR_D = AMO | (0b011 << kFunct3Shift) | (0b00010 << kFunct5Shift), + RO_SC_D = AMO | (0b011 << kFunct3Shift) | (0b00011 << kFunct5Shift), + RO_AMOSWAP_D = AMO | (0b011 << kFunct3Shift) | (0b00001 << kFunct5Shift), + RO_AMOADD_D = AMO | (0b011 << kFunct3Shift) | (0b00000 << kFunct5Shift), + RO_AMOXOR_D = AMO | (0b011 << kFunct3Shift) | (0b00100 << kFunct5Shift), + RO_AMOAND_D = AMO | (0b011 << kFunct3Shift) | (0b01100 << kFunct5Shift), + RO_AMOOR_D = AMO | (0b011 << kFunct3Shift) | (0b01000 << kFunct5Shift), + RO_AMOMIN_D = AMO | (0b011 << kFunct3Shift) | (0b10000 << kFunct5Shift), + RO_AMOMAX_D = AMO | (0b011 << kFunct3Shift) | (0b10100 << kFunct5Shift), + RO_AMOMINU_D = AMO | (0b011 << kFunct3Shift) | (0b11000 << kFunct5Shift), + RO_AMOMAXU_D = AMO | (0b011 << kFunct3Shift) | (0b11100 << kFunct5Shift), +#endif // JS_CODEGEN_RISCV64 +}; +} // namespace jit +} // namespace js + +#endif // jit_riscv64_constant_Constant_riscv64_a_h_ diff --git a/js/src/jit/riscv64/constant/Constant-riscv-c.h b/js/src/jit/riscv64/constant/Constant-riscv-c.h new file mode 100644 index 0000000000..a7d4792f5f --- /dev/null +++ b/js/src/jit/riscv64/constant/Constant-riscv-c.h @@ -0,0 +1,61 @@ +// Copyright 2022 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef jit_riscv64_constant_Constant_riscv64_c_h_ +#define jit_riscv64_constant_Constant_riscv64_c_h_ + +#include "jit/riscv64/constant/Base-constant-riscv.h" +namespace js { +namespace jit { +enum OpcodeRISCVC : uint32_t { + + RO_C_ADDI4SPN = C0 | (0b000 << kRvcFunct3Shift), + RO_C_ADDI16SP = C1 | (0b011 << kRvcFunct3Shift), + RO_C_LW = C0 | (0b010 << kRvcFunct3Shift), + RO_C_SW = C0 | (0b110 << kRvcFunct3Shift), + RO_C_NOP_ADDI = C1 | (0b000 << kRvcFunct3Shift), + RO_C_LI = C1 | (0b010 << kRvcFunct3Shift), + RO_C_SUB = C1 | (0b100011 << kRvcFunct6Shift) | (FUNCT2_0 << kRvcFunct2Shift), + RO_C_XOR = C1 | (0b100011 << kRvcFunct6Shift) | (FUNCT2_1 << kRvcFunct2Shift), + RO_C_OR = C1 | (0b100011 << kRvcFunct6Shift) | (FUNCT2_2 << kRvcFunct2Shift), + RO_C_AND = C1 | (0b100011 << kRvcFunct6Shift) | (FUNCT2_3 << kRvcFunct2Shift), + RO_C_LUI_ADD = C1 | (0b011 << kRvcFunct3Shift), + RO_C_MISC_ALU = C1 | (0b100 << kRvcFunct3Shift), + RO_C_J = C1 | (0b101 << kRvcFunct3Shift), + RO_C_BEQZ = C1 | (0b110 << kRvcFunct3Shift), + RO_C_BNEZ = C1 | (0b111 << kRvcFunct3Shift), + RO_C_SLLI = C2 | (0b000 << kRvcFunct3Shift), + RO_C_LWSP = C2 | (0b010 << kRvcFunct3Shift), + RO_C_JR_MV_ADD = C2 | (0b100 << kRvcFunct3Shift), + RO_C_JR = C2 | (0b1000 << kRvcFunct4Shift), + RO_C_MV = C2 | (0b1000 << kRvcFunct4Shift), + RO_C_EBREAK = C2 | (0b1001 << kRvcFunct4Shift), + RO_C_JALR = C2 | (0b1001 << kRvcFunct4Shift), + RO_C_ADD = C2 | (0b1001 << kRvcFunct4Shift), + RO_C_SWSP = C2 | (0b110 << kRvcFunct3Shift), + + RO_C_FSD = C0 | (0b101 << kRvcFunct3Shift), + RO_C_FLD = C0 | (0b001 << kRvcFunct3Shift), + RO_C_FLDSP = C2 | (0b001 << kRvcFunct3Shift), + RO_C_FSDSP = C2 | (0b101 << kRvcFunct3Shift), +#ifdef JS_CODEGEN_RISCV64 + RO_C_LD = C0 | (0b011 << kRvcFunct3Shift), + RO_C_SD = C0 | (0b111 << kRvcFunct3Shift), + RO_C_LDSP = C2 | (0b011 << kRvcFunct3Shift), + RO_C_SDSP = C2 | (0b111 << kRvcFunct3Shift), + RO_C_ADDIW = C1 | (0b001 << kRvcFunct3Shift), + RO_C_SUBW = + C1 | (0b100111 << kRvcFunct6Shift) | (FUNCT2_0 << kRvcFunct2Shift), + RO_C_ADDW = + C1 | (0b100111 << kRvcFunct6Shift) | (FUNCT2_1 << kRvcFunct2Shift), +#endif +#ifdef JS_CODEGEN_RISCV32 + RO_C_FLWSP = C2 | (0b011 << kRvcFunct3Shift), + RO_C_FSWSP = C2 | (0b111 << kRvcFunct3Shift), + RO_C_FLW = C0 | (0b011 << kRvcFunct3Shift), + RO_C_FSW = C0 | (0b111 << kRvcFunct3Shift), +#endif +}; +} // namespace jit +} // namespace js +#endif // jit_riscv64_constant_Constant_riscv64_c_h_ diff --git a/js/src/jit/riscv64/constant/Constant-riscv-d.h b/js/src/jit/riscv64/constant/Constant-riscv-d.h new file mode 100644 index 0000000000..d97e44ffe5 --- /dev/null +++ b/js/src/jit/riscv64/constant/Constant-riscv-d.h @@ -0,0 +1,55 @@ +// Copyright 2022 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef jit_riscv64_constant_Constant_riscv64_d_h_ +#define jit_riscv64_constant_Constant_riscv64_d_h_ +#include "jit/riscv64/constant/Base-constant-riscv.h" +namespace js { +namespace jit { + +enum OpcodeRISCVD : uint32_t { + // RV32D Standard Extension + RO_FLD = LOAD_FP | (0b011 << kFunct3Shift), + RO_FSD = STORE_FP | (0b011 << kFunct3Shift), + RO_FMADD_D = MADD | (0b01 << kFunct2Shift), + RO_FMSUB_D = MSUB | (0b01 << kFunct2Shift), + RO_FNMSUB_D = NMSUB | (0b01 << kFunct2Shift), + RO_FNMADD_D = NMADD | (0b01 << kFunct2Shift), + RO_FADD_D = OP_FP | (0b0000001 << kFunct7Shift), + RO_FSUB_D = OP_FP | (0b0000101 << kFunct7Shift), + RO_FMUL_D = OP_FP | (0b0001001 << kFunct7Shift), + RO_FDIV_D = OP_FP | (0b0001101 << kFunct7Shift), + RO_FSQRT_D = OP_FP | (0b0101101 << kFunct7Shift) | (0b00000 << kRs2Shift), + RO_FSGNJ_D = OP_FP | (0b000 << kFunct3Shift) | (0b0010001 << kFunct7Shift), + RO_FSGNJN_D = OP_FP | (0b001 << kFunct3Shift) | (0b0010001 << kFunct7Shift), + RO_FSQNJX_D = OP_FP | (0b010 << kFunct3Shift) | (0b0010001 << kFunct7Shift), + RO_FMIN_D = OP_FP | (0b000 << kFunct3Shift) | (0b0010101 << kFunct7Shift), + RO_FMAX_D = OP_FP | (0b001 << kFunct3Shift) | (0b0010101 << kFunct7Shift), + RO_FCVT_S_D = OP_FP | (0b0100000 << kFunct7Shift) | (0b00001 << kRs2Shift), + RO_FCVT_D_S = OP_FP | (0b0100001 << kFunct7Shift) | (0b00000 << kRs2Shift), + RO_FEQ_D = OP_FP | (0b010 << kFunct3Shift) | (0b1010001 << kFunct7Shift), + RO_FLT_D = OP_FP | (0b001 << kFunct3Shift) | (0b1010001 << kFunct7Shift), + RO_FLE_D = OP_FP | (0b000 << kFunct3Shift) | (0b1010001 << kFunct7Shift), + RO_FCLASS_D = OP_FP | (0b001 << kFunct3Shift) | (0b1110001 << kFunct7Shift) | + (0b00000 << kRs2Shift), + RO_FCVT_W_D = OP_FP | (0b1100001 << kFunct7Shift) | (0b00000 << kRs2Shift), + RO_FCVT_WU_D = OP_FP | (0b1100001 << kFunct7Shift) | (0b00001 << kRs2Shift), + RO_FCVT_D_W = OP_FP | (0b1101001 << kFunct7Shift) | (0b00000 << kRs2Shift), + RO_FCVT_D_WU = OP_FP | (0b1101001 << kFunct7Shift) | (0b00001 << kRs2Shift), + +#ifdef JS_CODEGEN_RISCV64 + // RV64D Standard Extension (in addition to RV32D) + RO_FCVT_L_D = OP_FP | (0b1100001 << kFunct7Shift) | (0b00010 << kRs2Shift), + RO_FCVT_LU_D = OP_FP | (0b1100001 << kFunct7Shift) | (0b00011 << kRs2Shift), + RO_FMV_X_D = OP_FP | (0b000 << kFunct3Shift) | (0b1110001 << kFunct7Shift) | + (0b00000 << kRs2Shift), + RO_FCVT_D_L = OP_FP | (0b1101001 << kFunct7Shift) | (0b00010 << kRs2Shift), + RO_FCVT_D_LU = OP_FP | (0b1101001 << kFunct7Shift) | (0b00011 << kRs2Shift), + RO_FMV_D_X = OP_FP | (0b000 << kFunct3Shift) | (0b1111001 << kFunct7Shift) | + (0b00000 << kRs2Shift), +#endif +}; +} // namespace jit +} // namespace js + +#endif // jit_riscv64_constant_Constant_riscv64_a_h_ diff --git a/js/src/jit/riscv64/constant/Constant-riscv-f.h b/js/src/jit/riscv64/constant/Constant-riscv-f.h new file mode 100644 index 0000000000..28c96394e2 --- /dev/null +++ b/js/src/jit/riscv64/constant/Constant-riscv-f.h @@ -0,0 +1,51 @@ +// Copyright 2022 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef jit_riscv64_constant_Constant_riscv64_f_h_ +#define jit_riscv64_constant_Constant_riscv64_f_h_ +#include "jit/riscv64/constant/Base-constant-riscv.h" +namespace js { +namespace jit { + +enum OpcodeRISCVF : uint32_t { + // RV32F Standard Extension + RO_FLW = LOAD_FP | (0b010 << kFunct3Shift), + RO_FSW = STORE_FP | (0b010 << kFunct3Shift), + RO_FMADD_S = MADD | (0b00 << kFunct2Shift), + RO_FMSUB_S = MSUB | (0b00 << kFunct2Shift), + RO_FNMSUB_S = NMSUB | (0b00 << kFunct2Shift), + RO_FNMADD_S = NMADD | (0b00 << kFunct2Shift), + RO_FADD_S = OP_FP | (0b0000000 << kFunct7Shift), + RO_FSUB_S = OP_FP | (0b0000100 << kFunct7Shift), + RO_FMUL_S = OP_FP | (0b0001000 << kFunct7Shift), + RO_FDIV_S = OP_FP | (0b0001100 << kFunct7Shift), + RO_FSQRT_S = OP_FP | (0b0101100 << kFunct7Shift) | (0b00000 << kRs2Shift), + RO_FSGNJ_S = OP_FP | (0b000 << kFunct3Shift) | (0b0010000 << kFunct7Shift), + RO_FSGNJN_S = OP_FP | (0b001 << kFunct3Shift) | (0b0010000 << kFunct7Shift), + RO_FSQNJX_S = OP_FP | (0b010 << kFunct3Shift) | (0b0010000 << kFunct7Shift), + RO_FMIN_S = OP_FP | (0b000 << kFunct3Shift) | (0b0010100 << kFunct7Shift), + RO_FMAX_S = OP_FP | (0b001 << kFunct3Shift) | (0b0010100 << kFunct7Shift), + RO_FCVT_W_S = OP_FP | (0b1100000 << kFunct7Shift) | (0b00000 << kRs2Shift), + RO_FCVT_WU_S = OP_FP | (0b1100000 << kFunct7Shift) | (0b00001 << kRs2Shift), + RO_FMV = OP_FP | (0b1110000 << kFunct7Shift) | (0b000 << kFunct3Shift) | + (0b00000 << kRs2Shift), + RO_FEQ_S = OP_FP | (0b010 << kFunct3Shift) | (0b1010000 << kFunct7Shift), + RO_FLT_S = OP_FP | (0b001 << kFunct3Shift) | (0b1010000 << kFunct7Shift), + RO_FLE_S = OP_FP | (0b000 << kFunct3Shift) | (0b1010000 << kFunct7Shift), + RO_FCLASS_S = OP_FP | (0b001 << kFunct3Shift) | (0b1110000 << kFunct7Shift), + RO_FCVT_S_W = OP_FP | (0b1101000 << kFunct7Shift) | (0b00000 << kRs2Shift), + RO_FCVT_S_WU = OP_FP | (0b1101000 << kFunct7Shift) | (0b00001 << kRs2Shift), + RO_FMV_W_X = OP_FP | (0b000 << kFunct3Shift) | (0b1111000 << kFunct7Shift), + +#ifdef JS_CODEGEN_RISCV64 + // RV64F Standard Extension (in addition to RV32F) + RO_FCVT_L_S = OP_FP | (0b1100000 << kFunct7Shift) | (0b00010 << kRs2Shift), + RO_FCVT_LU_S = OP_FP | (0b1100000 << kFunct7Shift) | (0b00011 << kRs2Shift), + RO_FCVT_S_L = OP_FP | (0b1101000 << kFunct7Shift) | (0b00010 << kRs2Shift), + RO_FCVT_S_LU = OP_FP | (0b1101000 << kFunct7Shift) | (0b00011 << kRs2Shift), +#endif // JS_CODEGEN_RISCV64 +}; +} // namespace jit +} // namespace js + +#endif // jit_riscv64_constant_Constant_riscv64_f_h_ diff --git a/js/src/jit/riscv64/constant/Constant-riscv-i.h b/js/src/jit/riscv64/constant/Constant-riscv-i.h new file mode 100644 index 0000000000..586ffd8a14 --- /dev/null +++ b/js/src/jit/riscv64/constant/Constant-riscv-i.h @@ -0,0 +1,73 @@ +// Copyright 2022 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef jit_riscv64_constant_Constant_riscv64_i_h_ +#define jit_riscv64_constant_Constant_riscv64_i_h_ +#include "jit/riscv64/constant/Base-constant-riscv.h" +namespace js { +namespace jit { + +enum OpcodeRISCV32I : uint32_t { + // Note use RO (RiscV Opcode) prefix + // RV32I Base Instruction Set + RO_LUI = LUI, + RO_AUIPC = AUIPC, + RO_JAL = JAL, + RO_JALR = JALR | (0b000 << kFunct3Shift), + RO_BEQ = BRANCH | (0b000 << kFunct3Shift), + RO_BNE = BRANCH | (0b001 << kFunct3Shift), + RO_BLT = BRANCH | (0b100 << kFunct3Shift), + RO_BGE = BRANCH | (0b101 << kFunct3Shift), + RO_BLTU = BRANCH | (0b110 << kFunct3Shift), + RO_BGEU = BRANCH | (0b111 << kFunct3Shift), + RO_LB = LOAD | (0b000 << kFunct3Shift), + RO_LH = LOAD | (0b001 << kFunct3Shift), + RO_LW = LOAD | (0b010 << kFunct3Shift), + RO_LBU = LOAD | (0b100 << kFunct3Shift), + RO_LHU = LOAD | (0b101 << kFunct3Shift), + RO_SB = STORE | (0b000 << kFunct3Shift), + RO_SH = STORE | (0b001 << kFunct3Shift), + RO_SW = STORE | (0b010 << kFunct3Shift), + RO_ADDI = OP_IMM | (0b000 << kFunct3Shift), + RO_SLTI = OP_IMM | (0b010 << kFunct3Shift), + RO_SLTIU = OP_IMM | (0b011 << kFunct3Shift), + RO_XORI = OP_IMM | (0b100 << kFunct3Shift), + RO_ORI = OP_IMM | (0b110 << kFunct3Shift), + RO_ANDI = OP_IMM | (0b111 << kFunct3Shift), + RO_SLLI = OP_IMM | (0b001 << kFunct3Shift), + RO_SRLI = OP_IMM | (0b101 << kFunct3Shift), + // RO_SRAI = OP_IMM | (0b101 << kFunct3Shift), // Same as SRLI, use func7 + RO_ADD = OP | (0b000 << kFunct3Shift) | (0b0000000 << kFunct7Shift), + RO_SUB = OP | (0b000 << kFunct3Shift) | (0b0100000 << kFunct7Shift), + RO_SLL = OP | (0b001 << kFunct3Shift) | (0b0000000 << kFunct7Shift), + RO_SLT = OP | (0b010 << kFunct3Shift) | (0b0000000 << kFunct7Shift), + RO_SLTU = OP | (0b011 << kFunct3Shift) | (0b0000000 << kFunct7Shift), + RO_XOR = OP | (0b100 << kFunct3Shift) | (0b0000000 << kFunct7Shift), + RO_SRL = OP | (0b101 << kFunct3Shift) | (0b0000000 << kFunct7Shift), + RO_SRA = OP | (0b101 << kFunct3Shift) | (0b0100000 << kFunct7Shift), + RO_OR = OP | (0b110 << kFunct3Shift) | (0b0000000 << kFunct7Shift), + RO_AND = OP | (0b111 << kFunct3Shift) | (0b0000000 << kFunct7Shift), + RO_FENCE = MISC_MEM | (0b000 << kFunct3Shift), + RO_ECALL = SYSTEM | (0b000 << kFunct3Shift), +// RO_EBREAK = SYSTEM | (0b000 << kFunct3Shift), // Same as ECALL, use imm12 + +#if JS_CODEGEN_RISCV64 + // RV64I Base Instruction Set (in addition to RV32I) + RO_LWU = LOAD | (0b110 << kFunct3Shift), + RO_LD = LOAD | (0b011 << kFunct3Shift), + RO_SD = STORE | (0b011 << kFunct3Shift), + RO_ADDIW = OP_IMM_32 | (0b000 << kFunct3Shift), + RO_SLLIW = OP_IMM_32 | (0b001 << kFunct3Shift), + RO_SRLIW = OP_IMM_32 | (0b101 << kFunct3Shift), + // RO_SRAIW = OP_IMM_32 | (0b101 << kFunct3Shift), // Same as SRLIW, use func7 + RO_ADDW = OP_32 | (0b000 << kFunct3Shift) | (0b0000000 << kFunct7Shift), + RO_SUBW = OP_32 | (0b000 << kFunct3Shift) | (0b0100000 << kFunct7Shift), + RO_SLLW = OP_32 | (0b001 << kFunct3Shift) | (0b0000000 << kFunct7Shift), + RO_SRLW = OP_32 | (0b101 << kFunct3Shift) | (0b0000000 << kFunct7Shift), + RO_SRAW = OP_32 | (0b101 << kFunct3Shift) | (0b0100000 << kFunct7Shift), +#endif +}; +} // namespace jit +} // namespace js + +#endif // jit_riscv64_constant_Constant_riscv64_i_h_ diff --git a/js/src/jit/riscv64/constant/Constant-riscv-m.h b/js/src/jit/riscv64/constant/Constant-riscv-m.h new file mode 100644 index 0000000000..81a69dab41 --- /dev/null +++ b/js/src/jit/riscv64/constant/Constant-riscv-m.h @@ -0,0 +1,34 @@ +// Copyright 2022 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef jit_riscv64_constant_Constant_riscv64_m_h_ +#define jit_riscv64_constant_Constant_riscv64_m_h_ + +#include "jit/riscv64/constant/Base-constant-riscv.h" +namespace js { +namespace jit { + +enum OpcodeRISCVM : uint32_t { + // RV32M Standard Extension + RO_MUL = OP | (0b000 << kFunct3Shift) | (0b0000001 << kFunct7Shift), + RO_MULH = OP | (0b001 << kFunct3Shift) | (0b0000001 << kFunct7Shift), + RO_MULHSU = OP | (0b010 << kFunct3Shift) | (0b0000001 << kFunct7Shift), + RO_MULHU = OP | (0b011 << kFunct3Shift) | (0b0000001 << kFunct7Shift), + RO_DIV = OP | (0b100 << kFunct3Shift) | (0b0000001 << kFunct7Shift), + RO_DIVU = OP | (0b101 << kFunct3Shift) | (0b0000001 << kFunct7Shift), + RO_REM = OP | (0b110 << kFunct3Shift) | (0b0000001 << kFunct7Shift), + RO_REMU = OP | (0b111 << kFunct3Shift) | (0b0000001 << kFunct7Shift), + +#ifdef JS_CODEGEN_RISCV64 + // RV64M Standard Extension (in addition to RV32M) + RO_MULW = OP_32 | (0b000 << kFunct3Shift) | (0b0000001 << kFunct7Shift), + RO_DIVW = OP_32 | (0b100 << kFunct3Shift) | (0b0000001 << kFunct7Shift), + RO_DIVUW = OP_32 | (0b101 << kFunct3Shift) | (0b0000001 << kFunct7Shift), + RO_REMW = OP_32 | (0b110 << kFunct3Shift) | (0b0000001 << kFunct7Shift), + RO_REMUW = OP_32 | (0b111 << kFunct3Shift) | (0b0000001 << kFunct7Shift), +#endif +}; +} // namespace jit +} // namespace js + +#endif // jit_riscv64_extension_CONSTANT_RISCV_M_h_ diff --git a/js/src/jit/riscv64/constant/Constant-riscv-v.h b/js/src/jit/riscv64/constant/Constant-riscv-v.h new file mode 100644 index 0000000000..cca3540efd --- /dev/null +++ b/js/src/jit/riscv64/constant/Constant-riscv-v.h @@ -0,0 +1,508 @@ +// Copyright 2022 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef jit_riscv64_constant_Constant_riscv64_v_h_ +#define jit_riscv64_constant_Constant_riscv64_v_h_ +#include "jit/riscv64/constant/Base-constant-riscv.h" +namespace js { +namespace jit { + +namespace RVV { +enum TailAgnosticType { + ta = 0x1, // Tail agnostic + tu = 0x0, // Tail undisturbed +}; + +enum MaskAgnosticType { + ma = 0x1, // Mask agnostic + mu = 0x0, // Mask undisturbed +}; +enum MaskType { + Mask = 0x0, // use the mask + NoMask = 0x1, +}; +} // namespace RVV + +enum OpcodeRISCVV : uint32_t { + // RVV Extension + OP_IVV = OP_V | (0b000 << kFunct3Shift), + OP_FVV = OP_V | (0b001 << kFunct3Shift), + OP_MVV = OP_V | (0b010 << kFunct3Shift), + OP_IVI = OP_V | (0b011 << kFunct3Shift), + OP_IVX = OP_V | (0b100 << kFunct3Shift), + OP_FVF = OP_V | (0b101 << kFunct3Shift), + OP_MVX = OP_V | (0b110 << kFunct3Shift), + + RO_V_VSETVLI = OP_V | (0b111 << kFunct3Shift) | 0b0 << 31, + RO_V_VSETIVLI = OP_V | (0b111 << kFunct3Shift) | 0b11 << 30, + RO_V_VSETVL = OP_V | (0b111 << kFunct3Shift) | 0b1 << 31, + + // RVV LOAD/STORE + RO_V_VL = LOAD_FP | (0b00 << kRvvMopShift) | (0b000 << kRvvNfShift), + RO_V_VLS = LOAD_FP | (0b10 << kRvvMopShift) | (0b000 << kRvvNfShift), + RO_V_VLX = LOAD_FP | (0b11 << kRvvMopShift) | (0b000 << kRvvNfShift), + + RO_V_VS = STORE_FP | (0b00 << kRvvMopShift) | (0b000 << kRvvNfShift), + RO_V_VSS = STORE_FP | (0b10 << kRvvMopShift) | (0b000 << kRvvNfShift), + RO_V_VSX = STORE_FP | (0b11 << kRvvMopShift) | (0b000 << kRvvNfShift), + RO_V_VSU = STORE_FP | (0b01 << kRvvMopShift) | (0b000 << kRvvNfShift), + // THE kFunct6Shift is mop + RO_V_VLSEG2 = LOAD_FP | (0b00 << kRvvMopShift) | (0b001 << kRvvNfShift), + RO_V_VLSEG3 = LOAD_FP | (0b00 << kRvvMopShift) | (0b010 << kRvvNfShift), + RO_V_VLSEG4 = LOAD_FP | (0b00 << kRvvMopShift) | (0b011 << kRvvNfShift), + RO_V_VLSEG5 = LOAD_FP | (0b00 << kRvvMopShift) | (0b100 << kRvvNfShift), + RO_V_VLSEG6 = LOAD_FP | (0b00 << kRvvMopShift) | (0b101 << kRvvNfShift), + RO_V_VLSEG7 = LOAD_FP | (0b00 << kRvvMopShift) | (0b110 << kRvvNfShift), + RO_V_VLSEG8 = LOAD_FP | (0b00 << kRvvMopShift) | (0b111 << kRvvNfShift), + + RO_V_VSSEG2 = STORE_FP | (0b00 << kRvvMopShift) | (0b001 << kRvvNfShift), + RO_V_VSSEG3 = STORE_FP | (0b00 << kRvvMopShift) | (0b010 << kRvvNfShift), + RO_V_VSSEG4 = STORE_FP | (0b00 << kRvvMopShift) | (0b011 << kRvvNfShift), + RO_V_VSSEG5 = STORE_FP | (0b00 << kRvvMopShift) | (0b100 << kRvvNfShift), + RO_V_VSSEG6 = STORE_FP | (0b00 << kRvvMopShift) | (0b101 << kRvvNfShift), + RO_V_VSSEG7 = STORE_FP | (0b00 << kRvvMopShift) | (0b110 << kRvvNfShift), + RO_V_VSSEG8 = STORE_FP | (0b00 << kRvvMopShift) | (0b111 << kRvvNfShift), + + RO_V_VLSSEG2 = LOAD_FP | (0b10 << kRvvMopShift) | (0b001 << kRvvNfShift), + RO_V_VLSSEG3 = LOAD_FP | (0b10 << kRvvMopShift) | (0b010 << kRvvNfShift), + RO_V_VLSSEG4 = LOAD_FP | (0b10 << kRvvMopShift) | (0b011 << kRvvNfShift), + RO_V_VLSSEG5 = LOAD_FP | (0b10 << kRvvMopShift) | (0b100 << kRvvNfShift), + RO_V_VLSSEG6 = LOAD_FP | (0b10 << kRvvMopShift) | (0b101 << kRvvNfShift), + RO_V_VLSSEG7 = LOAD_FP | (0b10 << kRvvMopShift) | (0b110 << kRvvNfShift), + RO_V_VLSSEG8 = LOAD_FP | (0b10 << kRvvMopShift) | (0b111 << kRvvNfShift), + + RO_V_VSSSEG2 = STORE_FP | (0b10 << kRvvMopShift) | (0b001 << kRvvNfShift), + RO_V_VSSSEG3 = STORE_FP | (0b10 << kRvvMopShift) | (0b010 << kRvvNfShift), + RO_V_VSSSEG4 = STORE_FP | (0b10 << kRvvMopShift) | (0b011 << kRvvNfShift), + RO_V_VSSSEG5 = STORE_FP | (0b10 << kRvvMopShift) | (0b100 << kRvvNfShift), + RO_V_VSSSEG6 = STORE_FP | (0b10 << kRvvMopShift) | (0b101 << kRvvNfShift), + RO_V_VSSSEG7 = STORE_FP | (0b10 << kRvvMopShift) | (0b110 << kRvvNfShift), + RO_V_VSSSEG8 = STORE_FP | (0b10 << kRvvMopShift) | (0b111 << kRvvNfShift), + + RO_V_VLXSEG2 = LOAD_FP | (0b11 << kRvvMopShift) | (0b001 << kRvvNfShift), + RO_V_VLXSEG3 = LOAD_FP | (0b11 << kRvvMopShift) | (0b010 << kRvvNfShift), + RO_V_VLXSEG4 = LOAD_FP | (0b11 << kRvvMopShift) | (0b011 << kRvvNfShift), + RO_V_VLXSEG5 = LOAD_FP | (0b11 << kRvvMopShift) | (0b100 << kRvvNfShift), + RO_V_VLXSEG6 = LOAD_FP | (0b11 << kRvvMopShift) | (0b101 << kRvvNfShift), + RO_V_VLXSEG7 = LOAD_FP | (0b11 << kRvvMopShift) | (0b110 << kRvvNfShift), + RO_V_VLXSEG8 = LOAD_FP | (0b11 << kRvvMopShift) | (0b111 << kRvvNfShift), + + RO_V_VSXSEG2 = STORE_FP | (0b11 << kRvvMopShift) | (0b001 << kRvvNfShift), + RO_V_VSXSEG3 = STORE_FP | (0b11 << kRvvMopShift) | (0b010 << kRvvNfShift), + RO_V_VSXSEG4 = STORE_FP | (0b11 << kRvvMopShift) | (0b011 << kRvvNfShift), + RO_V_VSXSEG5 = STORE_FP | (0b11 << kRvvMopShift) | (0b100 << kRvvNfShift), + RO_V_VSXSEG6 = STORE_FP | (0b11 << kRvvMopShift) | (0b101 << kRvvNfShift), + RO_V_VSXSEG7 = STORE_FP | (0b11 << kRvvMopShift) | (0b110 << kRvvNfShift), + RO_V_VSXSEG8 = STORE_FP | (0b11 << kRvvMopShift) | (0b111 << kRvvNfShift), + + // RVV Vector Arithmetic Instruction + VADD_FUNCT6 = 0b000000, + RO_V_VADD_VI = OP_IVI | (VADD_FUNCT6 << kRvvFunct6Shift), + RO_V_VADD_VV = OP_IVV | (VADD_FUNCT6 << kRvvFunct6Shift), + RO_V_VADD_VX = OP_IVX | (VADD_FUNCT6 << kRvvFunct6Shift), + + VSUB_FUNCT6 = 0b000010, + RO_V_VSUB_VX = OP_IVX | (VSUB_FUNCT6 << kRvvFunct6Shift), + RO_V_VSUB_VV = OP_IVV | (VSUB_FUNCT6 << kRvvFunct6Shift), + + VDIVU_FUNCT6 = 0b100000, + RO_V_VDIVU_VX = OP_MVX | (VDIVU_FUNCT6 << kRvvFunct6Shift), + RO_V_VDIVU_VV = OP_MVV | (VDIVU_FUNCT6 << kRvvFunct6Shift), + + VDIV_FUNCT6 = 0b100001, + RO_V_VDIV_VX = OP_MVX | (VDIV_FUNCT6 << kRvvFunct6Shift), + RO_V_VDIV_VV = OP_MVV | (VDIV_FUNCT6 << kRvvFunct6Shift), + + VREMU_FUNCT6 = 0b100010, + RO_V_VREMU_VX = OP_MVX | (VREMU_FUNCT6 << kRvvFunct6Shift), + RO_V_VREMU_VV = OP_MVV | (VREMU_FUNCT6 << kRvvFunct6Shift), + + VREM_FUNCT6 = 0b100011, + RO_V_VREM_VX = OP_MVX | (VREM_FUNCT6 << kRvvFunct6Shift), + RO_V_VREM_VV = OP_MVV | (VREM_FUNCT6 << kRvvFunct6Shift), + + VMULHU_FUNCT6 = 0b100100, + RO_V_VMULHU_VX = OP_MVX | (VMULHU_FUNCT6 << kRvvFunct6Shift), + RO_V_VMULHU_VV = OP_MVV | (VMULHU_FUNCT6 << kRvvFunct6Shift), + + VMUL_FUNCT6 = 0b100101, + RO_V_VMUL_VX = OP_MVX | (VMUL_FUNCT6 << kRvvFunct6Shift), + RO_V_VMUL_VV = OP_MVV | (VMUL_FUNCT6 << kRvvFunct6Shift), + + VWMUL_FUNCT6 = 0b111011, + RO_V_VWMUL_VX = OP_MVX | (VWMUL_FUNCT6 << kRvvFunct6Shift), + RO_V_VWMUL_VV = OP_MVV | (VWMUL_FUNCT6 << kRvvFunct6Shift), + + VWMULU_FUNCT6 = 0b111000, + RO_V_VWMULU_VX = OP_MVX | (VWMULU_FUNCT6 << kRvvFunct6Shift), + RO_V_VWMULU_VV = OP_MVV | (VWMULU_FUNCT6 << kRvvFunct6Shift), + + VMULHSU_FUNCT6 = 0b100110, + RO_V_VMULHSU_VX = OP_MVX | (VMULHSU_FUNCT6 << kRvvFunct6Shift), + RO_V_VMULHSU_VV = OP_MVV | (VMULHSU_FUNCT6 << kRvvFunct6Shift), + + VMULH_FUNCT6 = 0b100111, + RO_V_VMULH_VX = OP_MVX | (VMULH_FUNCT6 << kRvvFunct6Shift), + RO_V_VMULH_VV = OP_MVV | (VMULH_FUNCT6 << kRvvFunct6Shift), + + VWADD_FUNCT6 = 0b110001, + RO_V_VWADD_VV = OP_MVV | (VWADD_FUNCT6 << kRvvFunct6Shift), + RO_V_VWADD_VX = OP_MVX | (VWADD_FUNCT6 << kRvvFunct6Shift), + + VWADDU_FUNCT6 = 0b110000, + RO_V_VWADDU_VV = OP_MVV | (VWADDU_FUNCT6 << kRvvFunct6Shift), + RO_V_VWADDU_VX = OP_MVX | (VWADDU_FUNCT6 << kRvvFunct6Shift), + + VWADDUW_FUNCT6 = 0b110101, + RO_V_VWADDUW_VX = OP_MVX | (VWADDUW_FUNCT6 << kRvvFunct6Shift), + RO_V_VWADDUW_VV = OP_MVV | (VWADDUW_FUNCT6 << kRvvFunct6Shift), + + VCOMPRESS_FUNCT6 = 0b010111, + RO_V_VCOMPRESS_VV = OP_MVV | (VCOMPRESS_FUNCT6 << kRvvFunct6Shift), + + VSADDU_FUNCT6 = 0b100000, + RO_V_VSADDU_VI = OP_IVI | (VSADDU_FUNCT6 << kRvvFunct6Shift), + RO_V_VSADDU_VV = OP_IVV | (VSADDU_FUNCT6 << kRvvFunct6Shift), + RO_V_VSADDU_VX = OP_IVX | (VSADDU_FUNCT6 << kRvvFunct6Shift), + + VSADD_FUNCT6 = 0b100001, + RO_V_VSADD_VI = OP_IVI | (VSADD_FUNCT6 << kRvvFunct6Shift), + RO_V_VSADD_VV = OP_IVV | (VSADD_FUNCT6 << kRvvFunct6Shift), + RO_V_VSADD_VX = OP_IVX | (VSADD_FUNCT6 << kRvvFunct6Shift), + + VSSUB_FUNCT6 = 0b100011, + RO_V_VSSUB_VV = OP_IVV | (VSSUB_FUNCT6 << kRvvFunct6Shift), + RO_V_VSSUB_VX = OP_IVX | (VSSUB_FUNCT6 << kRvvFunct6Shift), + + VSSUBU_FUNCT6 = 0b100010, + RO_V_VSSUBU_VV = OP_IVV | (VSSUBU_FUNCT6 << kRvvFunct6Shift), + RO_V_VSSUBU_VX = OP_IVX | (VSSUBU_FUNCT6 << kRvvFunct6Shift), + + VRSUB_FUNCT6 = 0b000011, + RO_V_VRSUB_VX = OP_IVX | (VRSUB_FUNCT6 << kRvvFunct6Shift), + RO_V_VRSUB_VI = OP_IVI | (VRSUB_FUNCT6 << kRvvFunct6Shift), + + VMINU_FUNCT6 = 0b000100, + RO_V_VMINU_VX = OP_IVX | (VMINU_FUNCT6 << kRvvFunct6Shift), + RO_V_VMINU_VV = OP_IVV | (VMINU_FUNCT6 << kRvvFunct6Shift), + + VMIN_FUNCT6 = 0b000101, + RO_V_VMIN_VX = OP_IVX | (VMIN_FUNCT6 << kRvvFunct6Shift), + RO_V_VMIN_VV = OP_IVV | (VMIN_FUNCT6 << kRvvFunct6Shift), + + VMAXU_FUNCT6 = 0b000110, + RO_V_VMAXU_VX = OP_IVX | (VMAXU_FUNCT6 << kRvvFunct6Shift), + RO_V_VMAXU_VV = OP_IVV | (VMAXU_FUNCT6 << kRvvFunct6Shift), + + VMAX_FUNCT6 = 0b000111, + RO_V_VMAX_VX = OP_IVX | (VMAX_FUNCT6 << kRvvFunct6Shift), + RO_V_VMAX_VV = OP_IVV | (VMAX_FUNCT6 << kRvvFunct6Shift), + + VAND_FUNCT6 = 0b001001, + RO_V_VAND_VI = OP_IVI | (VAND_FUNCT6 << kRvvFunct6Shift), + RO_V_VAND_VV = OP_IVV | (VAND_FUNCT6 << kRvvFunct6Shift), + RO_V_VAND_VX = OP_IVX | (VAND_FUNCT6 << kRvvFunct6Shift), + + VOR_FUNCT6 = 0b001010, + RO_V_VOR_VI = OP_IVI | (VOR_FUNCT6 << kRvvFunct6Shift), + RO_V_VOR_VV = OP_IVV | (VOR_FUNCT6 << kRvvFunct6Shift), + RO_V_VOR_VX = OP_IVX | (VOR_FUNCT6 << kRvvFunct6Shift), + + VXOR_FUNCT6 = 0b001011, + RO_V_VXOR_VI = OP_IVI | (VXOR_FUNCT6 << kRvvFunct6Shift), + RO_V_VXOR_VV = OP_IVV | (VXOR_FUNCT6 << kRvvFunct6Shift), + RO_V_VXOR_VX = OP_IVX | (VXOR_FUNCT6 << kRvvFunct6Shift), + + VRGATHER_FUNCT6 = 0b001100, + RO_V_VRGATHER_VI = OP_IVI | (VRGATHER_FUNCT6 << kRvvFunct6Shift), + RO_V_VRGATHER_VV = OP_IVV | (VRGATHER_FUNCT6 << kRvvFunct6Shift), + RO_V_VRGATHER_VX = OP_IVX | (VRGATHER_FUNCT6 << kRvvFunct6Shift), + + VMV_FUNCT6 = 0b010111, + RO_V_VMV_VI = OP_IVI | (VMV_FUNCT6 << kRvvFunct6Shift), + RO_V_VMV_VV = OP_IVV | (VMV_FUNCT6 << kRvvFunct6Shift), + RO_V_VMV_VX = OP_IVX | (VMV_FUNCT6 << kRvvFunct6Shift), + RO_V_VFMV_VF = OP_FVF | (VMV_FUNCT6 << kRvvFunct6Shift), + + RO_V_VMERGE_VI = RO_V_VMV_VI, + RO_V_VMERGE_VV = RO_V_VMV_VV, + RO_V_VMERGE_VX = RO_V_VMV_VX, + + VMSEQ_FUNCT6 = 0b011000, + RO_V_VMSEQ_VI = OP_IVI | (VMSEQ_FUNCT6 << kRvvFunct6Shift), + RO_V_VMSEQ_VV = OP_IVV | (VMSEQ_FUNCT6 << kRvvFunct6Shift), + RO_V_VMSEQ_VX = OP_IVX | (VMSEQ_FUNCT6 << kRvvFunct6Shift), + + VMSNE_FUNCT6 = 0b011001, + RO_V_VMSNE_VI = OP_IVI | (VMSNE_FUNCT6 << kRvvFunct6Shift), + RO_V_VMSNE_VV = OP_IVV | (VMSNE_FUNCT6 << kRvvFunct6Shift), + RO_V_VMSNE_VX = OP_IVX | (VMSNE_FUNCT6 << kRvvFunct6Shift), + + VMSLTU_FUNCT6 = 0b011010, + RO_V_VMSLTU_VV = OP_IVV | (VMSLTU_FUNCT6 << kRvvFunct6Shift), + RO_V_VMSLTU_VX = OP_IVX | (VMSLTU_FUNCT6 << kRvvFunct6Shift), + + VMSLT_FUNCT6 = 0b011011, + RO_V_VMSLT_VV = OP_IVV | (VMSLT_FUNCT6 << kRvvFunct6Shift), + RO_V_VMSLT_VX = OP_IVX | (VMSLT_FUNCT6 << kRvvFunct6Shift), + + VMSLE_FUNCT6 = 0b011101, + RO_V_VMSLE_VI = OP_IVI | (VMSLE_FUNCT6 << kRvvFunct6Shift), + RO_V_VMSLE_VV = OP_IVV | (VMSLE_FUNCT6 << kRvvFunct6Shift), + RO_V_VMSLE_VX = OP_IVX | (VMSLE_FUNCT6 << kRvvFunct6Shift), + + VMSLEU_FUNCT6 = 0b011100, + RO_V_VMSLEU_VI = OP_IVI | (VMSLEU_FUNCT6 << kRvvFunct6Shift), + RO_V_VMSLEU_VV = OP_IVV | (VMSLEU_FUNCT6 << kRvvFunct6Shift), + RO_V_VMSLEU_VX = OP_IVX | (VMSLEU_FUNCT6 << kRvvFunct6Shift), + + VMSGTU_FUNCT6 = 0b011110, + RO_V_VMSGTU_VI = OP_IVI | (VMSGTU_FUNCT6 << kRvvFunct6Shift), + RO_V_VMSGTU_VX = OP_IVX | (VMSGTU_FUNCT6 << kRvvFunct6Shift), + + VMSGT_FUNCT6 = 0b011111, + RO_V_VMSGT_VI = OP_IVI | (VMSGT_FUNCT6 << kRvvFunct6Shift), + RO_V_VMSGT_VX = OP_IVX | (VMSGT_FUNCT6 << kRvvFunct6Shift), + + VSLIDEUP_FUNCT6 = 0b001110, + RO_V_VSLIDEUP_VI = OP_IVI | (VSLIDEUP_FUNCT6 << kRvvFunct6Shift), + RO_V_VSLIDEUP_VX = OP_IVX | (VSLIDEUP_FUNCT6 << kRvvFunct6Shift), + + VSLIDEDOWN_FUNCT6 = 0b001111, + RO_V_VSLIDEDOWN_VI = OP_IVI | (VSLIDEDOWN_FUNCT6 << kRvvFunct6Shift), + RO_V_VSLIDEDOWN_VX = OP_IVX | (VSLIDEDOWN_FUNCT6 << kRvvFunct6Shift), + + VSRL_FUNCT6 = 0b101000, + RO_V_VSRL_VI = OP_IVI | (VSRL_FUNCT6 << kRvvFunct6Shift), + RO_V_VSRL_VV = OP_IVV | (VSRL_FUNCT6 << kRvvFunct6Shift), + RO_V_VSRL_VX = OP_IVX | (VSRL_FUNCT6 << kRvvFunct6Shift), + + VSRA_FUNCT6 = 0b101001, + RO_V_VSRA_VI = OP_IVI | (VSRA_FUNCT6 << kRvvFunct6Shift), + RO_V_VSRA_VV = OP_IVV | (VSRA_FUNCT6 << kRvvFunct6Shift), + RO_V_VSRA_VX = OP_IVX | (VSRA_FUNCT6 << kRvvFunct6Shift), + + VSLL_FUNCT6 = 0b100101, + RO_V_VSLL_VI = OP_IVI | (VSLL_FUNCT6 << kRvvFunct6Shift), + RO_V_VSLL_VV = OP_IVV | (VSLL_FUNCT6 << kRvvFunct6Shift), + RO_V_VSLL_VX = OP_IVX | (VSLL_FUNCT6 << kRvvFunct6Shift), + + VSMUL_FUNCT6 = 0b100111, + RO_V_VSMUL_VV = OP_IVV | (VSMUL_FUNCT6 << kRvvFunct6Shift), + RO_V_VSMUL_VX = OP_IVX | (VSMUL_FUNCT6 << kRvvFunct6Shift), + + VADC_FUNCT6 = 0b010000, + RO_V_VADC_VI = OP_IVI | (VADC_FUNCT6 << kRvvFunct6Shift), + RO_V_VADC_VV = OP_IVV | (VADC_FUNCT6 << kRvvFunct6Shift), + RO_V_VADC_VX = OP_IVX | (VADC_FUNCT6 << kRvvFunct6Shift), + + VMADC_FUNCT6 = 0b010001, + RO_V_VMADC_VI = OP_IVI | (VMADC_FUNCT6 << kRvvFunct6Shift), + RO_V_VMADC_VV = OP_IVV | (VMADC_FUNCT6 << kRvvFunct6Shift), + RO_V_VMADC_VX = OP_IVX | (VMADC_FUNCT6 << kRvvFunct6Shift), + + VWXUNARY0_FUNCT6 = 0b010000, + VRXUNARY0_FUNCT6 = 0b010000, + VMUNARY0_FUNCT6 = 0b010100, + + RO_V_VWXUNARY0 = OP_MVV | (VWXUNARY0_FUNCT6 << kRvvFunct6Shift), + RO_V_VRXUNARY0 = OP_MVX | (VRXUNARY0_FUNCT6 << kRvvFunct6Shift), + RO_V_VMUNARY0 = OP_MVV | (VMUNARY0_FUNCT6 << kRvvFunct6Shift), + + VID_V = 0b10001, + + VXUNARY0_FUNCT6 = 0b010010, + RO_V_VXUNARY0 = OP_MVV | (VXUNARY0_FUNCT6 << kRvvFunct6Shift), + + VWFUNARY0_FUNCT6 = 0b010000, + RO_V_VFMV_FS = OP_FVV | (VWFUNARY0_FUNCT6 << kRvvFunct6Shift), + + VRFUNARY0_FUNCT6 = 0b010000, + RO_V_VFMV_SF = OP_FVF | (VRFUNARY0_FUNCT6 << kRvvFunct6Shift), + + VREDMAXU_FUNCT6 = 0b000110, + RO_V_VREDMAXU = OP_MVV | (VREDMAXU_FUNCT6 << kRvvFunct6Shift), + VREDMAX_FUNCT6 = 0b000111, + RO_V_VREDMAX = OP_MVV | (VREDMAX_FUNCT6 << kRvvFunct6Shift), + + VREDMINU_FUNCT6 = 0b000100, + RO_V_VREDMINU = OP_MVV | (VREDMINU_FUNCT6 << kRvvFunct6Shift), + VREDMIN_FUNCT6 = 0b000101, + RO_V_VREDMIN = OP_MVV | (VREDMIN_FUNCT6 << kRvvFunct6Shift), + + VFUNARY0_FUNCT6 = 0b010010, + RO_V_VFUNARY0 = OP_FVV | (VFUNARY0_FUNCT6 << kRvvFunct6Shift), + VFUNARY1_FUNCT6 = 0b010011, + RO_V_VFUNARY1 = OP_FVV | (VFUNARY1_FUNCT6 << kRvvFunct6Shift), + + VFCVT_XU_F_V = 0b00000, + VFCVT_X_F_V = 0b00001, + VFCVT_F_XU_V = 0b00010, + VFCVT_F_X_V = 0b00011, + VFWCVT_XU_F_V = 0b01000, + VFWCVT_X_F_V = 0b01001, + VFWCVT_F_XU_V = 0b01010, + VFWCVT_F_X_V = 0b01011, + VFWCVT_F_F_V = 0b01100, + VFNCVT_F_F_W = 0b10100, + VFNCVT_X_F_W = 0b10001, + VFNCVT_XU_F_W = 0b10000, + + VFCLASS_V = 0b10000, + VFSQRT_V = 0b00000, + VFRSQRT7_V = 0b00100, + VFREC7_V = 0b00101, + + VFADD_FUNCT6 = 0b000000, + RO_V_VFADD_VV = OP_FVV | (VFADD_FUNCT6 << kRvvFunct6Shift), + RO_V_VFADD_VF = OP_FVF | (VFADD_FUNCT6 << kRvvFunct6Shift), + + VFSUB_FUNCT6 = 0b000010, + RO_V_VFSUB_VV = OP_FVV | (VFSUB_FUNCT6 << kRvvFunct6Shift), + RO_V_VFSUB_VF = OP_FVF | (VFSUB_FUNCT6 << kRvvFunct6Shift), + + VFDIV_FUNCT6 = 0b100000, + RO_V_VFDIV_VV = OP_FVV | (VFDIV_FUNCT6 << kRvvFunct6Shift), + RO_V_VFDIV_VF = OP_FVF | (VFDIV_FUNCT6 << kRvvFunct6Shift), + + VFMUL_FUNCT6 = 0b100100, + RO_V_VFMUL_VV = OP_FVV | (VFMUL_FUNCT6 << kRvvFunct6Shift), + RO_V_VFMUL_VF = OP_FVF | (VFMUL_FUNCT6 << kRvvFunct6Shift), + + // Vector Widening Floating-Point Add/Subtract Instructions + VFWADD_FUNCT6 = 0b110000, + RO_V_VFWADD_VV = OP_FVV | (VFWADD_FUNCT6 << kRvvFunct6Shift), + RO_V_VFWADD_VF = OP_FVF | (VFWADD_FUNCT6 << kRvvFunct6Shift), + + VFWSUB_FUNCT6 = 0b110010, + RO_V_VFWSUB_VV = OP_FVV | (VFWSUB_FUNCT6 << kRvvFunct6Shift), + RO_V_VFWSUB_VF = OP_FVF | (VFWSUB_FUNCT6 << kRvvFunct6Shift), + + VFWADD_W_FUNCT6 = 0b110100, + RO_V_VFWADD_W_VV = OP_FVV | (VFWADD_W_FUNCT6 << kRvvFunct6Shift), + RO_V_VFWADD_W_VF = OP_FVF | (VFWADD_W_FUNCT6 << kRvvFunct6Shift), + + VFWSUB_W_FUNCT6 = 0b110110, + RO_V_VFWSUB_W_VV = OP_FVV | (VFWSUB_W_FUNCT6 << kRvvFunct6Shift), + RO_V_VFWSUB_W_VF = OP_FVF | (VFWSUB_W_FUNCT6 << kRvvFunct6Shift), + + // Vector Widening Floating-Point Reduction Instructions + VFWREDUSUM_FUNCT6 = 0b110001, + RO_V_VFWREDUSUM_VV = OP_FVV | (VFWREDUSUM_FUNCT6 << kRvvFunct6Shift), + + VFWREDOSUM_FUNCT6 = 0b110011, + RO_V_VFWREDOSUM_VV = OP_FVV | (VFWREDOSUM_FUNCT6 << kRvvFunct6Shift), + + // Vector Widening Floating-Point Multiply + VFWMUL_FUNCT6 = 0b111000, + RO_V_VFWMUL_VV = OP_FVV | (VFWMUL_FUNCT6 << kRvvFunct6Shift), + RO_V_VFWMUL_VF = OP_FVF | (VFWMUL_FUNCT6 << kRvvFunct6Shift), + + VMFEQ_FUNCT6 = 0b011000, + RO_V_VMFEQ_VV = OP_FVV | (VMFEQ_FUNCT6 << kRvvFunct6Shift), + RO_V_VMFEQ_VF = OP_FVF | (VMFEQ_FUNCT6 << kRvvFunct6Shift), + + VMFNE_FUNCT6 = 0b011100, + RO_V_VMFNE_VV = OP_FVV | (VMFNE_FUNCT6 << kRvvFunct6Shift), + RO_V_VMFNE_VF = OP_FVF | (VMFNE_FUNCT6 << kRvvFunct6Shift), + + VMFLT_FUNCT6 = 0b011011, + RO_V_VMFLT_VV = OP_FVV | (VMFLT_FUNCT6 << kRvvFunct6Shift), + RO_V_VMFLT_VF = OP_FVF | (VMFLT_FUNCT6 << kRvvFunct6Shift), + + VMFLE_FUNCT6 = 0b011001, + RO_V_VMFLE_VV = OP_FVV | (VMFLE_FUNCT6 << kRvvFunct6Shift), + RO_V_VMFLE_VF = OP_FVF | (VMFLE_FUNCT6 << kRvvFunct6Shift), + + VMFGE_FUNCT6 = 0b011111, + RO_V_VMFGE_VF = OP_FVF | (VMFGE_FUNCT6 << kRvvFunct6Shift), + + VMFGT_FUNCT6 = 0b011101, + RO_V_VMFGT_VF = OP_FVF | (VMFGT_FUNCT6 << kRvvFunct6Shift), + + VFMAX_FUNCT6 = 0b000110, + RO_V_VFMAX_VV = OP_FVV | (VFMAX_FUNCT6 << kRvvFunct6Shift), + RO_V_VFMAX_VF = OP_FVF | (VFMAX_FUNCT6 << kRvvFunct6Shift), + + VFREDMAX_FUNCT6 = 0b0001111, + RO_V_VFREDMAX_VV = OP_FVV | (VFREDMAX_FUNCT6 << kRvvFunct6Shift), + + VFMIN_FUNCT6 = 0b000100, + RO_V_VFMIN_VV = OP_FVV | (VFMIN_FUNCT6 << kRvvFunct6Shift), + RO_V_VFMIN_VF = OP_FVF | (VFMIN_FUNCT6 << kRvvFunct6Shift), + + VFSGNJ_FUNCT6 = 0b001000, + RO_V_VFSGNJ_VV = OP_FVV | (VFSGNJ_FUNCT6 << kRvvFunct6Shift), + RO_V_VFSGNJ_VF = OP_FVF | (VFSGNJ_FUNCT6 << kRvvFunct6Shift), + + VFSGNJN_FUNCT6 = 0b001001, + RO_V_VFSGNJN_VV = OP_FVV | (VFSGNJN_FUNCT6 << kRvvFunct6Shift), + RO_V_VFSGNJN_VF = OP_FVF | (VFSGNJN_FUNCT6 << kRvvFunct6Shift), + + VFSGNJX_FUNCT6 = 0b001010, + RO_V_VFSGNJX_VV = OP_FVV | (VFSGNJX_FUNCT6 << kRvvFunct6Shift), + RO_V_VFSGNJX_VF = OP_FVF | (VFSGNJX_FUNCT6 << kRvvFunct6Shift), + + VFMADD_FUNCT6 = 0b101000, + RO_V_VFMADD_VV = OP_FVV | (VFMADD_FUNCT6 << kRvvFunct6Shift), + RO_V_VFMADD_VF = OP_FVF | (VFMADD_FUNCT6 << kRvvFunct6Shift), + + VFNMADD_FUNCT6 = 0b101001, + RO_V_VFNMADD_VV = OP_FVV | (VFNMADD_FUNCT6 << kRvvFunct6Shift), + RO_V_VFNMADD_VF = OP_FVF | (VFNMADD_FUNCT6 << kRvvFunct6Shift), + + VFMSUB_FUNCT6 = 0b101010, + RO_V_VFMSUB_VV = OP_FVV | (VFMSUB_FUNCT6 << kRvvFunct6Shift), + RO_V_VFMSUB_VF = OP_FVF | (VFMSUB_FUNCT6 << kRvvFunct6Shift), + + VFNMSUB_FUNCT6 = 0b101011, + RO_V_VFNMSUB_VV = OP_FVV | (VFNMSUB_FUNCT6 << kRvvFunct6Shift), + RO_V_VFNMSUB_VF = OP_FVF | (VFNMSUB_FUNCT6 << kRvvFunct6Shift), + + VFMACC_FUNCT6 = 0b101100, + RO_V_VFMACC_VV = OP_FVV | (VFMACC_FUNCT6 << kRvvFunct6Shift), + RO_V_VFMACC_VF = OP_FVF | (VFMACC_FUNCT6 << kRvvFunct6Shift), + + VFNMACC_FUNCT6 = 0b101101, + RO_V_VFNMACC_VV = OP_FVV | (VFNMACC_FUNCT6 << kRvvFunct6Shift), + RO_V_VFNMACC_VF = OP_FVF | (VFNMACC_FUNCT6 << kRvvFunct6Shift), + + VFMSAC_FUNCT6 = 0b101110, + RO_V_VFMSAC_VV = OP_FVV | (VFMSAC_FUNCT6 << kRvvFunct6Shift), + RO_V_VFMSAC_VF = OP_FVF | (VFMSAC_FUNCT6 << kRvvFunct6Shift), + + VFNMSAC_FUNCT6 = 0b101111, + RO_V_VFNMSAC_VV = OP_FVV | (VFNMSAC_FUNCT6 << kRvvFunct6Shift), + RO_V_VFNMSAC_VF = OP_FVF | (VFNMSAC_FUNCT6 << kRvvFunct6Shift), + + // Vector Widening Floating-Point Fused Multiply-Add Instructions + VFWMACC_FUNCT6 = 0b111100, + RO_V_VFWMACC_VV = OP_FVV | (VFWMACC_FUNCT6 << kRvvFunct6Shift), + RO_V_VFWMACC_VF = OP_FVF | (VFWMACC_FUNCT6 << kRvvFunct6Shift), + + VFWNMACC_FUNCT6 = 0b111101, + RO_V_VFWNMACC_VV = OP_FVV | (VFWNMACC_FUNCT6 << kRvvFunct6Shift), + RO_V_VFWNMACC_VF = OP_FVF | (VFWNMACC_FUNCT6 << kRvvFunct6Shift), + + VFWMSAC_FUNCT6 = 0b111110, + RO_V_VFWMSAC_VV = OP_FVV | (VFWMSAC_FUNCT6 << kRvvFunct6Shift), + RO_V_VFWMSAC_VF = OP_FVF | (VFWMSAC_FUNCT6 << kRvvFunct6Shift), + + VFWNMSAC_FUNCT6 = 0b111111, + RO_V_VFWNMSAC_VV = OP_FVV | (VFWNMSAC_FUNCT6 << kRvvFunct6Shift), + RO_V_VFWNMSAC_VF = OP_FVF | (VFWNMSAC_FUNCT6 << kRvvFunct6Shift), + + VNCLIP_FUNCT6 = 0b101111, + RO_V_VNCLIP_WV = OP_IVV | (VNCLIP_FUNCT6 << kRvvFunct6Shift), + RO_V_VNCLIP_WX = OP_IVX | (VNCLIP_FUNCT6 << kRvvFunct6Shift), + RO_V_VNCLIP_WI = OP_IVI | (VNCLIP_FUNCT6 << kRvvFunct6Shift), + + VNCLIPU_FUNCT6 = 0b101110, + RO_V_VNCLIPU_WV = OP_IVV | (VNCLIPU_FUNCT6 << kRvvFunct6Shift), + RO_V_VNCLIPU_WX = OP_IVX | (VNCLIPU_FUNCT6 << kRvvFunct6Shift), + RO_V_VNCLIPU_WI = OP_IVI | (VNCLIPU_FUNCT6 << kRvvFunct6Shift), +}; +} // namespace jit +} // namespace js + +#endif // jit_riscv64_constant_Constant_riscv64_v_h_ diff --git a/js/src/jit/riscv64/constant/Constant-riscv-zicsr.h b/js/src/jit/riscv64/constant/Constant-riscv-zicsr.h new file mode 100644 index 0000000000..6fecfa3d92 --- /dev/null +++ b/js/src/jit/riscv64/constant/Constant-riscv-zicsr.h @@ -0,0 +1,30 @@ +// Copyright 2022 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef jit_riscv64_constant_Constant_riscv64_zicsr_h_ +#define jit_riscv64_constant_Constant_riscv64_zicsr_h_ + +#include "jit/riscv64/constant/Base-constant-riscv.h" +namespace js { +namespace jit { +// RISCV CSR related bit mask and shift +const int kFcsrFlagsBits = 5; +const uint32_t kFcsrFlagsMask = (1 << kFcsrFlagsBits) - 1; +const int kFcsrFrmBits = 3; +const int kFcsrFrmShift = kFcsrFlagsBits; +const uint32_t kFcsrFrmMask = ((1 << kFcsrFrmBits) - 1) << kFcsrFrmShift; +const int kFcsrBits = kFcsrFlagsBits + kFcsrFrmBits; +const uint32_t kFcsrMask = kFcsrFlagsMask | kFcsrFrmMask; + +enum OpcodeRISCVZICSR : uint32_t { + // RV32/RV64 Zicsr Standard Extension + RO_CSRRW = SYSTEM | (0b001 << kFunct3Shift), + RO_CSRRS = SYSTEM | (0b010 << kFunct3Shift), + RO_CSRRC = SYSTEM | (0b011 << kFunct3Shift), + RO_CSRRWI = SYSTEM | (0b101 << kFunct3Shift), + RO_CSRRSI = SYSTEM | (0b110 << kFunct3Shift), + RO_CSRRCI = SYSTEM | (0b111 << kFunct3Shift), +}; +} // namespace jit +} // namespace js +#endif // jit_riscv64_constant_Constant_riscv64_zicsr_h_ diff --git a/js/src/jit/riscv64/constant/Constant-riscv-zifencei.h b/js/src/jit/riscv64/constant/Constant-riscv-zifencei.h new file mode 100644 index 0000000000..be01cd0ae0 --- /dev/null +++ b/js/src/jit/riscv64/constant/Constant-riscv-zifencei.h @@ -0,0 +1,15 @@ +// Copyright 2022 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef jit_riscv64_constant_Constant_riscv64_zifencei_h_ +#define jit_riscv64_constant_Constant_riscv64_zifencei_h_ + +#include "jit/riscv64/constant/Base-constant-riscv.h" +namespace js { +namespace jit { +enum OpcodeRISCVIFENCEI : uint32_t { + RO_FENCE_I = MISC_MEM | (0b001 << kFunct3Shift), +}; +} +} // namespace js +#endif // jit_riscv64_constant_Constant_riscv64_zifencei_h_ diff --git a/js/src/jit/riscv64/constant/Constant-riscv64.h b/js/src/jit/riscv64/constant/Constant-riscv64.h new file mode 100644 index 0000000000..b9b1f894e7 --- /dev/null +++ b/js/src/jit/riscv64/constant/Constant-riscv64.h @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef jit_riscv64_constant_Constant_riscv64_h +#define jit_riscv64_constant_Constant_riscv64_h +#include "mozilla/Assertions.h" +#include "mozilla/Types.h" + +#include <stdio.h> + +#include "jit/riscv64/constant/Base-constant-riscv.h" +#include "jit/riscv64/constant/Constant-riscv-a.h" +#include "jit/riscv64/constant/Constant-riscv-c.h" +#include "jit/riscv64/constant/Constant-riscv-d.h" +#include "jit/riscv64/constant/Constant-riscv-f.h" +#include "jit/riscv64/constant/Constant-riscv-i.h" +#include "jit/riscv64/constant/Constant-riscv-m.h" +#include "jit/riscv64/constant/Constant-riscv-v.h" +#include "jit/riscv64/constant/Constant-riscv-zicsr.h" +#include "jit/riscv64/constant/Constant-riscv-zifencei.h" + +namespace js { +namespace jit { + +// A reasonable (ie, safe) buffer size for the disassembly of a single +// instruction. +const int ReasonableBufferSize = 256; + +// Difference between address of current opcode and value read from pc +// register. +static constexpr int kPcLoadDelta = 4; + +// Bits available for offset field in branches +static constexpr int kBranchOffsetBits = 13; + +// Bits available for offset field in jump +static constexpr int kJumpOffsetBits = 21; + +// Bits available for offset field in compresed jump +static constexpr int kCJalOffsetBits = 12; + +// Bits available for offset field in 4 branch +static constexpr int kCBranchOffsetBits = 9; + +// Max offset for b instructions with 12-bit offset field (multiple of 2) +static constexpr int kMaxBranchOffset = (1 << (kBranchOffsetBits - 1)) - 1; + +static constexpr int kCBranchOffset = (1 << (kCBranchOffsetBits - 1)) - 1; +// Max offset for jal instruction with 20-bit offset field (multiple of 2) +static constexpr int kMaxJumpOffset = (1 << (kJumpOffsetBits - 1)) - 1; + +static constexpr int kCJumpOffset = (1 << (kCJalOffsetBits - 1)) - 1; + +static constexpr int kTrampolineSlotsSize = 2 * kInstrSize; + +static_assert(kCJalOffsetBits == kOffset12); +static_assert(kCBranchOffsetBits == kOffset9); +static_assert(kJumpOffsetBits == kOffset21); +static_assert(kBranchOffsetBits == kOffset13); +// Vector as used by the original code to allow for minimal modification. +// Functions exactly like a character array with helper methods. +} // namespace jit +} // namespace js + +#endif // jit_riscv64_constant_Constant_riscv64_h diff --git a/js/src/jit/riscv64/constant/util-riscv64.h b/js/src/jit/riscv64/constant/util-riscv64.h new file mode 100644 index 0000000000..089e0f3b94 --- /dev/null +++ b/js/src/jit/riscv64/constant/util-riscv64.h @@ -0,0 +1,82 @@ + +// Copyright 2022 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef jit_riscv64_constant_util_riscv64__h_ +#define jit_riscv64_constant_util_riscv64__h_ +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +namespace js { +namespace jit { +template <typename T> +class V8Vector { + public: + V8Vector() : start_(nullptr), length_(0) {} + V8Vector(T* data, int length) : start_(data), length_(length) { + MOZ_ASSERT(length == 0 || (length > 0 && data != nullptr)); + } + + // Returns the length of the vector. + int length() const { return length_; } + + // Returns the pointer to the start of the data in the vector. + T* start() const { return start_; } + + // Access individual vector elements - checks bounds in debug mode. + T& operator[](int index) const { + MOZ_ASSERT(0 <= index && index < length_); + return start_[index]; + } + + inline V8Vector<T> operator+(int offset) { + MOZ_ASSERT(offset < length_); + return V8Vector<T>(start_ + offset, length_ - offset); + } + + private: + T* start_; + int length_; +}; + +template <typename T, int kSize> +class EmbeddedVector : public V8Vector<T> { + public: + EmbeddedVector() : V8Vector<T>(buffer_, kSize) {} + + explicit EmbeddedVector(T initial_value) : V8Vector<T>(buffer_, kSize) { + for (int i = 0; i < kSize; ++i) { + buffer_[i] = initial_value; + } + } + + // When copying, make underlying Vector to reference our buffer. + EmbeddedVector(const EmbeddedVector& rhs) : V8Vector<T>(rhs) { + MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize); + this->set_start(buffer_); + } + + EmbeddedVector& operator=(const EmbeddedVector& rhs) { + if (this == &rhs) return *this; + V8Vector<T>::operator=(rhs); + MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize); + this->set_start(buffer_); + return *this; + } + + private: + T buffer_[kSize]; +}; + +// Helper function for printing to a Vector. +static inline int MOZ_FORMAT_PRINTF(2, 3) + SNPrintF(V8Vector<char> str, const char* format, ...) { + va_list args; + va_start(args, format); + int result = vsnprintf(str.start(), str.length(), format, args); + va_end(args); + return result; +} +} // namespace jit +} // namespace js +#endif |