//===-- RISCVInstrInfo.td - Target Description for RISCV ---*- tablegen -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file describes the RISC-V instructions in TableGen format. // //===----------------------------------------------------------------------===// include "RISCVInstrFormats.td" //===----------------------------------------------------------------------===// // RISC-V specific DAG Nodes. //===----------------------------------------------------------------------===// def SDT_RISCVCall : SDTypeProfile<0, -1, [SDTCisVT<0, XLenVT>]>; def SDT_RISCVCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; def SDT_RISCVCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; def SDT_RISCVSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>, SDTCisSameAs<0, 4>, SDTCisSameAs<4, 5>]>; def Call : SDNode<"RISCVISD::CALL", SDT_RISCVCall, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>; def CallSeqStart : SDNode<"ISD::CALLSEQ_START", SDT_RISCVCallSeqStart, [SDNPHasChain, SDNPOutGlue]>; def CallSeqEnd : SDNode<"ISD::CALLSEQ_END", SDT_RISCVCallSeqEnd, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; def RetFlag : SDNode<"RISCVISD::RET_FLAG", SDTNone, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; def SelectCC : SDNode<"RISCVISD::SELECT_CC", SDT_RISCVSelectCC, [SDNPInGlue]>; //===----------------------------------------------------------------------===// // Operand and SDNode transformation definitions. //===----------------------------------------------------------------------===// class ImmAsmOperand : AsmOperandClass { let Name = prefix # "Imm" # width # suffix; let RenderMethod = "addImmOperands"; let DiagnosticType = !strconcat("Invalid", Name); } class SImmAsmOperand : ImmAsmOperand<"S", width, suffix> { } class UImmAsmOperand : ImmAsmOperand<"U", width, suffix> { } def FenceArg : AsmOperandClass { let Name = "FenceArg"; let RenderMethod = "addFenceArgOperands"; let DiagnosticType = "InvalidFenceArg"; } def fencearg : Operand { let ParserMatchClass = FenceArg; let PrintMethod = "printFenceArg"; let DecoderMethod = "decodeUImmOperand<4>"; } def UImmLog2XLenAsmOperand : AsmOperandClass { let Name = "UImmLog2XLen"; let RenderMethod = "addImmOperands"; let DiagnosticType = "InvalidUImmLog2XLen"; } def uimmlog2xlen : Operand, ImmLeafis64Bit()) return isUInt<6>(Imm); return isUInt<5>(Imm); }]> { let ParserMatchClass = UImmLog2XLenAsmOperand; // TODO: should ensure invalid shamt is rejected when decoding. let DecoderMethod = "decodeUImmOperand<6>"; } def uimm5 : Operand, ImmLeaf(Imm);}]> { let ParserMatchClass = UImmAsmOperand<5>; let DecoderMethod = "decodeUImmOperand<5>"; } def simm12 : Operand, ImmLeaf(Imm);}]> { let ParserMatchClass = SImmAsmOperand<12>; let EncoderMethod = "getImmOpValue"; let DecoderMethod = "decodeSImmOperand<12>"; } def uimm12 : Operand { let ParserMatchClass = UImmAsmOperand<12>; let DecoderMethod = "decodeUImmOperand<12>"; } // A 13-bit signed immediate where the least significant bit is zero. def simm13_lsb0 : Operand { let ParserMatchClass = SImmAsmOperand<13, "Lsb0">; let EncoderMethod = "getImmOpValueAsr1"; let DecoderMethod = "decodeSImmOperandAndLsl1<13>"; } def uimm20 : Operand { let ParserMatchClass = UImmAsmOperand<20>; let EncoderMethod = "getImmOpValue"; let DecoderMethod = "decodeUImmOperand<20>"; } // A 21-bit signed immediate where the least significant bit is zero. def simm21_lsb0 : Operand { let ParserMatchClass = SImmAsmOperand<21, "Lsb0">; let EncoderMethod = "getImmOpValueAsr1"; let DecoderMethod = "decodeSImmOperandAndLsl1<21>"; } // A parameterized register class alternative to i32imm/i64imm from Target.td. def ixlenimm : Operand; // Standalone (codegen-only) immleaf patterns. def simm32 : ImmLeaf(Imm);}]>; // Addressing modes. // Necessary because a frameindex can't be matched directly in a pattern. def AddrFI : ComplexPattern; // Extract least significant 12 bits from an immediate value and sign extend // them. def LO12Sext : SDNodeXFormgetTargetConstant(SignExtend64<12>(N->getZExtValue()), SDLoc(N), N->getValueType(0)); }]>; // Extract the most significant 20 bits from an immediate value. Add 1 if bit // 11 is 1, to compensate for the low 12 bits in the matching immediate addi // or ld/st being negative. def HI20 : SDNodeXFormgetTargetConstant(((N->getZExtValue()+0x800) >> 12) & 0xfffff, SDLoc(N), N->getValueType(0)); }]>; //===----------------------------------------------------------------------===// // Instruction Class Templates //===----------------------------------------------------------------------===// let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class BranchCC_rri funct3, string opcodestr> : RVInstB { let isBranch = 1; let isTerminator = 1; } let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in class Load_ri funct3, string opcodestr> : RVInstI; // Operands for stores are in the order srcreg, base, offset rather than // reflecting the order these fields are specified in the instruction // encoding. let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in class Store_rri funct3, string opcodestr> : RVInstS; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class ALU_ri funct3, string opcodestr> : RVInstI; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class Shift_ri funct3, string opcodestr> : RVInstIShift; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class ALU_rr funct7, bits<3> funct3, string opcodestr> : RVInstR; let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in class CSR_ir funct3, string opcodestr> : RVInstI; let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in class CSR_ii funct3, string opcodestr> : RVInstI; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class ShiftW_ri funct3, string opcodestr> : RVInstIShiftW; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class ALUW_rr funct7, bits<3> funct3, string opcodestr> : RVInstR; let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in class Priv funct7> : RVInstR; //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { def LUI : RVInstU; def AUIPC : RVInstU; let isCall = 1 in def JAL : RVInstJ; let isCall = 1 in def JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), "jalr", "$rd, $rs1, $imm12">; } // hasSideEffects = 0, mayLoad = 0, mayStore = 0 def BEQ : BranchCC_rri<0b000, "beq">; def BNE : BranchCC_rri<0b001, "bne">; def BLT : BranchCC_rri<0b100, "blt">; def BGE : BranchCC_rri<0b101, "bge">; def BLTU : BranchCC_rri<0b110, "bltu">; def BGEU : BranchCC_rri<0b111, "bgeu">; def LB : Load_ri<0b000, "lb">; def LH : Load_ri<0b001, "lh">; def LW : Load_ri<0b010, "lw">; def LBU : Load_ri<0b100, "lbu">; def LHU : Load_ri<0b101, "lhu">; def SB : Store_rri<0b000, "sb">; def SH : Store_rri<0b001, "sh">; def SW : Store_rri<0b010, "sw">; def ADDI : ALU_ri<0b000, "addi">; def SLTI : ALU_ri<0b010, "slti">; def SLTIU : ALU_ri<0b011, "sltiu">; def XORI : ALU_ri<0b100, "xori">; def ORI : ALU_ri<0b110, "ori">; def ANDI : ALU_ri<0b111, "andi">; def SLLI : Shift_ri<0, 0b001, "slli">; def SRLI : Shift_ri<0, 0b101, "srli">; def SRAI : Shift_ri<1, 0b101, "srai">; def ADD : ALU_rr<0b0000000, 0b000, "add">; def SUB : ALU_rr<0b0100000, 0b000, "sub">; def SLL : ALU_rr<0b0000000, 0b001, "sll">; def SLT : ALU_rr<0b0000000, 0b010, "slt">; def SLTU : ALU_rr<0b0000000, 0b011, "sltu">; def XOR : ALU_rr<0b0000000, 0b100, "xor">; def SRL : ALU_rr<0b0000000, 0b101, "srl">; def SRA : ALU_rr<0b0100000, 0b101, "sra">; def OR : ALU_rr<0b0000000, 0b110, "or">; def AND : ALU_rr<0b0000000, 0b111, "and">; let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins fencearg:$pred, fencearg:$succ), "fence", "$pred, $succ"> { bits<4> pred; bits<4> succ; let rs1 = 0; let rd = 0; let imm12 = {0b0000,pred,succ}; } def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", ""> { let rs1 = 0; let rd = 0; let imm12 = 0; } def ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", ""> { let rs1 = 0; let rd = 0; let imm12 = 0; } def EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", ""> { let rs1 = 0; let rd = 0; let imm12 = 1; } } // hasSideEffects = 1, mayLoad = 0, mayStore = 0 def CSRRW : CSR_ir<0b001, "csrrw">; def CSRRS : CSR_ir<0b010, "csrrs">; def CSRRC : CSR_ir<0b011, "csrrc">; def CSRRWI : CSR_ii<0b101, "csrrwi">; def CSRRSI : CSR_ii<0b110, "csrrsi">; def CSRRCI : CSR_ii<0b111, "csrrci">; /// RV64I instructions let Predicates = [IsRV64] in { def LWU : Load_ri<0b110, "lwu">; def LD : Load_ri<0b011, "ld">; def SD : Store_rri<0b011, "sd">; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), "addiw", "$rd, $rs1, $imm12">; def SLLIW : ShiftW_ri<0, 0b001, "slliw">; def SRLIW : ShiftW_ri<0, 0b101, "srliw">; def SRAIW : ShiftW_ri<1, 0b101, "sraiw">; def ADDW : ALUW_rr<0b0000000, 0b000, "addw">; def SUBW : ALUW_rr<0b0100000, 0b000, "subw">; def SLLW : ALUW_rr<0b0000000, 0b001, "sllw">; def SRLW : ALUW_rr<0b0000000, 0b101, "srlw">; def SRAW : ALUW_rr<0b0100000, 0b101, "sraw">; } // Predicates = [IsRV64] //===----------------------------------------------------------------------===// // Privileged instructions //===----------------------------------------------------------------------===// let isBarrier = 1, isReturn = 1, isTerminator = 1 in { def URET : Priv<"uret", 0b0000000> { let rd = 0; let rs1 = 0; let rs2 = 0b00010; } def SRET : Priv<"sret", 0b0001000> { let rd = 0; let rs1 = 0; let rs2 = 0b00010; } def MRET : Priv<"mret", 0b0011000> { let rd = 0; let rs1 = 0; let rs2 = 0b00010; } } // isBarrier = 1, isReturn = 1, isTerminator = 1 def WFI : Priv<"wfi", 0b0001000> { let rd = 0; let rs1 = 0; let rs2 = 0b00101; } let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in def SFENCE_VMA : RVInstR<0b0001001, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2), "sfence.vma", "$rs1, $rs2"> { let rd = 0; } //===----------------------------------------------------------------------===// // Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) //===----------------------------------------------------------------------===// // TODO la // TODO lb lh lw // TODO RV64I: ld // TODO sb sh sw // TODO RV64I: sd def : InstAlias<"nop", (ADDI X0, X0, 0)>; // TODO li def : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>; def : InstAlias<"not $rd, $rs", (XORI GPR:$rd, GPR:$rs, -1)>; def : InstAlias<"neg $rd, $rs", (SUB GPR:$rd, X0, GPR:$rs)>; let Predicates = [IsRV64] in { def : InstAlias<"negw $rd, $rs", (SUBW GPR:$rd, X0, GPR:$rs)>; def : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs, 0)>; } // Predicates = [IsRV64] def : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs, 1)>; def : InstAlias<"snez $rd, $rs", (SLTU GPR:$rd, X0, GPR:$rs)>; def : InstAlias<"sltz $rd, $rs", (SLT GPR:$rd, GPR:$rs, X0)>; def : InstAlias<"sgtz $rd, $rs", (SLT GPR:$rd, X0, GPR:$rs)>; def : InstAlias<"beqz $rs, $offset", (BEQ GPR:$rs, X0, simm13_lsb0:$offset)>; def : InstAlias<"bnez $rs, $offset", (BNE GPR:$rs, X0, simm13_lsb0:$offset)>; def : InstAlias<"blez $rs, $offset", (BGE X0, GPR:$rs, simm13_lsb0:$offset)>; def : InstAlias<"bgez $rs, $offset", (BGE GPR:$rs, X0, simm13_lsb0:$offset)>; def : InstAlias<"bltz $rs, $offset", (BLT GPR:$rs, X0, simm13_lsb0:$offset)>; def : InstAlias<"bgtz $rs, $offset", (BLT X0, GPR:$rs, simm13_lsb0:$offset)>; // Always output the canonical mnemonic for the pseudo branch instructions. // The GNU tools emit the canonical mnemonic for the branch pseudo instructions // as well (e.g. "bgt" will be recognised by the assembler but never printed by // objdump). Match this behaviour by setting a zero weight. def : InstAlias<"bgt $rs, $rt, $offset", (BLT GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; def : InstAlias<"ble $rs, $rt, $offset", (BGE GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; def : InstAlias<"bgtu $rs, $rt, $offset", (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; def : InstAlias<"bleu $rs, $rt, $offset", (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; // "ret" has more weight since "ret" and "jr" alias the same "jalr" instruction. def : InstAlias<"j $offset", (JAL X0, simm21_lsb0:$offset)>; def : InstAlias<"jal $offset", (JAL X1, simm21_lsb0:$offset)>; def : InstAlias<"jr $rs", (JALR X0, GPR:$rs, 0)>; def : InstAlias<"jalr $rs", (JALR X1, GPR:$rs, 0)>; def : InstAlias<"ret", (JALR X0, X1, 0), 2>; // TODO call // TODO tail def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw // CSR Addresses: 0xC00 == cycle, 0xC01 == time, 0xC02 == instret // 0xC80 == cycleh, 0xC81 == timeh, 0xC82 == instreth def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, 0xC02, X0)>; def : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, 0xC00, X0)>; def : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, 0xC01, X0)>; let Predicates = [IsRV32] in { def : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, 0xC82, X0)>; def : InstAlias<"rdcycleh $rd", (CSRRS GPR:$rd, 0xC80, X0)>; def : InstAlias<"rdtimeh $rd", (CSRRS GPR:$rd, 0xC81, X0)>; } // Predicates = [IsRV32] def : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, uimm12:$csr, X0)>; def : InstAlias<"csrw $csr, $rs", (CSRRW X0, uimm12:$csr, GPR:$rs)>; def : InstAlias<"csrs $csr, $rs", (CSRRS X0, uimm12:$csr, GPR:$rs)>; def : InstAlias<"csrc $csr, $rs", (CSRRC X0, uimm12:$csr, GPR:$rs)>; def : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, uimm12:$csr, uimm5:$imm)>; def : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, uimm12:$csr, uimm5:$imm)>; def : InstAlias<"csrci $csr, $imm", (CSRRCI X0, uimm12:$csr, uimm5:$imm)>; def : InstAlias<"sfence.vma", (SFENCE_VMA X0, X0)>; def : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>; //===----------------------------------------------------------------------===// // Pseudo-instructions and codegen patterns // // Naming convention: For 'generic' pattern classes, we use the naming // convention PatTy1Ty2. For pattern classes which offer a more complex // expension, prefix the class name, e.g. BccPat. //===----------------------------------------------------------------------===// /// Generic pattern classes class PatGprGpr : Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>; class PatGprSimm12 : Pat<(OpNode GPR:$rs1, simm12:$imm12), (Inst GPR:$rs1, simm12:$imm12)>; class PatGprUimmLog2XLen : Pat<(OpNode GPR:$rs1, uimmlog2xlen:$shamt), (Inst GPR:$rs1, uimmlog2xlen:$shamt)>; /// Predicates def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{ return isOrEquivalentToAdd(N); }]>; /// Immediates def : Pat<(simm12:$imm), (ADDI X0, simm12:$imm)>; // TODO: Add a pattern for immediates with all zeroes in the lower 12 bits. def : Pat<(simm32:$imm), (ADDI (LUI (HI20 imm:$imm)), (LO12Sext imm:$imm))>; /// Simple arithmetic operations def : PatGprGpr; def : PatGprSimm12; def : PatGprGpr; def : PatGprGpr; def : PatGprSimm12; def : PatGprGpr; def : PatGprSimm12; def : PatGprGpr; def : PatGprSimm12; def : PatGprGpr; def : PatGprUimmLog2XLen; def : PatGprGpr; def : PatGprUimmLog2XLen; def : PatGprGpr; def : PatGprUimmLog2XLen; /// FrameIndex calculations def : Pat<(add (i32 AddrFI:$Rs), simm12:$imm12), (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>; def : Pat<(IsOrAdd (i32 AddrFI:$Rs), simm12:$imm12), (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>; /// Setcc def : PatGprGpr; def : PatGprSimm12; def : PatGprGpr; def : PatGprSimm12; // Define pattern expansions for setcc operations that aren't directly // handled by a RISC-V instruction. def : Pat<(seteq GPR:$rs1, GPR:$rs2), (SLTIU (XOR GPR:$rs1, GPR:$rs2), 1)>; def : Pat<(setne GPR:$rs1, GPR:$rs2), (SLTU X0, (XOR GPR:$rs1, GPR:$rs2))>; def : Pat<(setugt GPR:$rs1, GPR:$rs2), (SLTU GPR:$rs2, GPR:$rs1)>; def : Pat<(setuge GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs1, GPR:$rs2), 1)>; def : Pat<(setule GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs2, GPR:$rs1), 1)>; def : Pat<(setgt GPR:$rs1, GPR:$rs2), (SLT GPR:$rs2, GPR:$rs1)>; def : Pat<(setge GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs1, GPR:$rs2), 1)>; def : Pat<(setle GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs2, GPR:$rs1), 1)>; let usesCustomInserter = 1 in def Select_GPR_Using_CC_GPR : Pseudo<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs, ixlenimm:$imm, GPR:$src, GPR:$src2), [(set XLenVT:$dst, (SelectCC GPR:$lhs, GPR:$rhs, (XLenVT imm:$imm), GPR:$src, GPR:$src2))]>; /// Branches and jumps // Match `(brcond (CondOp ..), ..)` and lower to the appropriate RISC-V branch // instruction. class BccPat : Pat<(brcond (i32 (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12), (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>; def : BccPat; def : BccPat; def : BccPat; def : BccPat; def : BccPat; def : BccPat; class BccSwapPat : Pat<(brcond (i32 (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12), (InstBcc GPR:$rs2, GPR:$rs1, bb:$imm12)>; // Condition codes that don't have matching RISC-V branch instructions, but // are trivially supported by swapping the two input operands def : BccSwapPat; def : BccSwapPat; def : BccSwapPat; def : BccSwapPat; // An extra pattern is needed for a brcond without a setcc (i.e. where the // condition was calculated elsewhere). def : Pat<(brcond GPR:$cond, bb:$imm12), (BNE GPR:$cond, X0, bb:$imm12)>; let isBarrier = 1, isBranch = 1, isTerminator = 1 in def PseudoBR : Pseudo<(outs), (ins simm21_lsb0:$imm20), [(br bb:$imm20)]>, PseudoInstExpansion<(JAL X0, simm21_lsb0:$imm20)>; let isCall = 1, Defs=[X1] in let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in def PseudoBRIND : Pseudo<(outs), (ins GPR:$rs1, simm12:$imm12), []>, PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; def : Pat<(brind GPR:$rs1), (PseudoBRIND GPR:$rs1, 0)>; def : Pat<(brind (add GPR:$rs1, simm12:$imm12)), (PseudoBRIND GPR:$rs1, simm12:$imm12)>; let isCall = 1, Defs = [X1] in def PseudoCALL : Pseudo<(outs), (ins GPR:$rs1), [(Call GPR:$rs1)]>, PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>; let isBarrier = 1, isReturn = 1, isTerminator = 1 in def PseudoRET : Pseudo<(outs), (ins), [(RetFlag)]>, PseudoInstExpansion<(JALR X0, X1, 0)>; /// Loads multiclass LdPat { def : Pat<(LoadOp GPR:$rs1), (Inst GPR:$rs1, 0)>; def : Pat<(LoadOp AddrFI:$rs1), (Inst AddrFI:$rs1, 0)>; def : Pat<(LoadOp (add GPR:$rs1, simm12:$imm12)), (Inst GPR:$rs1, simm12:$imm12)>; def : Pat<(LoadOp (add AddrFI:$rs1, simm12:$imm12)), (Inst AddrFI:$rs1, simm12:$imm12)>; def : Pat<(LoadOp (IsOrAdd AddrFI:$rs1, simm12:$imm12)), (Inst AddrFI:$rs1, simm12:$imm12)>; } defm : LdPat; defm : LdPat; defm : LdPat; defm : LdPat; defm : LdPat; defm : LdPat; defm : LdPat; /// Stores multiclass StPat { def : Pat<(StoreOp GPR:$rs2, GPR:$rs1), (Inst GPR:$rs2, GPR:$rs1, 0)>; def : Pat<(StoreOp GPR:$rs2, AddrFI:$rs1), (Inst GPR:$rs2, AddrFI:$rs1, 0)>; def : Pat<(StoreOp GPR:$rs2, (add GPR:$rs1, simm12:$imm12)), (Inst GPR:$rs2, GPR:$rs1, simm12:$imm12)>; def : Pat<(StoreOp GPR:$rs2, (add AddrFI:$rs1, simm12:$imm12)), (Inst GPR:$rs2, AddrFI:$rs1, simm12:$imm12)>; def : Pat<(StoreOp GPR:$rs2, (IsOrAdd AddrFI:$rs1, simm12:$imm12)), (Inst GPR:$rs2, AddrFI:$rs1, simm12:$imm12)>; } defm : StPat; defm : StPat; defm : StPat; /// Other pseudo-instructions // Pessimistically assume the stack pointer will be clobbered let Defs = [X2], Uses = [X2] in { def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), [(CallSeqStart timm:$amt1, timm:$amt2)]>; def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), [(CallSeqEnd timm:$amt1, timm:$amt2)]>; } // Defs = [X2], Uses = [X2] //===----------------------------------------------------------------------===// // Standard extensions //===----------------------------------------------------------------------===// include "RISCVInstrInfoM.td" include "RISCVInstrInfoA.td" include "RISCVInstrInfoF.td" include "RISCVInstrInfoD.td" include "RISCVInstrInfoC.td"