Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  Instruction.h

  Sprache: C
 

// 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_base_Instruction_h
#define jit_riscv64_base_Instruction_h

#include "mozilla/Assertions.h"

#include <stdint.h>

#include "jit/riscv64/base/Integer.h"
#include "jit/riscv64/constant/Constant-riscv64.h"

namespace js::jit {

// On RISCV all instructions are 32 bits, except for RVC.
using Instr = int32_t;
using ShortInstr = int16_t;

// -----------------------------------------------------------------------------
// 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;

class InstructionBase {
  // Sign-extend a |len|-bits integer.
  static constexpr int32_t sext(int32_t x, uint32_t len) {
    MOZ_ASSERT(0 < len && len <= 32);
    return ((x << (32 - len)) >> (32 - len));
  }

  // Zero-extend a |len|-bits integer.
  static constexpr uint32_t zext(uint32_t x, uint32_t len) {
    MOZ_ASSERT(0 < len && len <= 32);
    return ((x << (32 - len)) >> (32 - len));
  }

 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;
  }

  inline bool IsShortInstruction() const {
    uint8_t FirstByte = *reinterpret_cast<const uint8_t*>(this);
    return (FirstByte & 0x03) <= C2;
  }

  inline uint8_t InstructionSize() const {
    return IsShortInstruction() ? kShortInstrSize : kInstrSize;
  }

  // Get the raw instruction bits.
  inline Instr InstructionBits() const {
    if (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 enum BaseOpcode BaseOpcodeValue() const {
    return static_cast<enum BaseOpcode>(
        Bits(kBaseOpcodeShift + kBaseOpcodeBits - 1, kBaseOpcodeShift));
  }

  // Return the fields at their original place in the instruction encoding.
  inline enum BaseOpcode BaseOpcodeFieldRaw() const {
    return static_cast<enum BaseOpcode>(InstructionBits() & kBaseOpcodeMask);
  }

  // Safe to call within R-type instructions
  inline int Funct7FieldRaw() const { return InstructionBits() & kFunct7Mask; }

  // Safe to call within R-type instructions
  inline int Funct6FieldRaw() const { return InstructionBits() & kFunct6Mask; }

  // 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;
    }
    return InstructionBits() & kBaseOpcodeMask;
  }

  // Get the encoding type of the instruction.
  Type InstructionType() const;
  OffsetSize GetOffsetSize() const;
  inline ImmBranchRangeType GetImmBranchRangeType() const {
    return OffsetSizeToImmBranchRangeType(GetOffsetSize());
  }

  /// Getters

  // Say if the instruction is a break or a trap.
  inline bool IsTrap() const { return InstructionBits() == kBreakInstr; }

  // Check if the instruction is a branch of some kind.
  inline bool IsBranch() const { return BaseOpcode() == BRANCH; }

  inline bool IsJal() const { return BaseOpcode() == JAL; }

  inline bool IsJalr() const { return BaseOpcode() == JALR; }

  inline bool IsLui() const { return BaseOpcode() == LUI; }

  inline bool IsAuipc() const { return BaseOpcode() == AUIPC; }

  inline bool IsAddi() const {
    return (InstructionBits() & kITypeMask) == RO_ADDI;
  }

  inline bool IsOri() const {
    return (InstructionBits() & kITypeMask) == RO_ORI;
  }

  inline bool IsSlli() const {
    return (InstructionBits() & kITypeMask) == RO_SLLI;
  }

  inline bool IsLw() const { return (InstructionBits() & kITypeMask) == RO_LW; }

  inline bool IsLd() const { return (InstructionBits() & kITypeMask) == RO_LD; }

  inline bool IsAddiw() const {
    return (InstructionBits() & kITypeMask) == RO_ADDIW;
  }

  inline bool IsNop() const { return InstructionBits() == kNopByte; }

  inline int BaseOpcode() const { return InstructionBits() & kBaseOpcodeMask; }

