//===-- RISCVInstrFormats.td - RISCV Instruction Formats ---*- tablegen -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // // These instruction format definitions are structured to match the // description in the RISC-V User-Level ISA specification as closely as // possible. For instance, the specification describes instructions with the // MSB (31st bit) on the left and the LSB (0th bit) on the right. This is // reflected in the order of parameters to each instruction class. // // One area of divergence is in the description of immediates. The // specification describes immediate encoding in terms of bit-slicing // operations on the logical value represented. The immediate argument to // these instruction formats instead represents the bit sequence that will be // inserted into the instruction. e.g. although JAL's immediate is logically // a 21-bit value (where the LSB is always zero), we describe it as an imm20 // to match how it is encoded. // //===----------------------------------------------------------------------===// // Format specifies the encoding used by the instruction. This is used by // RISCVMCCodeEmitter to determine which form of fixup to use. These // definitions must be kept in-sync with RISCVBaseInfo.h. class InstFormat val> { bits<5> Value = val; } def InstFormatPseudo : InstFormat<0>; def InstFormatR : InstFormat<1>; def InstFormatR4 : InstFormat<2>; def InstFormatI : InstFormat<3>; def InstFormatS : InstFormat<4>; def InstFormatB : InstFormat<5>; def InstFormatU : InstFormat<6>; def InstFormatJ : InstFormat<7>; def InstFormatCR : InstFormat<8>; def InstFormatCI : InstFormat<9>; def InstFormatCSS : InstFormat<10>; def InstFormatCIW : InstFormat<11>; def InstFormatCL : InstFormat<12>; def InstFormatCS : InstFormat<13>; def InstFormatCA : InstFormat<14>; def InstFormatCB : InstFormat<15>; def InstFormatCJ : InstFormat<16>; def InstFormatOther : InstFormat<17>; class RISCVVConstraint val> { bits<3> Value = val; } def NoConstraint : RISCVVConstraint<0b000>; def VS2Constraint : RISCVVConstraint<0b001>; def VS1Constraint : RISCVVConstraint<0b010>; def VMConstraint : RISCVVConstraint<0b100>; // Illegal instructions: // // * The destination vector register group for a masked vector instruction // cannot overlap the source mask register (v0), unless the destination vector // register is being written with a mask value (e.g., comparisons) or the // scalar result of a reduction. // // * Widening: The destination EEW is greater than the source EEW, the source // EMUL is at least 1. The destination vector register group cannot overlap // with the source vector register groups besides the highest-numbered part of // the destination register group. // // * Narrowing: The destination EEW is smaller than the source EEW. The // destination vector register group cannot overlap with the source vector // register groups besides the lowest-numbered part of the source register // group. // // * vmsbf.m/vmsif.m/vmsof.m: The destination register cannot overlap the // source register and, if masked, cannot overlap the mask register ('v0'). // // * viota: The destination register cannot overlap the source register and, // if masked, cannot overlap the mask register ('v0'). // // * v[f]slide[1]up: The destination vector register group for vslideup cannot // overlap the source vector register group. // // * vrgather: The destination vector register group cannot overlap with the // source vector register groups. // // * vcompress: The destination vector register group cannot overlap the // source vector register group or the source mask register def WidenV : RISCVVConstraint; def WidenW : RISCVVConstraint; def WidenCvt : RISCVVConstraint; def Iota : RISCVVConstraint; def SlideUp : RISCVVConstraint; def Vrgather : RISCVVConstraint; def Vcompress : RISCVVConstraint; // The following opcode names match those given in Table 19.1 in the // RISC-V User-level ISA specification ("RISC-V base opcode map"). class RISCVOpcode val> { string Name = name; bits<7> Value = val; } def RISCVOpcodesList : GenericTable { let FilterClass = "RISCVOpcode"; let Fields = [ "Name", "Value" ]; let PrimaryKey = [ "Value" ]; let PrimaryKeyName = "lookupRISCVOpcodeByValue"; } def lookupRISCVOpcodeByName : SearchIndex { let Table = RISCVOpcodesList; let Key = [ "Name" ]; } def OPC_LOAD : RISCVOpcode<"LOAD", 0b0000011>; def OPC_LOAD_FP : RISCVOpcode<"LOAD_FP", 0b0000111>; def OPC_CUSTOM_0 : RISCVOpcode<"CUSTOM_0", 0b0001011>; def OPC_MISC_MEM : RISCVOpcode<"MISC_MEM", 0b0001111>; def OPC_OP_IMM : RISCVOpcode<"OP_IMM", 0b0010011>; def OPC_AUIPC : RISCVOpcode<"AUIPC", 0b0010111>; def OPC_OP_IMM_32 : RISCVOpcode<"OP_IMM_32", 0b0011011>; def OPC_STORE : RISCVOpcode<"STORE", 0b0100011>; def OPC_STORE_FP : RISCVOpcode<"STORE_FP", 0b0100111>; def OPC_CUSTOM_1 : RISCVOpcode<"CUSTOM_1", 0b0101011>; def OPC_AMO : RISCVOpcode<"AMO", 0b0101111>; def OPC_OP : RISCVOpcode<"OP", 0b0110011>; def OPC_LUI : RISCVOpcode<"LUI", 0b0110111>; def OPC_OP_32 : RISCVOpcode<"OP_32", 0b0111011>; def OPC_MADD : RISCVOpcode<"MADD", 0b1000011>; def OPC_MSUB : RISCVOpcode<"MSUB", 0b1000111>; def OPC_NMSUB : RISCVOpcode<"NMSUB", 0b1001011>; def OPC_NMADD : RISCVOpcode<"NMADD", 0b1001111>; def OPC_OP_FP : RISCVOpcode<"OP_FP", 0b1010011>; def OPC_OP_V : RISCVOpcode<"OP_V", 0b1010111>; def OPC_CUSTOM_2 : RISCVOpcode<"CUSTOM_2", 0b1011011>; def OPC_BRANCH : RISCVOpcode<"BRANCH", 0b1100011>; def OPC_JALR : RISCVOpcode<"JALR", 0b1100111>; def OPC_JAL : RISCVOpcode<"JAL", 0b1101111>; def OPC_SYSTEM : RISCVOpcode<"SYSTEM", 0b1110011>; def OPC_CUSTOM_3 : RISCVOpcode<"CUSTOM_3", 0b1111011>; class RVInst pattern, InstFormat format> : Instruction { field bits<32> Inst; // SoftFail is a field the disassembler can use to provide a way for // instructions to not match without killing the whole decode process. It is // mainly used for ARM, but Tablegen expects this field to exist or it fails // to build the decode table. field bits<32> SoftFail = 0; let Size = 4; bits<7> Opcode = 0; let Inst{6-0} = Opcode; let Namespace = "RISCV"; dag OutOperandList = outs; dag InOperandList = ins; let AsmString = opcodestr # "\t" # argstr; let Pattern = pattern; let TSFlags{4-0} = format.Value; // Defaults RISCVVConstraint RVVConstraint = NoConstraint; let TSFlags{7-5} = RVVConstraint.Value; bits<3> VLMul = 0; let TSFlags{10-8} = VLMul; bit HasDummyMask = 0; let TSFlags{11} = HasDummyMask; bit ForceTailAgnostic = false; let TSFlags{12} = ForceTailAgnostic; bit HasMergeOp = 0; let TSFlags{13} = HasMergeOp; bit HasSEWOp = 0; let TSFlags{14} = HasSEWOp; bit HasVLOp = 0; let TSFlags{15} = HasVLOp; bit HasVecPolicyOp = 0; let TSFlags{16} = HasVecPolicyOp; bit IsRVVWideningReduction = 0; let TSFlags{17} = IsRVVWideningReduction; bit UsesMaskPolicy = 0; let TSFlags{18} = UsesMaskPolicy; // Indicates that the result can be considered sign extended from bit 31. Some // instructions with this flag aren't W instructions, but are either sign // extended from a smaller size, always outputs a small integer, or put zeros // in bits 63:31. Used by the SExtWRemoval pass. bit IsSignExtendingOpW = 0; let TSFlags{19} = IsSignExtendingOpW; } // Pseudo instructions class Pseudo pattern, string opcodestr = "", string argstr = ""> : RVInst { let isPseudo = 1; let isCodeGenOnly = 1; } class PseudoQuietFCMP : Pseudo<(outs GPR:$rd), (ins Ty:$rs1, Ty:$rs2), []> { let hasSideEffects = 1; let mayLoad = 0; let mayStore = 0; } // Pseudo load instructions. class PseudoLoad : Pseudo<(outs rdty:$rd), (ins bare_symbol:$addr), [], opcodestr, "$rd, $addr"> { let hasSideEffects = 0; let mayLoad = 1; let mayStore = 0; let isCodeGenOnly = 0; let isAsmParserOnly = 1; } class PseudoFloatLoad : Pseudo<(outs GPR:$tmp, rdty:$rd), (ins bare_symbol:$addr), [], opcodestr, "$rd, $addr, $tmp"> { let hasSideEffects = 0; let mayLoad = 1; let mayStore = 0; let isCodeGenOnly = 0; let isAsmParserOnly = 1; } // Pseudo store instructions. class PseudoStore : Pseudo<(outs GPR:$tmp), (ins rsty:$rs, bare_symbol:$addr), [], opcodestr, "$rs, $addr, $tmp"> { let hasSideEffects = 0; let mayLoad = 0; let mayStore = 1; let isCodeGenOnly = 0; let isAsmParserOnly = 1; } // Instruction formats are listed in the order they appear in the RISC-V // instruction set manual (R, I, S, B, U, J) with sub-formats (e.g. RVInstR4, // RVInstRAtomic) sorted alphabetically. class RVInstR funct7, bits<3> funct3, RISCVOpcode opcode, dag outs, dag ins, string opcodestr, string argstr> : RVInst { bits<5> rs2; bits<5> rs1; bits<5> rd; let Inst{31-25} = funct7; let Inst{24-20} = rs2; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = rd; let Opcode = opcode.Value; } class RVInstR4 funct2, bits<3> funct3, RISCVOpcode opcode, dag outs, dag ins, string opcodestr, string argstr> : RVInst { bits<5> rs3; bits<5> rs2; bits<5> rs1; bits<5> rd; let Inst{31-27} = rs3; let Inst{26-25} = funct2; let Inst{24-20} = rs2; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = rd; let Opcode = opcode.Value; } class RVInstR4Frm funct2, RISCVOpcode opcode, dag outs, dag ins, string opcodestr, string argstr> : RVInst { bits<5> rs3; bits<5> rs2; bits<5> rs1; bits<3> frm; bits<5> rd; let Inst{31-27} = rs3; let Inst{26-25} = funct2; let Inst{24-20} = rs2; let Inst{19-15} = rs1; let Inst{14-12} = frm; let Inst{11-7} = rd; let Opcode = opcode.Value; } class RVInstRAtomic funct5, bit aq, bit rl, bits<3> funct3, RISCVOpcode opcode, dag outs, dag ins, string opcodestr, string argstr> : RVInst { bits<5> rs2; bits<5> rs1; bits<5> rd; let Inst{31-27} = funct5; let Inst{26} = aq; let Inst{25} = rl; let Inst{24-20} = rs2; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = rd; let Opcode = opcode.Value; } class RVInstRFrm funct7, RISCVOpcode opcode, dag outs, dag ins, string opcodestr, string argstr> : RVInst { bits<5> rs2; bits<5> rs1; bits<3> frm; bits<5> rd; let Inst{31-25} = funct7; let Inst{24-20} = rs2; let Inst{19-15} = rs1; let Inst{14-12} = frm; let Inst{11-7} = rd; let Opcode = opcode.Value; } class RVInstI funct3, RISCVOpcode opcode, dag outs, dag ins, string opcodestr, string argstr> : RVInst { bits<12> imm12; bits<5> rs1; bits<5> rd; let Inst{31-20} = imm12; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = rd; let Opcode = opcode.Value; } class RVInstIShift imm11_7, bits<3> funct3, RISCVOpcode opcode, dag outs, dag ins, string opcodestr, string argstr> : RVInst { bits<6> shamt; bits<5> rs1; bits<5> rd; let Inst{31-27} = imm11_7; let Inst{26} = 0; let Inst{25-20} = shamt; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = rd; let Opcode = opcode.Value; } class RVInstIShiftW imm11_5, bits<3> funct3, RISCVOpcode opcode, dag outs, dag ins, string opcodestr, string argstr> : RVInst { bits<5> shamt; bits<5> rs1; bits<5> rd; let Inst{31-25} = imm11_5; let Inst{24-20} = shamt; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = rd; let Opcode = opcode.Value; } class RVInstS funct3, RISCVOpcode opcode, dag outs, dag ins, string opcodestr, string argstr> : RVInst { bits<12> imm12; bits<5> rs2; bits<5> rs1; let Inst{31-25} = imm12{11-5}; let Inst{24-20} = rs2; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = imm12{4-0}; let Opcode = opcode.Value; } class RVInstB funct3, RISCVOpcode opcode, dag outs, dag ins, string opcodestr, string argstr> : RVInst { bits<12> imm12; bits<5> rs2; bits<5> rs1; let Inst{31} = imm12{11}; let Inst{30-25} = imm12{9-4}; let Inst{24-20} = rs2; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-8} = imm12{3-0}; let Inst{7} = imm12{10}; let Opcode = opcode.Value; } class RVInstU : RVInst { bits<20> imm20; bits<5> rd; let Inst{31-12} = imm20; let Inst{11-7} = rd; let Opcode = opcode.Value; } class RVInstJ : RVInst { bits<20> imm20; bits<5> rd; let Inst{31} = imm20{19}; let Inst{30-21} = imm20{9-0}; let Inst{20} = imm20{10}; let Inst{19-12} = imm20{18-11}; let Inst{11-7} = rd; let Opcode = opcode.Value; } //===----------------------------------------------------------------------===// // Instruction classes for .insn directives //===----------------------------------------------------------------------===// class DirectiveInsnR : RVInst { bits<7> opcode; bits<7> funct7; bits<3> funct3; bits<5> rs2; bits<5> rs1; bits<5> rd; let Inst{31-25} = funct7; let Inst{24-20} = rs2; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = rd; let Opcode = opcode; let AsmString = ".insn r " # argstr; } class DirectiveInsnR4 : RVInst { bits<7> opcode; bits<2> funct2; bits<3> funct3; bits<5> rs3; bits<5> rs2; bits<5> rs1; bits<5> rd; let Inst{31-27} = rs3; let Inst{26-25} = funct2; let Inst{24-20} = rs2; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = rd; let Opcode = opcode; let AsmString = ".insn r4 " # argstr; } class DirectiveInsnI : RVInst { bits<7> opcode; bits<3> funct3; bits<12> imm12; bits<5> rs1; bits<5> rd; let Inst{31-20} = imm12; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = rd; let Opcode = opcode; let AsmString = ".insn i " # argstr; } class DirectiveInsnS : RVInst { bits<7> opcode; bits<3> funct3; bits<12> imm12; bits<5> rs2; bits<5> rs1; let Inst{31-25} = imm12{11-5}; let Inst{24-20} = rs2; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = imm12{4-0}; let Opcode = opcode; let AsmString = ".insn s " # argstr; } class DirectiveInsnB : RVInst { bits<7> opcode; bits<3> funct3; bits<12> imm12; bits<5> rs2; bits<5> rs1; let Inst{31} = imm12{11}; let Inst{30-25} = imm12{9-4}; let Inst{24-20} = rs2; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-8} = imm12{3-0}; let Inst{7} = imm12{10}; let Opcode = opcode; let AsmString = ".insn b " # argstr; } class DirectiveInsnU : RVInst { bits<7> opcode; bits<20> imm20; bits<5> rd; let Inst{31-12} = imm20; let Inst{11-7} = rd; let Opcode = opcode; let AsmString = ".insn u " # argstr; } class DirectiveInsnJ : RVInst { bits<7> opcode; bits<20> imm20; bits<5> rd; let Inst{31-12} = imm20; let Inst{11-7} = rd; let Opcode = opcode; let AsmString = ".insn j " # argstr; }