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