  inline int RvcOpcode() const {
    MOZ_ASSERT(IsShortInstruction());
    return InstructionBits() & kRvcOpcodeMask;
  }

  inline int Rs1Value() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kRType ||
               InstructionType() == InstructionBase::kR4Type ||
               InstructionType() == InstructionBase::kIType ||
               InstructionType() == InstructionBase::kSType ||
               InstructionType() == InstructionBase::kBType ||
               InstructionType() == InstructionBase::kVType);
    return Bits(kRs1Shift + kRs1Bits - 1, kRs1Shift);
  }

  inline int Rs2Value() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kRType ||
               InstructionType() == InstructionBase::kR4Type ||
               InstructionType() == InstructionBase::kSType ||
               InstructionType() == InstructionBase::kBType ||
               InstructionType() == InstructionBase::kIType ||
               InstructionType() == InstructionBase::kVType);
    return Bits(kRs2Shift + kRs2Bits - 1, kRs2Shift);
  }

  inline int Rs3Value() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kR4Type);
    return Bits(kRs3Shift + kRs3Bits - 1, kRs3Shift);
  }

  inline int Vs1Value() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kVType ||
               InstructionType() == InstructionBase::kIType ||
               InstructionType() == InstructionBase::kSType);
    return Bits(kVs1Shift + kVs1Bits - 1, kVs1Shift);
  }

  inline int Vs2Value() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kVType ||
               InstructionType() == InstructionBase::kIType ||
               InstructionType() == InstructionBase::kSType);
    return Bits(kVs2Shift + kVs2Bits - 1, kVs2Shift);
  }

  inline int VdValue() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kVType ||
               InstructionType() == InstructionBase::kIType ||
               InstructionType() == InstructionBase::kSType);
    return Bits(kVdShift + kVdBits - 1, kVdShift);
  }

  inline int RdValue() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kRType ||
               InstructionType() == InstructionBase::kR4Type ||
               InstructionType() == InstructionBase::kIType ||
               InstructionType() == InstructionBase::kSType ||
               InstructionType() == InstructionBase::kUType ||
               InstructionType() == InstructionBase::kJType ||
               InstructionType() == InstructionBase::kVType);
    return Bits(kRdShift + kRdBits - 1, kRdShift);
  }

  inline int RvcRs1Value() const { return RvcRdValue(); }

  inline int RvcRdValue() const {
    MOZ_ASSERT(IsShortInstruction());
    return Bits(kRvcRdShift + kRvcRdBits - 1, kRvcRdShift);
  }

  inline int RvcRs2Value() const {
    MOZ_ASSERT(IsShortInstruction());
    return Bits(kRvcRs2Shift + kRvcRs2Bits - 1, kRvcRs2Shift);
  }

  inline int RvcRs1sValue() const {
    MOZ_ASSERT(IsShortInstruction());
    return 0b1000 + Bits(kRvcRs1sShift + kRvcRs1sBits - 1, kRvcRs1sShift);
  }

  inline int RvcRs2sValue() const {
    MOZ_ASSERT(IsShortInstruction());
    return 0b1000 + Bits(kRvcRs2sShift + kRvcRs2sBits - 1, kRvcRs2sShift);
  }

  inline int Funct7Value() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kRType);
    return Bits(kFunct7Shift + kFunct7Bits - 1, kFunct7Shift);
  }

  inline int Funct2Value() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kR4Type);
    return Bits(kFunct2Shift + kFunct2Bits - 1, kFunct2Shift);
  }

  inline int Funct3Value() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kRType ||
               InstructionType() == InstructionBase::kR4Type ||
               InstructionType() == InstructionBase::kIType ||
               InstructionType() == InstructionBase::kSType ||
               InstructionType() == InstructionBase::kBType);
    return Bits(kFunct3Shift + kFunct3Bits - 1, kFunct3Shift);
  }

  inline int Funct5Value() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kRType &&
               BaseOpcode() == OP_FP);
    return Bits(kFunct5Shift + kFunct5Bits - 1, kFunct5Shift);
  }

  inline int RvcFunct6Value() const {
    MOZ_ASSERT(IsShortInstruction());
    return Bits(kRvcFunct6Shift + kRvcFunct6Bits - 1, kRvcFunct6Shift);
  }

  inline int RvcFunct4Value() const {
    MOZ_ASSERT(IsShortInstruction());
    return Bits(kRvcFunct4Shift + kRvcFunct4Bits - 1, kRvcFunct4Shift);
  }

  inline int RvcFunct3Value() const {
    MOZ_ASSERT(IsShortInstruction());
    return Bits(kRvcFunct3Shift + kRvcFunct3Bits - 1, kRvcFunct3Shift);
  }

  inline int RvcFunct2Value() const {
    MOZ_ASSERT(IsShortInstruction());
    return Bits(kRvcFunct2Shift + kRvcFunct2Bits - 1, kRvcFunct2Shift);
  }

  inline int RvcFunct2BValue() const {
    MOZ_ASSERT(IsShortInstruction());
    return Bits(kRvcFunct2BShift + kRvcFunct2Bits - 1, kRvcFunct2BShift);
  }

  inline int CsrValue() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kIType &&
               BaseOpcode() == SYSTEM);
    return Bits(kCsrShift + kCsrBits - 1, kCsrShift);
  }

  inline int RoundMode() const {
    MOZ_ASSERT((InstructionType() == InstructionBase::kRType ||
                InstructionType() == InstructionBase::kR4Type) &&
               BaseOpcode() == OP_FP);
    return Bits(kFunct3Shift + kFunct3Bits - 1, kFunct3Shift);
  }

  inline int MemoryOrder(bool is_pred) const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kIType &&
               BaseOpcode() == MISC_MEM);
    if (is_pred) {
      return Bits(kPredOrderShift + kMemOrderBits - 1, kPredOrderShift);
    }
    return Bits(kSuccOrderShift + kMemOrderBits - 1, kSuccOrderShift);
  }

  inline int Imm12Value() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kIType);
    int Value = Bits(kImm12Shift + kImm12Bits - 1, kImm12Shift);
    return sext(Value, kImm12Bits);
  }

  inline int BranchOffset() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kBType);
    // | imm[12|10:5] | rs2 | rs1 | funct3 | imm[4:1|11] | opcode |
    //  31          25                      11          7
    uint32_t Bits = InstructionBits();
    int16_t imm13 = ((Bits & 0xf00) >> 7) | ((Bits & 0x7e000000) >> 20) |
                    ((Bits & 0x80) << 4) | ((Bits & 0x80000000) >> 19);
    return sext(imm13, 13);
  }

  inline int StoreOffset() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kSType);
    // | imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode |
    //  31       25                      11       7
    uint32_t Bits = InstructionBits();
    int16_t imm12 = ((Bits & 0xf80) >> 7) | ((Bits & 0xfe000000) >> 20);
    return sext(imm12, 12);
  }

  inline int Imm20UValue() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kUType);
    // | imm[31:12] | rd | opcode |
    //  31        12
    int32_t Bits = InstructionBits();
    return Bits >> 12;
  }

  inline int Imm20JValue() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kJType);
    // | imm[20|10:1|11|19:12] | rd | opcode |
    //  31                   12
    uint32_t Bits = InstructionBits();
    int32_t imm20 = ((Bits & 0x7fe00000) >> 20) | ((Bits & 0x100000) >> 9) |
                    (Bits & 0xff000) | ((Bits & 0x80000000) >> 11);
    return sext(imm20, 20 + 1);  // +1 b/c J immediates are shifted by 1 bit.
  }

  inline bool IsArithShift() const {
    // Valid only for right shift operations
    MOZ_ASSERT((BaseOpcode() == OP || BaseOpcode() == OP_32 ||
                BaseOpcode() == OP_IMM || BaseOpcode() == OP_IMM_32) &&
               Funct3Value() == 0b101);
    return InstructionBits() & 0x40000000;
  }

  inline int Shamt() const {
    // Valid only for shift instructions (SLLI, SRLI, SRAI)
    MOZ_ASSERT(((InstructionBits() & kBaseOpcodeMask) == OP_IMM ||
                (InstructionBits() & kBaseOpcodeMask) == OP_IMM_32) &&
               (Funct3Value() == 0b001 || Funct3Value() == 0b101));
    // | 0A0000 | shamt | rs1 | funct3 | rd | opcode |
    //  31       25    20
    return Bits(kImm12Shift + 5, kImm12Shift);
  }

  inline int Shamt32() const {
    // Valid only for shift instructions (SLLIW, SRLIW, SRAIW)
    MOZ_ASSERT((InstructionBits() & kBaseOpcodeMask) == OP_IMM_32 &&
               (Funct3Value() == 0b001 || Funct3Value() == 0b101));
    // | 0A00000 | shamt | rs1 | funct3 | rd | opcode |
    //  31        24   20
    return Bits(kImm12Shift + 4, kImm12Shift);
  }

  inline int RvcImm6Value() const {
    MOZ_ASSERT(IsShortInstruction());
    // | funct3 | imm[5] | rs1/rd | imm[4:0] | opcode |
    //  15         12              6        2
    uint32_t Bits = InstructionBits();
    int32_t imm6 = ((Bits & 0x1000) >> 7) | ((Bits & 0x7c) >> 2);
    return sext(imm6, 6);
  }

  inline int RvcImm6Addi16spValue() const {
    MOZ_ASSERT(IsShortInstruction());
    // | funct3 | nzimm[9] | 2 | nzimm[4|6|8:7|5] | opcode |
    //  15         12           6                2
    uint32_t Bits = InstructionBits();
    int32_t imm10 = ((Bits & 0x1000) >> 3) | ((Bits & 0x40) >> 2) |
                    ((Bits & 0x20) << 1) | ((Bits & 0x18) << 4) |
                    ((Bits & 0x4) << 3);
    MOZ_ASSERT(imm10 != 0);
    return sext(imm10, 10);
  }

  inline int RvcImm8Addi4spnValue() const {
    MOZ_ASSERT(IsShortInstruction());
    // | funct3 | nzimm[11]  | rd' | opcode |
    //  15      13           5     2
    uint32_t Bits = 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(IsShortInstruction());
    // | funct3 | nzuimm[5] | rs1/rd | nzuimm[4:0] | opcode |
    //  15         12                 6           2
    int32_t imm6 = RvcImm6Value();
    return imm6 & 0x3f;
  }

  inline int RvcImm6LwspValue() const {
    MOZ_ASSERT(IsShortInstruction());
    // | funct3 | uimm[5] | rs1 | uimm[4:2|7:6] | opcode |
    //  15         12            6             2
    uint32_t Bits = InstructionBits();
    int32_t imm8 =
        ((Bits & 0x1000) >> 7) | ((Bits & 0x70) >> 2) | ((Bits & 0xc) << 4);
    return imm8;
  }

  inline int RvcImm6LdspValue() const {
    MOZ_ASSERT(IsShortInstruction());
    // | funct3 | uimm[5] | rs1 | uimm[4:3|8:6] | opcode |
    //  15         12            6             2
    uint32_t Bits = InstructionBits();
    int32_t imm9 =
        ((Bits & 0x1000) >> 7) | ((Bits & 0x60) >> 2) | ((Bits & 0x1c) << 4);
    return imm9;
  }

  inline int RvcImm6SwspValue() const {
    MOZ_ASSERT(IsShortInstruction());
    // | funct3 | uimm[5:2|7:6] | rs2 | opcode |
    //  15       12            7
    uint32_t Bits = InstructionBits();
    int32_t imm8 = ((Bits & 0x1e00) >> 7) | ((Bits & 0x180) >> 1);
    return imm8;
  }

  inline int RvcImm6SdspValue() const {
    MOZ_ASSERT(IsShortInstruction());
    // | funct3 | uimm[5:3|8:6] | rs2 | opcode |
    //  15       12            7
    uint32_t Bits = InstructionBits();
    int32_t imm9 = ((Bits & 0x1c00) >> 7) | ((Bits & 0x380) >> 1);
    return imm9;
  }

  inline int RvcImm5WValue() const {
    MOZ_ASSERT(IsShortInstruction());
    // | funct3 | imm[5:3] | rs1 | imm[2|6] | rd | opcode |
    //  15       12       10     6          4     2
    uint32_t Bits = InstructionBits();
    int32_t imm7 =
        ((Bits & 0x1c00) >> 7) | ((Bits & 0x40) >> 4) | ((Bits & 0x20) << 1);
    return imm7;
  }

  inline int RvcImm5DValue() const {
    MOZ_ASSERT(IsShortInstruction());
    // | funct3 | imm[5:3] | rs1 | imm[7:6] | rd | opcode |
    //  15       12        10    6          4     2
    uint32_t Bits = InstructionBits();
    int32_t imm8 = ((Bits & 0x1c00) >> 7) | ((Bits & 0x60) << 1);
    return imm8;
  }

  inline int RvcImm11CJValue() const {
    MOZ_ASSERT(IsShortInstruction());
    // | funct3 | [11|4|9:8|10|6|7|3:1|5] | opcode |
    //  15      12                        2
    uint32_t Bits = 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 sext(imm12, 12);
  }

  inline int RvcImm8BValue() const {
    MOZ_ASSERT(IsShortInstruction());
    // | funct3 | imm[8|4:3] | rs1` | imm[7:6|2:1|5]  | opcode |
    //  15       12        10       7                 2
    uint32_t Bits = InstructionBits();
    int32_t imm9 = ((Bits & 0x4) << 3) | ((Bits & 0x18) >> 2) |
                   ((Bits & 0x60) << 1) | ((Bits & 0xc00) >> 7) |
                   ((Bits & 0x1000) >> 4);
    return sext(imm9, 9);
  }

  inline int vl_vs_width() {
    int width = 0;
    if ((InstructionBits() & kBaseOpcodeMask) != LOAD_FP &&
        (InstructionBits() & kBaseOpcodeMask) != STORE_FP) {
      return -1;
    }
    switch (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;
  }

  inline uint32_t Rvvzimm() const {
    if ((InstructionBits() & (kBaseOpcodeMask | kFunct3Mask | 0x80000000)) ==
        RO_V_VSETVLI) {
      uint32_t Bits = InstructionBits();
      uint32_t zimm = Bits & kRvvZimmMask;
      return zimm >> kRvvZimmShift;
    } else {
      MOZ_ASSERT((InstructionBits() & (kBaseOpcodeMask | kFunct3Mask |
                                       0xC0000000)) == RO_V_VSETIVLI);
      uint32_t Bits = InstructionBits();
      uint32_t zimm = Bits & kRvvZimmMask;
      return (zimm >> kRvvZimmShift) & 0x3FF;
    }
  }

  inline uint32_t Rvvuimm() const {
    MOZ_ASSERT((InstructionBits() &
                (kBaseOpcodeMask | kFunct3Mask | 0xC0000000)) == RO_V_VSETIVLI);
    uint32_t Bits = InstructionBits();
    uint32_t uimm = Bits & kRvvUimmMask;
    return uimm >> kRvvUimmShift;
  }

  inline uint32_t RvvVsew() const {
    uint32_t zimm = Rvvzimm();
    uint32_t vsew = (zimm >> 3) & 0x7;
    return vsew;
  }

  inline uint32_t RvvVlmul() const {
    uint32_t zimm = Rvvzimm();
    uint32_t vlmul = zimm & 0x7;
    return vlmul;
  }

  inline uint8_t RvvVM() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kVType ||
               InstructionType() == InstructionBase::kIType ||
               InstructionType() == InstructionBase::kSType);
    return Bits(kRvvVmShift + kRvvVmBits - 1, kRvvVmShift);
  }

  inline const char* RvvSEW() const {
    uint32_t vsew = 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 = RvvVlmul();
    switch (vlmul) {
#define CAST_VLMUL(name) \
  case name:             \
    return #name;
      RVV_LMUL(CAST_VLMUL)
      default:
        return "unknown";
#undef CAST_VLMUL
    }
  }

  inline int32_t RvvSimm5() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kVType);
    return sext(Bits(kRvvImm5Shift + kRvvImm5Bits - 1, kRvvImm5Shift),
                kRvvImm5Bits);
  }

  inline uint32_t RvvUimm5() const {
    MOZ_ASSERT(InstructionType() == InstructionBase::kVType);
    uint32_t imm = Bits(kRvvImm5Shift + kRvvImm5Bits - 1, kRvvImm5Shift);
    return zext(imm, kRvvImm5Bits);
  }

  inline bool AqValue() const { return Bits(kAqShift, kAqShift); }

  inline bool RlValue() const { return Bits(kRlShift, kRlShift); }

  /// Setters

  inline void SetRdValue(int rd) {
    MOZ_ASSERT(InstructionType() == InstructionBase::kRType ||
               InstructionType() == InstructionBase::kR4Type ||
               InstructionType() == InstructionBase::kIType ||
               InstructionType() == InstructionBase::kSType ||
               InstructionType() == InstructionBase::kUType ||
               InstructionType() == InstructionBase::kJType ||
               InstructionType() == InstructionBase::kVType);
    MOZ_ASSERT(is_uintn(rd, kRdBits));

    Instr bits = InstructionBits() & ~kRdFieldMask;
    SetInstructionBits((rd << kRdShift) | bits);
  }

  inline void SetRs1Value(int rs1) {
    MOZ_ASSERT(InstructionType() == InstructionBase::kRType ||
               InstructionType() == InstructionBase::kR4Type ||
               InstructionType() == InstructionBase::kIType ||
               InstructionType() == InstructionBase::kSType ||
               InstructionType() == InstructionBase::kBType ||
               InstructionType() == InstructionBase::kVType);
    MOZ_ASSERT(is_uintn(rs1, kRs1Bits));

    Instr bits = InstructionBits() & ~kRs1FieldMask;
    SetInstructionBits((rs1 << kRs1Shift) | bits);
  }

  inline void SetImm12Value(int32_t imm12) {
    MOZ_ASSERT(InstructionType() == InstructionBase::kIType);
    MOZ_ASSERT(is_uint12(imm12) || is_int12(imm12));

    // | imm[11:0] | rs1 | funct3 | rd | opcode |
    //  31       20
    Instr bits = InstructionBits() & ~kImm12Mask;
    SetInstructionBits((imm12 << kImm12Shift) | bits);
  }

  inline void SetBranchOffset(int32_t imm13) {
    MOZ_ASSERT(InstructionType() == InstructionBase::kBType);
    MOZ_ASSERT((imm13 & 1) == 0);
    MOZ_ASSERT(is_intn(imm13, kBranchOffsetBits));

    // | imm[12|10:5] | rs2 | rs1 | funct3 | imm[4:1|11] | opcode |
    //  31          25                      11          7
    Instr bits = InstructionBits() & ~kBImm12Mask;
    int32_t imm12 = ((imm13 & 0x800) >> 4) |   // bit  11
                    ((imm13 & 0x1e) << 7) |    // bits 4-1
                    ((imm13 & 0x7e0) << 20) |  // bits 10-5
                    ((imm13 & 0x1000) << 19);  // bit 12
    SetInstructionBits((imm12 & kBImm12Mask) | bits);
  }

  inline void SetImm20UValue(int32_t imm20) {
    MOZ_ASSERT(InstructionType() == InstructionBase::kUType);
    MOZ_ASSERT(is_int20(imm20) || is_uint20(imm20));

    // | imm[31:12] | rd | opcode |
    //  31        12
    Instr bits = InstructionBits() & ~kImm20Mask;
    SetInstructionBits((imm20 << kImm20Shift) | bits);
  }

  inline void SetImm20JValue(int32_t imm21) {
    MOZ_ASSERT(InstructionType() == InstructionBase::kJType);
    MOZ_ASSERT((imm21 & 1) == 0);
    MOZ_ASSERT(is_intn(imm21, kJumpOffsetBits));

    // | imm[20|10:1|11|19:12] | rd | opcode |
    //  31                   12
    Instr bits = InstructionBits() & ~kImm20Mask;
    int32_t imm20 = (imm21 & 0xff000) |          // bits 19-12
                    ((imm21 & 0x800) << 9) |     // bit  11
                    ((imm21 & 0x7fe) << 20) |    // bits 10-1
                    ((imm21 & 0x100000) << 11);  // bit  20
    SetInstructionBits((imm20 & kImm20Mask) | bits);
  }

  inline void SetShamt(int32_t shamt) {
    // Valid only for shift instructions (SLLI, SRLI, SRAI)
    MOZ_ASSERT(((InstructionBits() & kBaseOpcodeMask) == OP_IMM ||
                (InstructionBits() & kBaseOpcodeMask) == OP_IMM_32) &&
               (Funct3Value() == 0b001 || Funct3Value() == 0b101));
    MOZ_ASSERT_IF((InstructionBits() & kBaseOpcodeMask) == OP_IMM,
                  0 <= shamt && shamt <= 63);
    MOZ_ASSERT_IF((InstructionBits() & kBaseOpcodeMask) == OP_IMM_32,
                  0 <= shamt && shamt <= 31);

    // SLLI, SRLI, SRAI:
    // | 0A0000 | shamt | rs1 | funct3 | rd | opcode |
    //  31       25    20
    //
    // SLLIW, SRLIW, SRAIW:
    // | 0A00000 | shamt | rs1 | funct3 | rd | opcode |
    //  31        24   20
    int32_t imm12 = ((InstructionBits() & 0x40000000) >> kImm12Shift) | shamt;
    SetImm12Value(imm12);
  }

  /// Compound setters

  void SetIFormat(OpcodeRISCV32I opcode, int rd, int rs1, int32_t imm12) {
    SetInstructionBits(opcode);
    MOZ_ASSERT(InstructionType() == kIType);

    SetRdValue(rd);
    SetRs1Value(rs1);
    SetImm12Value(imm12);
  }

  void SetJFormat(OpcodeRISCV32I opcode, int rd, int32_t imm21) {
    SetInstructionBits(opcode);
    MOZ_ASSERT(InstructionType() == kJType);

    SetRdValue(rd);
    SetImm20JValue(imm21);
  }

  void SetUFormat(OpcodeRISCV32I opcode, int rd, int32_t imm20) {
    SetInstructionBits(opcode);
    MOZ_ASSERT(InstructionType() == kUType);

    SetRdValue(rd);
    SetImm20UValue(imm20);
  }

  void SetNop() { SetInstructionBits(kNopByte); }

 protected:
  InstructionBase() {}
};

class Instruction : public 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(uint8_t* pc) {
    return reinterpret_cast<Instruction*>(pc);
  }
  static const Instruction* At(const uint8_t* pc) {
    return reinterpret_cast<const Instruction*>(pc);
  }

  // We need to prevent the creation of instances of class Instruction.
  Instruction() = delete;
  Instruction(const Instruction&) = delete;
  Instruction& operator=(const Instruction&) = delete;
};

}  // namespace js::jit

#endif  //  jit_riscv64_base_Instruction_h

Messung V0.5 in Prozent
C=87 H=100 G=93

¤ Dauer der Verarbeitung: 0.14 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002