// 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 #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(this); return (FirstByte & 0x03) <= C2; } template int InstructionGetters::RvcRdValue() const { MOZ_ASSERT(this->IsShortInstruction()); return this->Bits(kRvcRdShift + kRvcRdBits - 1, kRvcRdShift); } template int InstructionGetters::RvcRs2Value() const { MOZ_ASSERT(this->IsShortInstruction()); return this->Bits(kRvcRs2Shift + kRvcRs2Bits - 1, kRvcRs2Shift); } template int InstructionGetters::RvcRs1sValue() const { MOZ_ASSERT(this->IsShortInstruction()); return 0b1000 + this->Bits(kRvcRs1sShift + kRvcRs1sBits - 1, kRvcRs1sShift); } template int InstructionGetters::RvcRs2sValue() const { MOZ_ASSERT(this->IsShortInstruction()); return 0b1000 + this->Bits(kRvcRs2sShift + kRvcRs2sBits - 1, kRvcRs2sShift); } template inline int InstructionGetters::RvcFunct6Value() const { MOZ_ASSERT(this->IsShortInstruction()); return this->Bits(kRvcFunct6Shift + kRvcFunct6Bits - 1, kRvcFunct6Shift); } template inline int InstructionGetters::RvcFunct4Value() const { MOZ_ASSERT(this->IsShortInstruction()); return this->Bits(kRvcFunct4Shift + kRvcFunct4Bits - 1, kRvcFunct4Shift); } template inline int InstructionGetters::RvcFunct3Value() const { MOZ_ASSERT(this->IsShortInstruction()); return this->Bits(kRvcFunct3Shift + kRvcFunct3Bits - 1, kRvcFunct3Shift); } template inline int InstructionGetters::RvcFunct2Value() const { MOZ_ASSERT(this->IsShortInstruction()); return this->Bits(kRvcFunct2Shift + kRvcFunct2Bits - 1, kRvcFunct2Shift); } template inline int InstructionGetters::RvcFunct2BValue() const { MOZ_ASSERT(this->IsShortInstruction()); return this->Bits(kRvcFunct2BShift + kRvcFunct2Bits - 1, kRvcFunct2BShift); } template uint32_t InstructionGetters::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 uint32_t InstructionGetters::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; #ifdef JS_SIMULATOR_RISCV64 template class InstructionGetters; #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