1//===-- RISCVInstrInfo.td - Target Description for RISCV ---*- tablegen -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file describes the RISC-V instructions in TableGen format. 10// 11//===----------------------------------------------------------------------===// 12 13//===----------------------------------------------------------------------===// 14// RISC-V specific DAG Nodes. 15//===----------------------------------------------------------------------===// 16 17// Target-independent type requirements, but with target-specific formats. 18def SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, 19 SDTCisVT<1, i32>]>; 20def SDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, 21 SDTCisVT<1, i32>]>; 22 23// Target-dependent type requirements. 24def SDT_RISCVCall : SDTypeProfile<0, -1, [SDTCisVT<0, XLenVT>]>; 25def SDT_RISCVSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>, 26 SDTCisSameAs<0, 4>, 27 SDTCisSameAs<4, 5>]>; 28 29// Target-independent nodes, but with target-specific formats. 30def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart, 31 [SDNPHasChain, SDNPOutGlue]>; 32def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd, 33 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; 34 35// Target-dependent nodes. 36def riscv_call : SDNode<"RISCVISD::CALL", SDT_RISCVCall, 37 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 38 SDNPVariadic]>; 39def riscv_ret_flag : SDNode<"RISCVISD::RET_FLAG", SDTNone, 40 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; 41def riscv_uret_flag : SDNode<"RISCVISD::URET_FLAG", SDTNone, 42 [SDNPHasChain, SDNPOptInGlue]>; 43def riscv_sret_flag : SDNode<"RISCVISD::SRET_FLAG", SDTNone, 44 [SDNPHasChain, SDNPOptInGlue]>; 45def riscv_mret_flag : SDNode<"RISCVISD::MRET_FLAG", SDTNone, 46 [SDNPHasChain, SDNPOptInGlue]>; 47def riscv_selectcc : SDNode<"RISCVISD::SELECT_CC", SDT_RISCVSelectCC, 48 [SDNPInGlue]>; 49def riscv_tail : SDNode<"RISCVISD::TAIL", SDT_RISCVCall, 50 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 51 SDNPVariadic]>; 52def riscv_sllw : SDNode<"RISCVISD::SLLW", SDTIntShiftOp>; 53def riscv_sraw : SDNode<"RISCVISD::SRAW", SDTIntShiftOp>; 54def riscv_srlw : SDNode<"RISCVISD::SRLW", SDTIntShiftOp>; 55 56//===----------------------------------------------------------------------===// 57// Operand and SDNode transformation definitions. 58//===----------------------------------------------------------------------===// 59 60class ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass { 61 let Name = prefix # "ImmXLen" # suffix; 62 let RenderMethod = "addImmOperands"; 63 let DiagnosticType = !strconcat("Invalid", Name); 64} 65 66class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass { 67 let Name = prefix # "Imm" # width # suffix; 68 let RenderMethod = "addImmOperands"; 69 let DiagnosticType = !strconcat("Invalid", Name); 70} 71 72def ImmZeroAsmOperand : AsmOperandClass { 73 let Name = "ImmZero"; 74 let RenderMethod = "addImmOperands"; 75 let DiagnosticType = !strconcat("Invalid", Name); 76} 77 78class SImmAsmOperand<int width, string suffix = ""> 79 : ImmAsmOperand<"S", width, suffix> { 80} 81 82class UImmAsmOperand<int width, string suffix = ""> 83 : ImmAsmOperand<"U", width, suffix> { 84} 85 86def FenceArg : AsmOperandClass { 87 let Name = "FenceArg"; 88 let RenderMethod = "addFenceArgOperands"; 89 let DiagnosticType = "InvalidFenceArg"; 90} 91 92def fencearg : Operand<XLenVT> { 93 let ParserMatchClass = FenceArg; 94 let PrintMethod = "printFenceArg"; 95 let DecoderMethod = "decodeUImmOperand<4>"; 96 let OperandType = "OPERAND_UIMM4"; 97 let OperandNamespace = "RISCVOp"; 98} 99 100def UImmLog2XLenAsmOperand : AsmOperandClass { 101 let Name = "UImmLog2XLen"; 102 let RenderMethod = "addImmOperands"; 103 let DiagnosticType = "InvalidUImmLog2XLen"; 104} 105 106def uimmlog2xlen : Operand<XLenVT>, ImmLeaf<XLenVT, [{ 107 if (Subtarget->is64Bit()) 108 return isUInt<6>(Imm); 109 return isUInt<5>(Imm); 110}]> { 111 let ParserMatchClass = UImmLog2XLenAsmOperand; 112 // TODO: should ensure invalid shamt is rejected when decoding. 113 let DecoderMethod = "decodeUImmOperand<6>"; 114 let MCOperandPredicate = [{ 115 int64_t Imm; 116 if (!MCOp.evaluateAsConstantImm(Imm)) 117 return false; 118 if (STI.getTargetTriple().isArch64Bit()) 119 return isUInt<6>(Imm); 120 return isUInt<5>(Imm); 121 }]; 122 let OperandType = "OPERAND_UIMMLOG2XLEN"; 123 let OperandNamespace = "RISCVOp"; 124} 125 126def uimm5 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> { 127 let ParserMatchClass = UImmAsmOperand<5>; 128 let DecoderMethod = "decodeUImmOperand<5>"; 129 let OperandType = "OPERAND_UIMM5"; 130 let OperandNamespace = "RISCVOp"; 131} 132 133def simm12 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isInt<12>(Imm);}]> { 134 let ParserMatchClass = SImmAsmOperand<12>; 135 let EncoderMethod = "getImmOpValue"; 136 let DecoderMethod = "decodeSImmOperand<12>"; 137 let MCOperandPredicate = [{ 138 int64_t Imm; 139 if (MCOp.evaluateAsConstantImm(Imm)) 140 return isInt<12>(Imm); 141 return MCOp.isBareSymbolRef(); 142 }]; 143 let OperandType = "OPERAND_SIMM12"; 144 let OperandNamespace = "RISCVOp"; 145} 146 147// A 12-bit signed immediate plus one where the imm range will be -2047~2048. 148def simm12_plus1 : Operand<XLenVT>, ImmLeaf<XLenVT, 149 [{return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048;}]> { 150 let ParserMatchClass = SImmAsmOperand<12>; 151 let EncoderMethod = "getImmOpValue"; 152 let DecoderMethod = "decodeSImmOperand<12>"; 153 let MCOperandPredicate = [{ 154 int64_t Imm; 155 if (MCOp.evaluateAsConstantImm(Imm)) 156 return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048; 157 return MCOp.isBareSymbolRef(); 158 }]; 159} 160 161// A 13-bit signed immediate where the least significant bit is zero. 162def simm13_lsb0 : Operand<OtherVT> { 163 let ParserMatchClass = SImmAsmOperand<13, "Lsb0">; 164 let EncoderMethod = "getImmOpValueAsr1"; 165 let DecoderMethod = "decodeSImmOperandAndLsl1<13>"; 166 let MCOperandPredicate = [{ 167 int64_t Imm; 168 if (MCOp.evaluateAsConstantImm(Imm)) 169 return isShiftedInt<12, 1>(Imm); 170 return MCOp.isBareSymbolRef(); 171 }]; 172 let OperandType = "OPERAND_SIMM13_LSB0"; 173 let OperandNamespace = "RISCVOp"; 174} 175 176class UImm20Operand : Operand<XLenVT> { 177 let EncoderMethod = "getImmOpValue"; 178 let DecoderMethod = "decodeUImmOperand<20>"; 179 let MCOperandPredicate = [{ 180 int64_t Imm; 181 if (MCOp.evaluateAsConstantImm(Imm)) 182 return isUInt<20>(Imm); 183 return MCOp.isBareSymbolRef(); 184 }]; 185 let OperandType = "OPERAND_UIMM20"; 186 let OperandNamespace = "RISCVOp"; 187} 188 189def uimm20_lui : UImm20Operand { 190 let ParserMatchClass = UImmAsmOperand<20, "LUI">; 191} 192def uimm20_auipc : UImm20Operand { 193 let ParserMatchClass = UImmAsmOperand<20, "AUIPC">; 194} 195 196def Simm21Lsb0JALAsmOperand : SImmAsmOperand<21, "Lsb0JAL"> { 197 let ParserMethod = "parseJALOffset"; 198} 199 200// A 21-bit signed immediate where the least significant bit is zero. 201def simm21_lsb0_jal : Operand<OtherVT> { 202 let ParserMatchClass = Simm21Lsb0JALAsmOperand; 203 let EncoderMethod = "getImmOpValueAsr1"; 204 let DecoderMethod = "decodeSImmOperandAndLsl1<21>"; 205 let MCOperandPredicate = [{ 206 int64_t Imm; 207 if (MCOp.evaluateAsConstantImm(Imm)) 208 return isShiftedInt<20, 1>(Imm); 209 return MCOp.isBareSymbolRef(); 210 }]; 211 let OperandType = "OPERAND_SIMM21_LSB0"; 212 let OperandNamespace = "RISCVOp"; 213} 214 215def BareSymbol : AsmOperandClass { 216 let Name = "BareSymbol"; 217 let RenderMethod = "addImmOperands"; 218 let DiagnosticType = "InvalidBareSymbol"; 219 let ParserMethod = "parseBareSymbol"; 220} 221 222// A bare symbol. 223def bare_symbol : Operand<XLenVT> { 224 let ParserMatchClass = BareSymbol; 225} 226 227def CallSymbol : AsmOperandClass { 228 let Name = "CallSymbol"; 229 let RenderMethod = "addImmOperands"; 230 let DiagnosticType = "InvalidCallSymbol"; 231 let ParserMethod = "parseCallSymbol"; 232} 233 234// A bare symbol used in call/tail only. 235def call_symbol : Operand<XLenVT> { 236 let ParserMatchClass = CallSymbol; 237} 238 239def PseudoJumpSymbol : AsmOperandClass { 240 let Name = "PseudoJumpSymbol"; 241 let RenderMethod = "addImmOperands"; 242 let DiagnosticType = "InvalidPseudoJumpSymbol"; 243 let ParserMethod = "parsePseudoJumpSymbol"; 244} 245 246// A bare symbol used for pseudo jumps only. 247def pseudo_jump_symbol : Operand<XLenVT> { 248 let ParserMatchClass = PseudoJumpSymbol; 249} 250 251def TPRelAddSymbol : AsmOperandClass { 252 let Name = "TPRelAddSymbol"; 253 let RenderMethod = "addImmOperands"; 254 let DiagnosticType = "InvalidTPRelAddSymbol"; 255 let ParserMethod = "parseOperandWithModifier"; 256} 257 258// A bare symbol with the %tprel_add variant. 259def tprel_add_symbol : Operand<XLenVT> { 260 let ParserMatchClass = TPRelAddSymbol; 261} 262 263def CSRSystemRegister : AsmOperandClass { 264 let Name = "CSRSystemRegister"; 265 let ParserMethod = "parseCSRSystemRegister"; 266 let DiagnosticType = "InvalidCSRSystemRegister"; 267} 268 269def csr_sysreg : Operand<XLenVT> { 270 let ParserMatchClass = CSRSystemRegister; 271 let PrintMethod = "printCSRSystemRegister"; 272 let DecoderMethod = "decodeUImmOperand<12>"; 273 let OperandType = "OPERAND_UIMM12"; 274 let OperandNamespace = "RISCVOp"; 275} 276 277// A parameterized register class alternative to i32imm/i64imm from Target.td. 278def ixlenimm : Operand<XLenVT>; 279 280def ixlenimm_li : Operand<XLenVT> { 281 let ParserMatchClass = ImmXLenAsmOperand<"", "LI">; 282} 283 284// Standalone (codegen-only) immleaf patterns. 285def simm32 : ImmLeaf<XLenVT, [{return isInt<32>(Imm);}]>; 286def simm32hi20 : ImmLeaf<XLenVT, [{return isShiftedInt<20, 12>(Imm);}]>; 287// A mask value that won't affect significant shift bits. 288def immbottomxlenset : ImmLeaf<XLenVT, [{ 289 if (Subtarget->is64Bit()) 290 return countTrailingOnes<uint64_t>(Imm) >= 6; 291 return countTrailingOnes<uint64_t>(Imm) >= 5; 292}]>; 293 294// Addressing modes. 295// Necessary because a frameindex can't be matched directly in a pattern. 296def AddrFI : ComplexPattern<iPTR, 1, "SelectAddrFI", [frameindex], []>; 297 298// Extract least significant 12 bits from an immediate value and sign extend 299// them. 300def LO12Sext : SDNodeXForm<imm, [{ 301 return CurDAG->getTargetConstant(SignExtend64<12>(N->getZExtValue()), 302 SDLoc(N), N->getValueType(0)); 303}]>; 304 305// Extract the most significant 20 bits from an immediate value. Add 1 if bit 306// 11 is 1, to compensate for the low 12 bits in the matching immediate addi 307// or ld/st being negative. 308def HI20 : SDNodeXForm<imm, [{ 309 return CurDAG->getTargetConstant(((N->getZExtValue()+0x800) >> 12) & 0xfffff, 310 SDLoc(N), N->getValueType(0)); 311}]>; 312 313// Return the negation of an immediate value. 314def NegImm : SDNodeXForm<imm, [{ 315 return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N), 316 N->getValueType(0)); 317}]>; 318 319//===----------------------------------------------------------------------===// 320// Instruction Formats 321//===----------------------------------------------------------------------===// 322 323include "RISCVInstrFormats.td" 324 325//===----------------------------------------------------------------------===// 326// Instruction Class Templates 327//===----------------------------------------------------------------------===// 328 329let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 330class BranchCC_rri<bits<3> funct3, string opcodestr> 331 : RVInstB<funct3, OPC_BRANCH, (outs), 332 (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12), 333 opcodestr, "$rs1, $rs2, $imm12">, 334 Sched<[WriteJmp, ReadJmp, ReadJmp]> { 335 let isBranch = 1; 336 let isTerminator = 1; 337} 338 339let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in 340class Load_ri<bits<3> funct3, string opcodestr> 341 : RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), 342 opcodestr, "$rd, ${imm12}(${rs1})">; 343 344// Operands for stores are in the order srcreg, base, offset rather than 345// reflecting the order these fields are specified in the instruction 346// encoding. 347let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in 348class Store_rri<bits<3> funct3, string opcodestr> 349 : RVInstS<funct3, OPC_STORE, (outs), 350 (ins GPR:$rs2, GPR:$rs1, simm12:$imm12), 351 opcodestr, "$rs2, ${imm12}(${rs1})">; 352 353let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 354class ALU_ri<bits<3> funct3, string opcodestr> 355 : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), 356 opcodestr, "$rd, $rs1, $imm12">, 357 Sched<[WriteIALU, ReadIALU]>; 358 359let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 360class Shift_ri<bit arithshift, bits<3> funct3, string opcodestr> 361 : RVInstIShift<arithshift, funct3, OPC_OP_IMM, (outs GPR:$rd), 362 (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr, 363 "$rd, $rs1, $shamt">, 364 Sched<[WriteShift, ReadShift]>; 365 366let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 367class ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr> 368 : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), 369 opcodestr, "$rd, $rs1, $rs2">; 370 371let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 372class CSR_ir<bits<3> funct3, string opcodestr> 373 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins csr_sysreg:$imm12, GPR:$rs1), 374 opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR, ReadCSR]>; 375 376let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 377class CSR_ii<bits<3> funct3, string opcodestr> 378 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), 379 (ins csr_sysreg:$imm12, uimm5:$rs1), 380 opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR]>; 381 382let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 383class ShiftW_ri<bit arithshift, bits<3> funct3, string opcodestr> 384 : RVInstIShiftW<arithshift, funct3, OPC_OP_IMM_32, (outs GPR:$rd), 385 (ins GPR:$rs1, uimm5:$shamt), opcodestr, 386 "$rd, $rs1, $shamt">, 387 Sched<[WriteShift32, ReadShift32]>; 388 389let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 390class ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr> 391 : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd), 392 (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2">; 393 394let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 395class Priv<string opcodestr, bits<7> funct7> 396 : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2), 397 opcodestr, "">; 398 399//===----------------------------------------------------------------------===// 400// Instructions 401//===----------------------------------------------------------------------===// 402 403let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { 404let isReMaterializable = 1, isAsCheapAsAMove = 1 in 405def LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20_lui:$imm20), 406 "lui", "$rd, $imm20">, Sched<[WriteIALU]>; 407 408let Predicates = [NotCapMode] in 409def AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20_auipc:$imm20), 410 "auipc", "$rd, $imm20">, Sched<[WriteIALU]>; 411 412let isCall = 1 in 413def JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20), 414 "jal", "$rd, $imm20">, Sched<[WriteJal]>; 415 416let isCall = 1 in 417def JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd), 418 (ins GPR:$rs1, simm12:$imm12), 419 "jalr", "$rd, ${imm12}(${rs1})">, 420 Sched<[WriteJalr, ReadJalr]>; 421} // hasSideEffects = 0, mayLoad = 0, mayStore = 0 422 423def BEQ : BranchCC_rri<0b000, "beq">; 424def BNE : BranchCC_rri<0b001, "bne">; 425def BLT : BranchCC_rri<0b100, "blt">; 426def BGE : BranchCC_rri<0b101, "bge">; 427def BLTU : BranchCC_rri<0b110, "bltu">; 428def BGEU : BranchCC_rri<0b111, "bgeu">; 429 430let Predicates = [NotCapMode] in { 431def LB : Load_ri<0b000, "lb">, Sched<[WriteLDB, ReadMemBase]>; 432def LH : Load_ri<0b001, "lh">, Sched<[WriteLDH, ReadMemBase]>; 433def LW : Load_ri<0b010, "lw">, Sched<[WriteLDW, ReadMemBase]>; 434def LBU : Load_ri<0b100, "lbu">, Sched<[WriteLDB, ReadMemBase]>; 435def LHU : Load_ri<0b101, "lhu">, Sched<[WriteLDH, ReadMemBase]>; 436 437def SB : Store_rri<0b000, "sb">, Sched<[WriteSTB, ReadStoreData, ReadMemBase]>; 438def SH : Store_rri<0b001, "sh">, Sched<[WriteSTH, ReadStoreData, ReadMemBase]>; 439def SW : Store_rri<0b010, "sw">, Sched<[WriteSTW, ReadStoreData, ReadMemBase]>; 440} // Predicates = [NotCapMode] 441 442// ADDI isn't always rematerializable, but isReMaterializable will be used as 443// a hint which is verified in isReallyTriviallyReMaterializable. 444let isReMaterializable = 1, isAsCheapAsAMove = 1 in 445def ADDI : ALU_ri<0b000, "addi">; 446 447def SLTI : ALU_ri<0b010, "slti">; 448def SLTIU : ALU_ri<0b011, "sltiu">; 449 450let isReMaterializable = 1, isAsCheapAsAMove = 1 in { 451def XORI : ALU_ri<0b100, "xori">; 452def ORI : ALU_ri<0b110, "ori">; 453} 454 455def ANDI : ALU_ri<0b111, "andi">; 456 457def SLLI : Shift_ri<0, 0b001, "slli">; 458def SRLI : Shift_ri<0, 0b101, "srli">; 459def SRAI : Shift_ri<1, 0b101, "srai">; 460 461def ADD : ALU_rr<0b0000000, 0b000, "add">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 462def SUB : ALU_rr<0b0100000, 0b000, "sub">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 463def SLL : ALU_rr<0b0000000, 0b001, "sll">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 464def SLT : ALU_rr<0b0000000, 0b010, "slt">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 465def SLTU : ALU_rr<0b0000000, 0b011, "sltu">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 466def XOR : ALU_rr<0b0000000, 0b100, "xor">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 467def SRL : ALU_rr<0b0000000, 0b101, "srl">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 468def SRA : ALU_rr<0b0100000, 0b101, "sra">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 469def OR : ALU_rr<0b0000000, 0b110, "or">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 470def AND : ALU_rr<0b0000000, 0b111, "and">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 471 472let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { 473def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs), 474 (ins fencearg:$pred, fencearg:$succ), 475 "fence", "$pred, $succ">, Sched<[]> { 476 bits<4> pred; 477 bits<4> succ; 478 479 let rs1 = 0; 480 let rd = 0; 481 let imm12 = {0b0000,pred,succ}; 482} 483 484def FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", "">, Sched<[]> { 485 let rs1 = 0; 486 let rd = 0; 487 let imm12 = {0b1000,0b0011,0b0011}; 488} 489 490def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", "">, Sched<[]> { 491 let rs1 = 0; 492 let rd = 0; 493 let imm12 = 0; 494} 495 496def ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", "">, Sched<[WriteJmp]> { 497 let rs1 = 0; 498 let rd = 0; 499 let imm12 = 0; 500} 501 502def EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", "">, 503 Sched<[]> { 504 let rs1 = 0; 505 let rd = 0; 506 let imm12 = 1; 507} 508 509// This is a de facto standard (as set by GNU binutils) 32-bit unimplemented 510// instruction (i.e., it should always trap, if your implementation has invalid 511// instruction traps). 512def UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", "">, 513 Sched<[]> { 514 let rs1 = 0; 515 let rd = 0; 516 let imm12 = 0b110000000000; 517} 518} // hasSideEffects = 1, mayLoad = 0, mayStore = 0 519 520def CSRRW : CSR_ir<0b001, "csrrw">; 521def CSRRS : CSR_ir<0b010, "csrrs">; 522def CSRRC : CSR_ir<0b011, "csrrc">; 523 524def CSRRWI : CSR_ii<0b101, "csrrwi">; 525def CSRRSI : CSR_ii<0b110, "csrrsi">; 526def CSRRCI : CSR_ii<0b111, "csrrci">; 527 528/// RV64I instructions 529 530let Predicates = [IsRV64, NotCapMode] in { 531def LWU : Load_ri<0b110, "lwu">, Sched<[WriteLDWU, ReadMemBase]>; 532def LD : Load_ri<0b011, "ld">, Sched<[WriteLDD, ReadMemBase]>; 533def SD : Store_rri<0b011, "sd">, Sched<[WriteSTD, ReadStoreData, ReadMemBase]>; 534} // Predicates = [IsRV64, NotCapMode] 535 536 537let Predicates = [IsRV64] in { 538let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 539def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd), 540 (ins GPR:$rs1, simm12:$imm12), 541 "addiw", "$rd, $rs1, $imm12">, 542 Sched<[WriteIALU32, ReadIALU32]>; 543 544def SLLIW : ShiftW_ri<0, 0b001, "slliw">; 545def SRLIW : ShiftW_ri<0, 0b101, "srliw">; 546def SRAIW : ShiftW_ri<1, 0b101, "sraiw">; 547 548def ADDW : ALUW_rr<0b0000000, 0b000, "addw">, 549 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 550def SUBW : ALUW_rr<0b0100000, 0b000, "subw">, 551 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 552def SLLW : ALUW_rr<0b0000000, 0b001, "sllw">, 553 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 554def SRLW : ALUW_rr<0b0000000, 0b101, "srlw">, 555 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 556def SRAW : ALUW_rr<0b0100000, 0b101, "sraw">, 557 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 558} // Predicates = [IsRV64] 559 560//===----------------------------------------------------------------------===// 561// Privileged instructions 562//===----------------------------------------------------------------------===// 563 564let isBarrier = 1, isReturn = 1, isTerminator = 1 in { 565def URET : Priv<"uret", 0b0000000>, Sched<[]> { 566 let rd = 0; 567 let rs1 = 0; 568 let rs2 = 0b00010; 569} 570 571def SRET : Priv<"sret", 0b0001000>, Sched<[]> { 572 let rd = 0; 573 let rs1 = 0; 574 let rs2 = 0b00010; 575} 576 577def MRET : Priv<"mret", 0b0011000>, Sched<[]> { 578 let rd = 0; 579 let rs1 = 0; 580 let rs2 = 0b00010; 581} 582} // isBarrier = 1, isReturn = 1, isTerminator = 1 583 584def WFI : Priv<"wfi", 0b0001000>, Sched<[]> { 585 let rd = 0; 586 let rs1 = 0; 587 let rs2 = 0b00101; 588} 589 590let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 591def SFENCE_VMA : RVInstR<0b0001001, 0b000, OPC_SYSTEM, (outs), 592 (ins GPR:$rs1, GPR:$rs2), 593 "sfence.vma", "$rs1, $rs2">, Sched<[]> { 594 let rd = 0; 595} 596 597//===----------------------------------------------------------------------===// 598// Debug instructions 599//===----------------------------------------------------------------------===// 600 601let isBarrier = 1, isReturn = 1, isTerminator = 1 in { 602def DRET : Priv<"dret", 0b0111101>, Sched<[]> { 603 let rd = 0; 604 let rs1 = 0; 605 let rs2 = 0b10010; 606} 607} // isBarrier = 1, isReturn = 1, isTerminator = 1 608 609//===----------------------------------------------------------------------===// 610// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) 611//===----------------------------------------------------------------------===// 612 613def : InstAlias<"nop", (ADDI X0, X0, 0)>; 614 615// Note that the size is 32 because up to 8 32-bit instructions are needed to 616// generate an arbitrary 64-bit immediate. However, the size does not really 617// matter since PseudoLI is currently only used in the AsmParser where it gets 618// expanded to real instructions immediately. 619let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32, 620 isCodeGenOnly = 0, isAsmParserOnly = 1 in 621def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [], 622 "li", "$rd, $imm">; 623 624let Predicates = [NotCapMode] in { 625def PseudoLB : PseudoLoad<"lb">; 626def PseudoLBU : PseudoLoad<"lbu">; 627def PseudoLH : PseudoLoad<"lh">; 628def PseudoLHU : PseudoLoad<"lhu">; 629def PseudoLW : PseudoLoad<"lw">; 630 631def PseudoSB : PseudoStore<"sb">; 632def PseudoSH : PseudoStore<"sh">; 633def PseudoSW : PseudoStore<"sw">; 634} // Predicates = [NotCapMode] 635 636let Predicates = [IsRV64, NotCapMode] in { 637def PseudoLWU : PseudoLoad<"lwu">; 638def PseudoLD : PseudoLoad<"ld">; 639def PseudoSD : PseudoStore<"sd">; 640} // Predicates = [IsRV64, NotCapMode] 641 642def : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>; 643def : InstAlias<"not $rd, $rs", (XORI GPR:$rd, GPR:$rs, -1)>; 644def : InstAlias<"neg $rd, $rs", (SUB GPR:$rd, X0, GPR:$rs)>; 645 646let Predicates = [IsRV64] in { 647def : InstAlias<"negw $rd, $rs", (SUBW GPR:$rd, X0, GPR:$rs)>; 648def : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs, 0)>; 649} // Predicates = [IsRV64] 650 651def : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs, 1)>; 652def : InstAlias<"snez $rd, $rs", (SLTU GPR:$rd, X0, GPR:$rs)>; 653def : InstAlias<"sltz $rd, $rs", (SLT GPR:$rd, GPR:$rs, X0)>; 654def : InstAlias<"sgtz $rd, $rs", (SLT GPR:$rd, X0, GPR:$rs)>; 655 656// sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu 657// form will always be printed. Therefore, set a zero weight. 658def : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>; 659def : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>; 660 661def : InstAlias<"beqz $rs, $offset", 662 (BEQ GPR:$rs, X0, simm13_lsb0:$offset)>; 663def : InstAlias<"bnez $rs, $offset", 664 (BNE GPR:$rs, X0, simm13_lsb0:$offset)>; 665def : InstAlias<"blez $rs, $offset", 666 (BGE X0, GPR:$rs, simm13_lsb0:$offset)>; 667def : InstAlias<"bgez $rs, $offset", 668 (BGE GPR:$rs, X0, simm13_lsb0:$offset)>; 669def : InstAlias<"bltz $rs, $offset", 670 (BLT GPR:$rs, X0, simm13_lsb0:$offset)>; 671def : InstAlias<"bgtz $rs, $offset", 672 (BLT X0, GPR:$rs, simm13_lsb0:$offset)>; 673 674// Always output the canonical mnemonic for the pseudo branch instructions. 675// The GNU tools emit the canonical mnemonic for the branch pseudo instructions 676// as well (e.g. "bgt" will be recognised by the assembler but never printed by 677// objdump). Match this behaviour by setting a zero weight. 678def : InstAlias<"bgt $rs, $rt, $offset", 679 (BLT GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 680def : InstAlias<"ble $rs, $rt, $offset", 681 (BGE GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 682def : InstAlias<"bgtu $rs, $rt, $offset", 683 (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 684def : InstAlias<"bleu $rs, $rt, $offset", 685 (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 686 687def : InstAlias<"j $offset", (JAL X0, simm21_lsb0_jal:$offset)>; 688def : InstAlias<"jal $offset", (JAL X1, simm21_lsb0_jal:$offset)>; 689 690// Non-zero offset aliases of "jalr" are the lowest weight, followed by the 691// two-register form, then the one-register forms and finally "ret". 692def : InstAlias<"jr $rs", (JALR X0, GPR:$rs, 0), 3>; 693def : InstAlias<"jr ${offset}(${rs})", (JALR X0, GPR:$rs, simm12:$offset)>; 694def : InstAlias<"jalr $rs", (JALR X1, GPR:$rs, 0), 3>; 695def : InstAlias<"jalr ${offset}(${rs})", (JALR X1, GPR:$rs, simm12:$offset)>; 696def : InstAlias<"jalr $rd, $rs", (JALR GPR:$rd, GPR:$rs, 0), 2>; 697def : InstAlias<"ret", (JALR X0, X1, 0), 4>; 698 699// Non-canonical forms for jump targets also accepted by the assembler. 700def : InstAlias<"jr $rs, $offset", (JALR X0, GPR:$rs, simm12:$offset), 0>; 701def : InstAlias<"jalr $rs, $offset", (JALR X1, GPR:$rs, simm12:$offset), 0>; 702def : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12:$offset), 0>; 703 704def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw 705 706def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>; 707def : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, CYCLE.Encoding, X0)>; 708def : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, TIME.Encoding, X0)>; 709 710let Predicates = [IsRV32] in { 711def : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, INSTRETH.Encoding, X0)>; 712def : InstAlias<"rdcycleh $rd", (CSRRS GPR:$rd, CYCLEH.Encoding, X0)>; 713def : InstAlias<"rdtimeh $rd", (CSRRS GPR:$rd, TIMEH.Encoding, X0)>; 714} // Predicates = [IsRV32] 715 716def : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, csr_sysreg:$csr, X0)>; 717def : InstAlias<"csrw $csr, $rs", (CSRRW X0, csr_sysreg:$csr, GPR:$rs)>; 718def : InstAlias<"csrs $csr, $rs", (CSRRS X0, csr_sysreg:$csr, GPR:$rs)>; 719def : InstAlias<"csrc $csr, $rs", (CSRRC X0, csr_sysreg:$csr, GPR:$rs)>; 720 721def : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>; 722def : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>; 723def : InstAlias<"csrci $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>; 724 725let EmitPriority = 0 in { 726def : InstAlias<"csrw $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>; 727def : InstAlias<"csrs $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>; 728def : InstAlias<"csrc $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>; 729 730def : InstAlias<"csrrw $rd, $csr, $imm", (CSRRWI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 731def : InstAlias<"csrrs $rd, $csr, $imm", (CSRRSI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 732def : InstAlias<"csrrc $rd, $csr, $imm", (CSRRCI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 733} 734 735def : InstAlias<"sfence.vma", (SFENCE_VMA X0, X0)>; 736def : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>; 737 738let EmitPriority = 0 in { 739let Predicates = [NotCapMode] in { 740def : InstAlias<"lb $rd, (${rs1})", 741 (LB GPR:$rd, GPR:$rs1, 0)>; 742def : InstAlias<"lh $rd, (${rs1})", 743 (LH GPR:$rd, GPR:$rs1, 0)>; 744def : InstAlias<"lw $rd, (${rs1})", 745 (LW GPR:$rd, GPR:$rs1, 0)>; 746def : InstAlias<"lbu $rd, (${rs1})", 747 (LBU GPR:$rd, GPR:$rs1, 0)>; 748def : InstAlias<"lhu $rd, (${rs1})", 749 (LHU GPR:$rd, GPR:$rs1, 0)>; 750 751def : InstAlias<"sb $rs2, (${rs1})", 752 (SB GPR:$rs2, GPR:$rs1, 0)>; 753def : InstAlias<"sh $rs2, (${rs1})", 754 (SH GPR:$rs2, GPR:$rs1, 0)>; 755def : InstAlias<"sw $rs2, (${rs1})", 756 (SW GPR:$rs2, GPR:$rs1, 0)>; 757} // Predicates = [NotCapMode] 758 759def : InstAlias<"add $rd, $rs1, $imm12", 760 (ADDI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 761def : InstAlias<"and $rd, $rs1, $imm12", 762 (ANDI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 763def : InstAlias<"xor $rd, $rs1, $imm12", 764 (XORI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 765def : InstAlias<"or $rd, $rs1, $imm12", 766 (ORI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 767def : InstAlias<"sll $rd, $rs1, $shamt", 768 (SLLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 769def : InstAlias<"srl $rd, $rs1, $shamt", 770 (SRLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 771def : InstAlias<"sra $rd, $rs1, $shamt", 772 (SRAI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 773let Predicates = [IsRV64, NotCapMode] in { 774def : InstAlias<"lwu $rd, (${rs1})", 775 (LWU GPR:$rd, GPR:$rs1, 0)>; 776def : InstAlias<"ld $rd, (${rs1})", 777 (LD GPR:$rd, GPR:$rs1, 0)>; 778def : InstAlias<"sd $rs2, (${rs1})", 779 (SD GPR:$rs2, GPR:$rs1, 0)>; 780} // Predicates = [IsRV64, NotCapMode] 781 782let Predicates = [IsRV64] in { 783def : InstAlias<"addw $rd, $rs1, $imm12", 784 (ADDIW GPR:$rd, GPR:$rs1, simm12:$imm12)>; 785def : InstAlias<"sllw $rd, $rs1, $shamt", 786 (SLLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 787def : InstAlias<"srlw $rd, $rs1, $shamt", 788 (SRLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 789def : InstAlias<"sraw $rd, $rs1, $shamt", 790 (SRAIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 791} // Predicates = [IsRV64] 792def : InstAlias<"slt $rd, $rs1, $imm12", 793 (SLTI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 794def : InstAlias<"sltu $rd, $rs1, $imm12", 795 (SLTIU GPR:$rd, GPR:$rs1, simm12:$imm12)>; 796} 797 798def : MnemonicAlias<"move", "mv">; 799 800// The SCALL and SBREAK instructions wererenamed to ECALL and EBREAK in 801// version 2.1 of the user-level ISA. Like the GNU toolchain, we still accept 802// the old name for backwards compatibility. 803def : MnemonicAlias<"scall", "ecall">; 804def : MnemonicAlias<"sbreak", "ebreak">; 805 806//===----------------------------------------------------------------------===// 807// Pseudo-instructions and codegen patterns 808// 809// Naming convention: For 'generic' pattern classes, we use the naming 810// convention PatTy1Ty2. For pattern classes which offer a more complex 811// expansion, prefix the class name, e.g. BccPat. 812//===----------------------------------------------------------------------===// 813 814/// Generic pattern classes 815 816class PatGprGpr<SDPatternOperator OpNode, RVInst Inst> 817 : Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>; 818class PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst> 819 : Pat<(OpNode GPR:$rs1, simm12:$imm12), (Inst GPR:$rs1, simm12:$imm12)>; 820class PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst> 821 : Pat<(OpNode GPR:$rs1, uimmlog2xlen:$shamt), 822 (Inst GPR:$rs1, uimmlog2xlen:$shamt)>; 823 824/// Predicates 825 826def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{ 827 return isOrEquivalentToAdd(N); 828}]>; 829def assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{ 830 return cast<VTSDNode>(N->getOperand(1))->getVT() == MVT::i32; 831}]>; 832def sexti32 : PatFrags<(ops node:$src), 833 [(sext_inreg node:$src, i32), 834 (assertsexti32 node:$src)]>; 835def assertzexti32 : PatFrag<(ops node:$src), (assertzext node:$src), [{ 836 return cast<VTSDNode>(N->getOperand(1))->getVT() == MVT::i32; 837}]>; 838def zexti32 : PatFrags<(ops node:$src), 839 [(and node:$src, 0xffffffff), 840 (assertzexti32 node:$src)]>; 841 842/// Immediates 843 844def : Pat<(simm12:$imm), (ADDI X0, simm12:$imm)>; 845def : Pat<(simm32hi20:$imm), (LUI (HI20 imm:$imm))>; 846def : Pat<(simm32:$imm), (ADDI (LUI (HI20 imm:$imm)), (LO12Sext imm:$imm))>, 847 Requires<[IsRV32]>; 848 849/// Simple arithmetic operations 850 851def : PatGprGpr<add, ADD>; 852def : PatGprSimm12<add, ADDI>; 853def : PatGprGpr<sub, SUB>; 854def : PatGprGpr<or, OR>; 855def : PatGprSimm12<or, ORI>; 856def : PatGprGpr<and, AND>; 857def : PatGprSimm12<and, ANDI>; 858def : PatGprGpr<xor, XOR>; 859def : PatGprSimm12<xor, XORI>; 860def : PatGprUimmLog2XLen<shl, SLLI>; 861def : PatGprUimmLog2XLen<srl, SRLI>; 862def : PatGprUimmLog2XLen<sra, SRAI>; 863 864// Match both a plain shift and one where the shift amount is masked (this is 865// typically introduced when the legalizer promotes the shift amount and 866// zero-extends it). For RISC-V, the mask is unnecessary as shifts in the base 867// ISA only read the least significant 5 bits (RV32I) or 6 bits (RV64I). 868class shiftop<SDPatternOperator operator> 869 : PatFrags<(ops node:$val, node:$count), 870 [(operator node:$val, node:$count), 871 (operator node:$val, (and node:$count, immbottomxlenset))]>; 872 873def : PatGprGpr<shiftop<shl>, SLL>; 874def : PatGprGpr<shiftop<srl>, SRL>; 875def : PatGprGpr<shiftop<sra>, SRA>; 876 877// This is a special case of the ADD instruction used to facilitate the use of a 878// fourth operand to emit a relocation on a symbol relating to this instruction. 879// The relocation does not affect any bits of the instruction itself but is used 880// as a hint to the linker. 881let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in 882def PseudoAddTPRel : Pseudo<(outs GPR:$rd), 883 (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [], 884 "add", "$rd, $rs1, $rs2, $src">; 885 886/// FrameIndex calculations 887 888def : Pat<(add (i32 AddrFI:$Rs), simm12:$imm12), 889 (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>; 890def : Pat<(IsOrAdd (i32 AddrFI:$Rs), simm12:$imm12), 891 (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>; 892 893/// Setcc 894 895def : PatGprGpr<setlt, SLT>; 896def : PatGprSimm12<setlt, SLTI>; 897def : PatGprGpr<setult, SLTU>; 898def : PatGprSimm12<setult, SLTIU>; 899 900// Define pattern expansions for setcc operations that aren't directly 901// handled by a RISC-V instruction. 902def : Pat<(seteq GPR:$rs1, 0), (SLTIU GPR:$rs1, 1)>; 903def : Pat<(seteq GPR:$rs1, GPR:$rs2), (SLTIU (XOR GPR:$rs1, GPR:$rs2), 1)>; 904def : Pat<(seteq GPR:$rs1, simm12_plus1:$imm12), 905 (SLTIU (ADDI GPR:$rs1, (NegImm simm12_plus1:$imm12)), 1)>; 906def : Pat<(setne GPR:$rs1, 0), (SLTU X0, GPR:$rs1)>; 907def : Pat<(setne GPR:$rs1, GPR:$rs2), (SLTU X0, (XOR GPR:$rs1, GPR:$rs2))>; 908def : Pat<(setne GPR:$rs1, simm12_plus1:$imm12), 909 (SLTU X0, (ADDI GPR:$rs1, (NegImm simm12_plus1:$imm12)))>; 910def : Pat<(setugt GPR:$rs1, GPR:$rs2), (SLTU GPR:$rs2, GPR:$rs1)>; 911def : Pat<(setuge GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs1, GPR:$rs2), 1)>; 912def : Pat<(setule GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs2, GPR:$rs1), 1)>; 913def : Pat<(setgt GPR:$rs1, GPR:$rs2), (SLT GPR:$rs2, GPR:$rs1)>; 914def : Pat<(setge GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs1, GPR:$rs2), 1)>; 915def : Pat<(setle GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs2, GPR:$rs1), 1)>; 916 917let usesCustomInserter = 1 in 918class SelectCC_rrirr<RegisterClass valty, RegisterClass cmpty> 919 : Pseudo<(outs valty:$dst), 920 (ins cmpty:$lhs, cmpty:$rhs, ixlenimm:$imm, 921 valty:$truev, valty:$falsev), 922 [(set valty:$dst, (riscv_selectcc cmpty:$lhs, cmpty:$rhs, 923 (XLenVT imm:$imm), valty:$truev, valty:$falsev))]>; 924 925def Select_GPR_Using_CC_GPR : SelectCC_rrirr<GPR, GPR>; 926 927/// Branches and jumps 928 929// Match `(brcond (CondOp ..), ..)` and lower to the appropriate RISC-V branch 930// instruction. 931class BccPat<PatFrag CondOp, RVInstB Inst> 932 : Pat<(brcond (XLenVT (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12), 933 (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>; 934 935def : BccPat<seteq, BEQ>; 936def : BccPat<setne, BNE>; 937def : BccPat<setlt, BLT>; 938def : BccPat<setge, BGE>; 939def : BccPat<setult, BLTU>; 940def : BccPat<setuge, BGEU>; 941 942class BccSwapPat<PatFrag CondOp, RVInst InstBcc> 943 : Pat<(brcond (XLenVT (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12), 944 (InstBcc GPR:$rs2, GPR:$rs1, bb:$imm12)>; 945 946// Condition codes that don't have matching RISC-V branch instructions, but 947// are trivially supported by swapping the two input operands 948def : BccSwapPat<setgt, BLT>; 949def : BccSwapPat<setle, BGE>; 950def : BccSwapPat<setugt, BLTU>; 951def : BccSwapPat<setule, BGEU>; 952 953// An extra pattern is needed for a brcond without a setcc (i.e. where the 954// condition was calculated elsewhere). 955def : Pat<(brcond GPR:$cond, bb:$imm12), (BNE GPR:$cond, X0, bb:$imm12)>; 956 957let isBarrier = 1, isBranch = 1, isTerminator = 1 in 958def PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>, 959 PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>; 960 961let isCall = 1, Defs=[X1] in 962let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in 963def PseudoBRIND : Pseudo<(outs), (ins GPR:$rs1, simm12:$imm12), []>, 964 PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; 965 966def : Pat<(brind GPR:$rs1), (PseudoBRIND GPR:$rs1, 0)>; 967def : Pat<(brind (add GPR:$rs1, simm12:$imm12)), 968 (PseudoBRIND GPR:$rs1, simm12:$imm12)>; 969 970// PseudoCALLReg is a generic pseudo instruction for calls which will eventually 971// expand to auipc and jalr while encoding, with any given register used as the 972// destination. 973// Define AsmString to print "call" when compile with -S flag. 974// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 975let Predicates = [NotCapMode], 976 isCall = 1, isBarrier = 1, isCodeGenOnly = 0, hasSideEffects = 0, 977 mayStore = 0, mayLoad = 0 in 978def PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), []> { 979 let AsmString = "call\t$rd, $func"; 980} 981 982// PseudoCALL is a pseudo instruction which will eventually expand to auipc 983// and jalr while encoding. This is desirable, as an auipc+jalr pair with 984// R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker 985// if the offset fits in a signed 21-bit immediate. 986// Define AsmString to print "call" when compile with -S flag. 987// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 988let Predicates = [NotCapMode], 989 isCall = 1, Defs = [X1], isCodeGenOnly = 0 in 990def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), []> { 991 let AsmString = "call\t$func"; 992} 993 994let Predicates = [NotCapMode, NotPureCapABI] in { 995def : Pat<(riscv_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>; 996def : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>; 997} // Predicates = [NotCapMode, NotPureCapABI] 998 999def : Pat<(riscv_uret_flag), (URET X0, X0)>; 1000def : Pat<(riscv_sret_flag), (SRET X0, X0)>; 1001def : Pat<(riscv_mret_flag), (MRET X0, X0)>; 1002 1003let Predicates = [NotPureCapABI], 1004 isCall = 1, Defs = [X1] in 1005def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rs1), 1006 [(riscv_call GPR:$rs1)]>, 1007 PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>; 1008 1009let Predicates = [NotPureCapABI], 1010 isBarrier = 1, isReturn = 1, isTerminator = 1 in 1011def PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_flag)]>, 1012 PseudoInstExpansion<(JALR X0, X1, 0)>; 1013 1014// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually 1015// expand to auipc and jalr while encoding. 1016// Define AsmString to print "tail" when compile with -S flag. 1017let Predicates = [NotCapMode], 1018 isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2], 1019 isCodeGenOnly = 0 in 1020def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), []> { 1021 let AsmString = "tail\t$dst"; 1022} 1023 1024let Predicates = [NotPureCapABI], 1025 isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in 1026def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1), 1027 [(riscv_tail GPRTC:$rs1)]>, 1028 PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>; 1029 1030let Predicates = [NotCapMode, NotPureCapABI] in { 1031def : Pat<(riscv_tail (iPTR tglobaladdr:$dst)), 1032 (PseudoTAIL texternalsym:$dst)>; 1033def : Pat<(riscv_tail (iPTR texternalsym:$dst)), 1034 (PseudoTAIL texternalsym:$dst)>; 1035} // Predicates = [NotCapMode, NotPureCapABI] 1036 1037let Predicates = [NotCapMode] in { 1038let isCall = 0, isBarrier = 0, isCodeGenOnly = 0, hasSideEffects = 0, 1039 mayStore = 0, mayLoad = 0 in 1040def PseudoJump : Pseudo<(outs GPR:$rd), (ins pseudo_jump_symbol:$target), []> { 1041 let AsmString = "jump\t$target, $rd"; 1042} 1043 1044let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0, 1045 isAsmParserOnly = 1 in 1046def PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1047 "lla", "$dst, $src">; 1048 1049let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, 1050 isAsmParserOnly = 1 in 1051def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1052 "la", "$dst, $src">; 1053 1054let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, 1055 isAsmParserOnly = 1 in 1056def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1057 "la.tls.ie", "$dst, $src">; 1058 1059let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, 1060 isAsmParserOnly = 1 in 1061def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1062 "la.tls.gd", "$dst, $src">; 1063} // Predicates = [NotCapMode] 1064 1065/// Loads 1066 1067multiclass LdPat<PatFrag LoadOp, RVInst Inst> { 1068 def : Pat<(LoadOp GPR:$rs1), (Inst GPR:$rs1, 0)>; 1069 def : Pat<(LoadOp AddrFI:$rs1), (Inst AddrFI:$rs1, 0)>; 1070 def : Pat<(LoadOp (add GPR:$rs1, simm12:$imm12)), 1071 (Inst GPR:$rs1, simm12:$imm12)>; 1072 def : Pat<(LoadOp (add AddrFI:$rs1, simm12:$imm12)), 1073 (Inst AddrFI:$rs1, simm12:$imm12)>; 1074 def : Pat<(LoadOp (IsOrAdd AddrFI:$rs1, simm12:$imm12)), 1075 (Inst AddrFI:$rs1, simm12:$imm12)>; 1076} 1077 1078defm : LdPat<sextloadi8, LB>, Requires<[NotCapMode]>; 1079defm : LdPat<extloadi8, LB>, Requires<[NotCapMode]>; 1080defm : LdPat<sextloadi16, LH>, Requires<[NotCapMode]>; 1081defm : LdPat<extloadi16, LH>, Requires<[NotCapMode]>; 1082defm : LdPat<load, LW>, Requires<[IsRV32, NotCapMode]>; 1083defm : LdPat<zextloadi8, LBU>, Requires<[NotCapMode]>; 1084defm : LdPat<zextloadi16, LHU>, Requires<[NotCapMode]>; 1085 1086/// Stores 1087 1088multiclass StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy> { 1089 def : Pat<(StoreOp StTy:$rs2, GPR:$rs1), (Inst StTy:$rs2, GPR:$rs1, 0)>; 1090 def : Pat<(StoreOp StTy:$rs2, AddrFI:$rs1), (Inst StTy:$rs2, AddrFI:$rs1, 0)>; 1091 def : Pat<(StoreOp StTy:$rs2, (add GPR:$rs1, simm12:$imm12)), 1092 (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>; 1093 def : Pat<(StoreOp StTy:$rs2, (add AddrFI:$rs1, simm12:$imm12)), 1094 (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>; 1095 def : Pat<(StoreOp StTy:$rs2, (IsOrAdd AddrFI:$rs1, simm12:$imm12)), 1096 (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>; 1097} 1098 1099defm : StPat<truncstorei8, SB, GPR>, Requires<[NotCapMode]>; 1100defm : StPat<truncstorei16, SH, GPR>, Requires<[NotCapMode]>; 1101defm : StPat<store, SW, GPR>, Requires<[IsRV32, NotCapMode]>; 1102 1103/// Fences 1104 1105// Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set 1106// Manual: Volume I. 1107 1108// fence acquire -> fence r, rw 1109def : Pat<(atomic_fence (XLenVT 4), (timm)), (FENCE 0b10, 0b11)>; 1110// fence release -> fence rw, w 1111def : Pat<(atomic_fence (XLenVT 5), (timm)), (FENCE 0b11, 0b1)>; 1112// fence acq_rel -> fence.tso 1113def : Pat<(atomic_fence (XLenVT 6), (timm)), (FENCE_TSO)>; 1114// fence seq_cst -> fence rw, rw 1115def : Pat<(atomic_fence (XLenVT 7), (timm)), (FENCE 0b11, 0b11)>; 1116 1117// Lowering for atomic load and store is defined in RISCVInstrInfoA.td. 1118// Although these are lowered to fence+load/store instructions defined in the 1119// base RV32I/RV64I ISA, this lowering is only used when the A extension is 1120// present. This is necessary as it isn't valid to mix __atomic_* libcalls 1121// with inline atomic operations for the same object. 1122 1123/// Other pseudo-instructions 1124 1125// Pessimistically assume the stack pointer will be clobbered 1126let Predicates = [NotPureCapABI] in { 1127let Defs = [X2], Uses = [X2] in { 1128def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 1129 [(callseq_start timm:$amt1, timm:$amt2)]>; 1130def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 1131 [(callseq_end timm:$amt1, timm:$amt2)]>; 1132} // Defs = [X2], Uses = [X2] 1133} // Predicates = [NotPureCapABI] 1134 1135/// RV64 patterns 1136 1137let Predicates = [IsRV64] in { 1138 1139/// sext and zext 1140 1141def : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>; 1142def : Pat<(and GPR:$rs1, 0xffffffff), (SRLI (SLLI GPR:$rs1, 32), 32)>; 1143 1144/// ALU operations 1145 1146def : Pat<(sext_inreg (add GPR:$rs1, GPR:$rs2), i32), 1147 (ADDW GPR:$rs1, GPR:$rs2)>; 1148def : Pat<(sext_inreg (add GPR:$rs1, simm12:$imm12), i32), 1149 (ADDIW GPR:$rs1, simm12:$imm12)>; 1150def : Pat<(sext_inreg (sub GPR:$rs1, GPR:$rs2), i32), 1151 (SUBW GPR:$rs1, GPR:$rs2)>; 1152def : Pat<(sext_inreg (shl GPR:$rs1, uimm5:$shamt), i32), 1153 (SLLIW GPR:$rs1, uimm5:$shamt)>; 1154// (srl (zexti32 ...), uimm5:$shamt) is matched with custom code due to the 1155// need to undo manipulation of the mask value performed by DAGCombine. 1156def : Pat<(sra (sext_inreg GPR:$rs1, i32), uimm5:$shamt), 1157 (SRAIW GPR:$rs1, uimm5:$shamt)>; 1158 1159def : PatGprGpr<riscv_sllw, SLLW>; 1160def : PatGprGpr<riscv_srlw, SRLW>; 1161def : PatGprGpr<riscv_sraw, SRAW>; 1162} // Predicates = [IsRV64] 1163 1164let Predicates = [IsRV64, NotCapMode] in { 1165 1166/// Loads 1167 1168defm : LdPat<sextloadi32, LW>; 1169defm : LdPat<extloadi32, LW>; 1170defm : LdPat<zextloadi32, LWU>; 1171defm : LdPat<load, LD>; 1172 1173/// Stores 1174 1175defm : StPat<truncstorei32, SW, GPR>; 1176defm : StPat<store, SD, GPR>; 1177} // Predicates = [IsRV64, NotCapMode] 1178 1179/// readcyclecounter 1180// On RV64, we can directly read the 64-bit "cycle" CSR. 1181let Predicates = [IsRV64] in 1182def : Pat<(readcyclecounter), (CSRRS CYCLE.Encoding, X0)>; 1183// On RV32, ReadCycleWide will be expanded to the suggested loop reading both 1184// halves of the 64-bit "cycle" CSR. 1185let Predicates = [IsRV32], usesCustomInserter = 1, hasSideEffects = 0, 1186mayLoad = 0, mayStore = 0, hasNoSchedulingInfo = 1 in 1187def ReadCycleWide : Pseudo<(outs GPR:$lo, GPR:$hi), (ins), [], "", "">; 1188 1189/// traps 1190 1191// We lower `trap` to `unimp`, as this causes a hard exception on nearly all 1192// systems. 1193def : Pat<(trap), (UNIMP)>; 1194 1195// We lower `debugtrap` to `ebreak`, as this will get the attention of the 1196// debugger if possible. 1197def : Pat<(debugtrap), (EBREAK)>; 1198 1199//===----------------------------------------------------------------------===// 1200// Standard extensions 1201//===----------------------------------------------------------------------===// 1202 1203include "RISCVInstrInfoM.td" 1204include "RISCVInstrInfoA.td" 1205include "RISCVInstrInfoF.td" 1206include "RISCVInstrInfoD.td" 1207include "RISCVInstrInfoC.td" 1208include "RISCVInstrInfoB.td" 1209include "RISCVInstrInfoV.td" 1210 1211//===----------------------------------------------------------------------===// 1212// Non-standard Extensions 1213//===----------------------------------------------------------------------===// 1214 1215include "RISCVInstrInfoXCheri.td" 1216