//===-- 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>; // 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> { bits<7> Value = val; } def OPC_LOAD : RISCVOpcode<0b0000011>; def OPC_LOAD_FP : RISCVOpcode<0b0000111>; def OPC_MISC_MEM : RISCVOpcode<0b0001111>; def OPC_OP_IMM : RISCVOpcode<0b0010011>; def OPC_AUIPC : RISCVOpcode<0b0010111>; def OPC_OP_IMM_32 : RISCVOpcode<0b0011011>; def OPC_STORE : RISCVOpcode<0b0100011>; def OPC_STORE_FP : RISCVOpcode<0b0100111>; def OPC_AMO : RISCVOpcode<0b0101111>; def OPC_OP : RISCVOpcode<0b0110011>; def OPC_LUI : RISCVOpcode<0b0110111>; def OPC_OP_32 : RISCVOpcode<0b0111011>; def OPC_MADD : RISCVOpcode<0b1000011>; def OPC_MSUB : RISCVOpcode<0b1000111>; def OPC_NMSUB : RISCVOpcode<0b1001011>; def OPC_NMADD : RISCVOpcode<0b1001111>; def OPC_OP_FP : RISCVOpcode<0b1010011>; def OPC_BRANCH : RISCVOpcode<0b1100011>; def OPC_JALR : RISCVOpcode<0b1100111>; def OPC_JAL : RISCVOpcode<0b1101111>; def OPC_SYSTEM : RISCVOpcode<0b1110011>; 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; } // Pseudo instructions class Pseudo pattern, string opcodestr = "", string argstr = ""> : RVInst { let isPseudo = 1; let isCodeGenOnly = 1; } // 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 rdty:$rd, GPR:$tmp), (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 rsty:$rs, GPR:$tmp), (ins 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, RISCVOpcode opcode, dag outs, dag ins, string opcodestr, string argstr> : RVInst { bits<5> rs3; bits<5> rs2; bits<5> rs1; bits<3> funct3; 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 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> funct3; 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 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 funct3, RISCVOpcode opcode, dag outs, dag ins, string opcodestr, string argstr> : RVInst { bits<6> shamt; bits<5> rs1; bits<5> rd; let Inst{31} = 0; let Inst{30} = arithshift; let Inst{29-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 funct3, RISCVOpcode opcode, dag outs, dag ins, string opcodestr, string argstr> : RVInst { bits<5> shamt; bits<5> rs1; bits<5> rd; let Inst{31} = 0; let Inst{30} = arithshift; let Inst{29-25} = 0; 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; }