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 SDTCisVT<3, OtherVT>, 27 SDTCisSameAs<0, 4>, 28 SDTCisSameAs<4, 5>]>; 29def SDT_RISCVBrCC : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>, 30 SDTCisVT<2, OtherVT>, 31 SDTCisVT<3, OtherVT>]>; 32def SDT_RISCVReadCSR : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisInt<1>]>; 33def SDT_RISCVWriteCSR : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisInt<1>]>; 34def SDT_RISCVSwapCSR : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisInt<1>, 35 SDTCisInt<2>]>; 36def SDT_RISCVReadCycleWide : SDTypeProfile<2, 0, [SDTCisVT<0, i32>, 37 SDTCisVT<1, i32>]>; 38def SDT_RISCVIntUnaryOpW : SDTypeProfile<1, 1, [ 39 SDTCisSameAs<0, 1>, SDTCisVT<0, i64> 40]>; 41def SDT_RISCVIntBinOpW : SDTypeProfile<1, 2, [ 42 SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64> 43]>; 44def SDT_RISCVIntShiftDOpW : SDTypeProfile<1, 3, [ 45 SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64>, SDTCisVT<3, i64> 46]>; 47 48// Target-independent nodes, but with target-specific formats. 49def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart, 50 [SDNPHasChain, SDNPOutGlue]>; 51def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd, 52 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; 53 54// Target-dependent nodes. 55def riscv_call : SDNode<"RISCVISD::CALL", SDT_RISCVCall, 56 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 57 SDNPVariadic]>; 58def riscv_ret_flag : SDNode<"RISCVISD::RET_FLAG", SDTNone, 59 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; 60def riscv_uret_flag : SDNode<"RISCVISD::URET_FLAG", SDTNone, 61 [SDNPHasChain, SDNPOptInGlue]>; 62def riscv_sret_flag : SDNode<"RISCVISD::SRET_FLAG", SDTNone, 63 [SDNPHasChain, SDNPOptInGlue]>; 64def riscv_mret_flag : SDNode<"RISCVISD::MRET_FLAG", SDTNone, 65 [SDNPHasChain, SDNPOptInGlue]>; 66def riscv_selectcc : SDNode<"RISCVISD::SELECT_CC", SDT_RISCVSelectCC>; 67def riscv_brcc : SDNode<"RISCVISD::BR_CC", SDT_RISCVBrCC, 68 [SDNPHasChain]>; 69def riscv_tail : SDNode<"RISCVISD::TAIL", SDT_RISCVCall, 70 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 71 SDNPVariadic]>; 72def riscv_sllw : SDNode<"RISCVISD::SLLW", SDT_RISCVIntBinOpW>; 73def riscv_sraw : SDNode<"RISCVISD::SRAW", SDT_RISCVIntBinOpW>; 74def riscv_srlw : SDNode<"RISCVISD::SRLW", SDT_RISCVIntBinOpW>; 75def riscv_read_csr : SDNode<"RISCVISD::READ_CSR", SDT_RISCVReadCSR, 76 [SDNPHasChain]>; 77def riscv_write_csr : SDNode<"RISCVISD::WRITE_CSR", SDT_RISCVWriteCSR, 78 [SDNPHasChain]>; 79def riscv_swap_csr : SDNode<"RISCVISD::SWAP_CSR", SDT_RISCVSwapCSR, 80 [SDNPHasChain]>; 81 82def riscv_read_cycle_wide : SDNode<"RISCVISD::READ_CYCLE_WIDE", 83 SDT_RISCVReadCycleWide, 84 [SDNPHasChain, SDNPSideEffect]>; 85 86def riscv_add_lo : SDNode<"RISCVISD::ADD_LO", SDTIntBinOp>; 87def riscv_hi : SDNode<"RISCVISD::HI", SDTIntUnaryOp>; 88def riscv_lla : SDNode<"RISCVISD::LLA", SDTIntUnaryOp>; 89def riscv_add_tprel : SDNode<"RISCVISD::ADD_TPREL", 90 SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, 91 SDTCisSameAs<0, 2>, 92 SDTCisSameAs<0, 3>, 93 SDTCisInt<0>]>>; 94 95def riscv_la : SDNode<"RISCVISD::LA", SDTLoad, 96 [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; 97def riscv_la_tls_ie : SDNode<"RISCVISD::LA_TLS_IE", SDTLoad, 98 [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; 99def riscv_la_tls_gd : SDNode<"RISCVISD::LA_TLS_GD", SDTIntUnaryOp>; 100 101//===----------------------------------------------------------------------===// 102// Operand and SDNode transformation definitions. 103//===----------------------------------------------------------------------===// 104 105class ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass { 106 let Name = prefix # "ImmXLen" # suffix; 107 let RenderMethod = "addImmOperands"; 108 let DiagnosticType = !strconcat("Invalid", Name); 109} 110 111class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass { 112 let Name = prefix # "Imm" # width # suffix; 113 let RenderMethod = "addImmOperands"; 114 let DiagnosticType = !strconcat("Invalid", Name); 115} 116 117def ImmZeroAsmOperand : AsmOperandClass { 118 let Name = "ImmZero"; 119 let RenderMethod = "addImmOperands"; 120 let DiagnosticType = !strconcat("Invalid", Name); 121} 122 123// A parse method for (${gpr}) or 0(${gpr}), where the 0 is be silently ignored. 124def ZeroOffsetMemOpOperand : AsmOperandClass { 125 let Name = "ZeroOffsetMemOpOperand"; 126 let RenderMethod = "addRegOperands"; 127 let PredicateMethod = "isGPR"; 128 let ParserMethod = "parseZeroOffsetMemOp"; 129} 130 131def GPRMemZeroOffset : RegisterOperand<GPR> { 132 let ParserMatchClass = ZeroOffsetMemOpOperand; 133 let PrintMethod = "printZeroOffsetMemOp"; 134} 135 136class SImmAsmOperand<int width, string suffix = ""> 137 : ImmAsmOperand<"S", width, suffix> { 138} 139 140class UImmAsmOperand<int width, string suffix = ""> 141 : ImmAsmOperand<"U", width, suffix> { 142} 143 144def FenceArg : AsmOperandClass { 145 let Name = "FenceArg"; 146 let RenderMethod = "addFenceArgOperands"; 147 let DiagnosticType = "InvalidFenceArg"; 148} 149 150def fencearg : Operand<XLenVT> { 151 let ParserMatchClass = FenceArg; 152 let PrintMethod = "printFenceArg"; 153 let DecoderMethod = "decodeUImmOperand<4>"; 154 let OperandType = "OPERAND_UIMM4"; 155 let OperandNamespace = "RISCVOp"; 156} 157 158def UImmLog2XLenAsmOperand : AsmOperandClass { 159 let Name = "UImmLog2XLen"; 160 let RenderMethod = "addImmOperands"; 161 let DiagnosticType = "InvalidUImmLog2XLen"; 162} 163 164def uimmlog2xlen : Operand<XLenVT>, ImmLeaf<XLenVT, [{ 165 if (Subtarget->is64Bit()) 166 return isUInt<6>(Imm); 167 return isUInt<5>(Imm); 168}]> { 169 let ParserMatchClass = UImmLog2XLenAsmOperand; 170 // TODO: should ensure invalid shamt is rejected when decoding. 171 let DecoderMethod = "decodeUImmOperand<6>"; 172 let MCOperandPredicate = [{ 173 int64_t Imm; 174 if (!MCOp.evaluateAsConstantImm(Imm)) 175 return false; 176 if (STI.getTargetTriple().isArch64Bit()) 177 return isUInt<6>(Imm); 178 return isUInt<5>(Imm); 179 }]; 180 let OperandType = "OPERAND_UIMMLOG2XLEN"; 181 let OperandNamespace = "RISCVOp"; 182} 183 184def uimm2 : Operand<XLenVT> { 185 let ParserMatchClass = UImmAsmOperand<2>; 186 let DecoderMethod = "decodeUImmOperand<2>"; 187 let OperandType = "OPERAND_UIMM2"; 188 let OperandNamespace = "RISCVOp"; 189} 190 191def uimm3 : Operand<XLenVT> { 192 let ParserMatchClass = UImmAsmOperand<3>; 193 let DecoderMethod = "decodeUImmOperand<3>"; 194 let OperandType = "OPERAND_UIMM3"; 195 let OperandNamespace = "RISCVOp"; 196} 197 198def uimm5 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> { 199 let ParserMatchClass = UImmAsmOperand<5>; 200 let DecoderMethod = "decodeUImmOperand<5>"; 201 let OperandType = "OPERAND_UIMM5"; 202 let OperandNamespace = "RISCVOp"; 203} 204 205def InsnDirectiveOpcode : AsmOperandClass { 206 let Name = "InsnDirectiveOpcode"; 207 let ParserMethod = "parseInsnDirectiveOpcode"; 208 let RenderMethod = "addImmOperands"; 209 let PredicateMethod = "isImm"; 210} 211 212def uimm7_opcode : Operand<XLenVT> { 213 let ParserMatchClass = InsnDirectiveOpcode; 214 let DecoderMethod = "decodeUImmOperand<7>"; 215 let OperandType = "OPERAND_UIMM7"; 216 let OperandNamespace = "RISCVOp"; 217} 218 219def uimm7 : Operand<XLenVT> { 220 let ParserMatchClass = UImmAsmOperand<7>; 221 let DecoderMethod = "decodeUImmOperand<7>"; 222 let OperandType = "OPERAND_UIMM7"; 223 let OperandNamespace = "RISCVOp"; 224} 225 226def simm12 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isInt<12>(Imm);}]> { 227 let ParserMatchClass = SImmAsmOperand<12>; 228 let EncoderMethod = "getImmOpValue"; 229 let DecoderMethod = "decodeSImmOperand<12>"; 230 let MCOperandPredicate = [{ 231 int64_t Imm; 232 if (MCOp.evaluateAsConstantImm(Imm)) 233 return isInt<12>(Imm); 234 return MCOp.isBareSymbolRef(); 235 }]; 236 let OperandType = "OPERAND_SIMM12"; 237 let OperandNamespace = "RISCVOp"; 238} 239 240// A 13-bit signed immediate where the least significant bit is zero. 241def simm13_lsb0 : Operand<OtherVT> { 242 let ParserMatchClass = SImmAsmOperand<13, "Lsb0">; 243 let PrintMethod = "printBranchOperand"; 244 let EncoderMethod = "getImmOpValueAsr1"; 245 let DecoderMethod = "decodeSImmOperandAndLsl1<13>"; 246 let MCOperandPredicate = [{ 247 int64_t Imm; 248 if (MCOp.evaluateAsConstantImm(Imm)) 249 return isShiftedInt<12, 1>(Imm); 250 return MCOp.isBareSymbolRef(); 251 }]; 252 let OperandType = "OPERAND_PCREL"; 253} 254 255class UImm20Operand : Operand<XLenVT> { 256 let EncoderMethod = "getImmOpValue"; 257 let DecoderMethod = "decodeUImmOperand<20>"; 258 let MCOperandPredicate = [{ 259 int64_t Imm; 260 if (MCOp.evaluateAsConstantImm(Imm)) 261 return isUInt<20>(Imm); 262 return MCOp.isBareSymbolRef(); 263 }]; 264 let OperandType = "OPERAND_UIMM20"; 265 let OperandNamespace = "RISCVOp"; 266} 267 268def uimm20_lui : UImm20Operand { 269 let ParserMatchClass = UImmAsmOperand<20, "LUI">; 270} 271def uimm20_auipc : UImm20Operand { 272 let ParserMatchClass = UImmAsmOperand<20, "AUIPC">; 273} 274 275def Simm21Lsb0JALAsmOperand : SImmAsmOperand<21, "Lsb0JAL"> { 276 let ParserMethod = "parseJALOffset"; 277} 278 279// A 21-bit signed immediate where the least significant bit is zero. 280def simm21_lsb0_jal : Operand<OtherVT> { 281 let ParserMatchClass = Simm21Lsb0JALAsmOperand; 282 let PrintMethod = "printBranchOperand"; 283 let EncoderMethod = "getImmOpValueAsr1"; 284 let DecoderMethod = "decodeSImmOperandAndLsl1<21>"; 285 let MCOperandPredicate = [{ 286 int64_t Imm; 287 if (MCOp.evaluateAsConstantImm(Imm)) 288 return isShiftedInt<20, 1>(Imm); 289 return MCOp.isBareSymbolRef(); 290 }]; 291 let OperandType = "OPERAND_PCREL"; 292} 293 294def BareSymbol : AsmOperandClass { 295 let Name = "BareSymbol"; 296 let RenderMethod = "addImmOperands"; 297 let DiagnosticType = "InvalidBareSymbol"; 298 let ParserMethod = "parseBareSymbol"; 299} 300 301// A bare symbol. 302def bare_symbol : Operand<XLenVT> { 303 let ParserMatchClass = BareSymbol; 304} 305 306def CallSymbol : AsmOperandClass { 307 let Name = "CallSymbol"; 308 let RenderMethod = "addImmOperands"; 309 let DiagnosticType = "InvalidCallSymbol"; 310 let ParserMethod = "parseCallSymbol"; 311} 312 313// A bare symbol used in call/tail only. 314def call_symbol : Operand<XLenVT> { 315 let ParserMatchClass = CallSymbol; 316} 317 318def PseudoJumpSymbol : AsmOperandClass { 319 let Name = "PseudoJumpSymbol"; 320 let RenderMethod = "addImmOperands"; 321 let DiagnosticType = "InvalidPseudoJumpSymbol"; 322 let ParserMethod = "parsePseudoJumpSymbol"; 323} 324 325// A bare symbol used for pseudo jumps only. 326def pseudo_jump_symbol : Operand<XLenVT> { 327 let ParserMatchClass = PseudoJumpSymbol; 328} 329 330def TPRelAddSymbol : AsmOperandClass { 331 let Name = "TPRelAddSymbol"; 332 let RenderMethod = "addImmOperands"; 333 let DiagnosticType = "InvalidTPRelAddSymbol"; 334 let ParserMethod = "parseOperandWithModifier"; 335} 336 337// A bare symbol with the %tprel_add variant. 338def tprel_add_symbol : Operand<XLenVT> { 339 let ParserMatchClass = TPRelAddSymbol; 340} 341 342def CSRSystemRegister : AsmOperandClass { 343 let Name = "CSRSystemRegister"; 344 let ParserMethod = "parseCSRSystemRegister"; 345 let DiagnosticType = "InvalidCSRSystemRegister"; 346} 347 348def csr_sysreg : Operand<XLenVT> { 349 let ParserMatchClass = CSRSystemRegister; 350 let PrintMethod = "printCSRSystemRegister"; 351 let DecoderMethod = "decodeUImmOperand<12>"; 352 let OperandType = "OPERAND_UIMM12"; 353 let OperandNamespace = "RISCVOp"; 354} 355 356// A parameterized register class alternative to i32imm/i64imm from Target.td. 357def ixlenimm : Operand<XLenVT>; 358 359def ixlenimm_li : Operand<XLenVT> { 360 let ParserMatchClass = ImmXLenAsmOperand<"", "LI">; 361} 362 363// Standalone (codegen-only) immleaf patterns. 364 365// A 12-bit signed immediate plus one where the imm range will be [-2047, 2048]. 366def simm12_plus1 : ImmLeaf<XLenVT, 367 [{return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048;}]>; 368 369// A 12-bit signed immediate sub one and exclude zero 370def simm12_minus1_nonzero : PatLeaf<(imm), [{ 371 if (!N->hasOneUse()) 372 return false; 373 // The immediate operand must be in range [-2049, 0) or (0, 2046]. 374 int64_t Imm = N->getSExtValue(); 375 return (Imm >= -2049 && Imm < 0) || (Imm > 0 && Imm <= 2046); 376}]>; 377 378// A 6-bit constant greater than 32. 379def uimm6gt32 : ImmLeaf<XLenVT, [{ 380 return isUInt<6>(Imm) && Imm > 32; 381}]>; 382 383// Addressing modes. 384// Necessary because a frameindex can't be matched directly in a pattern. 385def FrameAddrRegImm : ComplexPattern<iPTR, 2, "SelectFrameAddrRegImm", 386 [frameindex, or, add]>; 387def AddrRegImm : ComplexPattern<iPTR, 2, "SelectAddrRegImm">; 388 389// Return the negation of an immediate value. 390def NegImm : SDNodeXForm<imm, [{ 391 return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N), 392 N->getValueType(0)); 393}]>; 394 395// Return an immediate value minus 32. 396def ImmSub32 : SDNodeXForm<imm, [{ 397 return CurDAG->getTargetConstant(N->getSExtValue() - 32, SDLoc(N), 398 N->getValueType(0)); 399}]>; 400 401// Return an immediate value plus 1. 402def ImmPlus1 : SDNodeXForm<imm, [{ 403 return CurDAG->getTargetConstant(N->getSExtValue() + 1, SDLoc(N), 404 N->getValueType(0)); 405}]>; 406 407// Return an immediate subtracted from XLen. 408def ImmSubFromXLen : SDNodeXForm<imm, [{ 409 uint64_t XLen = Subtarget->getXLen(); 410 return CurDAG->getTargetConstant(XLen - N->getZExtValue(), SDLoc(N), 411 N->getValueType(0)); 412}]>; 413 414// Return an immediate subtracted from 32. 415def ImmSubFrom32 : SDNodeXForm<imm, [{ 416 return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N), 417 N->getValueType(0)); 418}]>; 419 420// Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1), 421// in which imm = imm0 + imm1 and both imm0 and imm1 are simm12. We make imm0 422// as large as possible and imm1 as small as possible so that we might be able 423// to use c.addi for the small immediate. 424def AddiPair : PatLeaf<(imm), [{ 425 if (!N->hasOneUse()) 426 return false; 427 // The immediate operand must be in range [-4096,-2049] or [2048,4094]. 428 int64_t Imm = N->getSExtValue(); 429 return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094); 430}]>; 431 432// Return imm - (imm < 0 ? -2048 : 2047). 433def AddiPairImmSmall : SDNodeXForm<imm, [{ 434 int64_t Imm = N->getSExtValue(); 435 int64_t Adj = N->getSExtValue() < 0 ? -2048 : 2047; 436 return CurDAG->getTargetConstant(Imm - Adj, SDLoc(N), 437 N->getValueType(0)); 438}]>; 439 440// Return -2048 if immediate is negative or 2047 if positive. These are the 441// largest simm12 values. 442def AddiPairImmLarge : SDNodeXForm<imm, [{ 443 int64_t Imm = N->getSExtValue() < 0 ? -2048 : 2047; 444 return CurDAG->getTargetConstant(Imm, SDLoc(N), 445 N->getValueType(0)); 446}]>; 447 448def TrailingZeros : SDNodeXForm<imm, [{ 449 return CurDAG->getTargetConstant(N->getAPIntValue().countTrailingZeros(), 450 SDLoc(N), N->getValueType(0)); 451}]>; 452 453def XLenSubTrailingOnes : SDNodeXForm<imm, [{ 454 uint64_t XLen = Subtarget->getXLen(); 455 uint64_t TrailingOnes = N->getAPIntValue().countTrailingOnes(); 456 return CurDAG->getTargetConstant(XLen - TrailingOnes, SDLoc(N), 457 N->getValueType(0)); 458}]>; 459 460// Checks if this mask is a non-empty sequence of ones starting at the 461// most/least significant bit with the remainder zero and exceeds simm32/simm12. 462def LeadingOnesMask : PatLeaf<(imm), [{ 463 if (!N->hasOneUse()) 464 return false; 465 return !isInt<32>(N->getSExtValue()) && isMask_64(~N->getSExtValue()); 466}], TrailingZeros>; 467 468def TrailingOnesMask : PatLeaf<(imm), [{ 469 if (!N->hasOneUse()) 470 return false; 471 return !isInt<12>(N->getSExtValue()) && isMask_64(N->getZExtValue()); 472}], XLenSubTrailingOnes>; 473 474//===----------------------------------------------------------------------===// 475// Instruction Formats 476//===----------------------------------------------------------------------===// 477 478include "RISCVInstrFormats.td" 479 480//===----------------------------------------------------------------------===// 481// Instruction Class Templates 482//===----------------------------------------------------------------------===// 483 484let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 485class BranchCC_rri<bits<3> funct3, string opcodestr> 486 : RVInstB<funct3, OPC_BRANCH, (outs), 487 (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12), 488 opcodestr, "$rs1, $rs2, $imm12">, 489 Sched<[WriteJmp, ReadJmp, ReadJmp]> { 490 let isBranch = 1; 491 let isTerminator = 1; 492} 493 494let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { 495class Load_ri<bits<3> funct3, string opcodestr> 496 : RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), 497 opcodestr, "$rd, ${imm12}(${rs1})">; 498 499class HLoad_r<bits<7> funct7, bits<5> funct5, string opcodestr> 500 : RVInstR<funct7, 0b100, OPC_SYSTEM, (outs GPR:$rd), 501 (ins GPRMemZeroOffset:$rs1), opcodestr, "$rd, $rs1"> { 502 let rs2 = funct5; 503} 504} 505 506// Operands for stores are in the order srcreg, base, offset rather than 507// reflecting the order these fields are specified in the instruction 508// encoding. 509let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in { 510class Store_rri<bits<3> funct3, string opcodestr> 511 : RVInstS<funct3, OPC_STORE, (outs), 512 (ins GPR:$rs2, GPR:$rs1, simm12:$imm12), 513 opcodestr, "$rs2, ${imm12}(${rs1})">; 514 515class HStore_rr<bits<7> funct7, string opcodestr> 516 : RVInstR<funct7, 0b100, OPC_SYSTEM, (outs), 517 (ins GPR:$rs2, GPRMemZeroOffset:$rs1), 518 opcodestr, "$rs2, $rs1"> { 519 let rd = 0; 520} 521} 522 523let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 524class ALU_ri<bits<3> funct3, string opcodestr> 525 : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), 526 opcodestr, "$rd, $rs1, $imm12">, 527 Sched<[WriteIALU, ReadIALU]>; 528 529let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 530class Shift_ri<bits<5> imm11_7, bits<3> funct3, string opcodestr> 531 : RVInstIShift<imm11_7, funct3, OPC_OP_IMM, (outs GPR:$rd), 532 (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr, 533 "$rd, $rs1, $shamt">, 534 Sched<[WriteShiftImm, ReadShiftImm]>; 535 536let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 537class ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr, 538 bit Commutable = 0> 539 : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), 540 opcodestr, "$rd, $rs1, $rs2"> { 541 let isCommutable = Commutable; 542} 543 544let hasNoSchedulingInfo = 1, 545 hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 546class CSR_ir<bits<3> funct3, string opcodestr> 547 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins csr_sysreg:$imm12, GPR:$rs1), 548 opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR, ReadCSR]>; 549 550let hasNoSchedulingInfo = 1, 551 hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 552class CSR_ii<bits<3> funct3, string opcodestr> 553 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), 554 (ins csr_sysreg:$imm12, uimm5:$rs1), 555 opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR]>; 556 557let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 558class ShiftW_ri<bits<7> imm11_5, bits<3> funct3, string opcodestr> 559 : RVInstIShiftW<imm11_5, funct3, OPC_OP_IMM_32, (outs GPR:$rd), 560 (ins GPR:$rs1, uimm5:$shamt), opcodestr, 561 "$rd, $rs1, $shamt">, 562 Sched<[WriteShiftImm32, ReadShiftImm32]>; 563 564let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 565class ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr, 566 bit Commutable = 0> 567 : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd), 568 (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2"> { 569 let isCommutable = Commutable; 570} 571 572let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 573class Priv<string opcodestr, bits<7> funct7> 574 : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2), 575 opcodestr, "">; 576 577let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 578class Priv_rr<string opcodestr, bits<7> funct7> 579 : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2), 580 opcodestr, "$rs1, $rs2"> { 581 let rd = 0; 582} 583 584//===----------------------------------------------------------------------===// 585// Instructions 586//===----------------------------------------------------------------------===// 587 588let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { 589let isReMaterializable = 1, isAsCheapAsAMove = 1 in 590def LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20_lui:$imm20), 591 "lui", "$rd, $imm20">, Sched<[WriteIALU]>; 592 593def AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20_auipc:$imm20), 594 "auipc", "$rd, $imm20">, Sched<[WriteIALU]>; 595 596let isCall = 1 in 597def JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20), 598 "jal", "$rd, $imm20">, Sched<[WriteJal]>; 599 600let isCall = 1 in 601def JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd), 602 (ins GPR:$rs1, simm12:$imm12), 603 "jalr", "$rd, ${imm12}(${rs1})">, 604 Sched<[WriteJalr, ReadJalr]>; 605} // hasSideEffects = 0, mayLoad = 0, mayStore = 0 606 607def BEQ : BranchCC_rri<0b000, "beq">; 608def BNE : BranchCC_rri<0b001, "bne">; 609def BLT : BranchCC_rri<0b100, "blt">; 610def BGE : BranchCC_rri<0b101, "bge">; 611def BLTU : BranchCC_rri<0b110, "bltu">; 612def BGEU : BranchCC_rri<0b111, "bgeu">; 613 614def LB : Load_ri<0b000, "lb">, Sched<[WriteLDB, ReadMemBase]>; 615def LH : Load_ri<0b001, "lh">, Sched<[WriteLDH, ReadMemBase]>; 616def LW : Load_ri<0b010, "lw">, Sched<[WriteLDW, ReadMemBase]>; 617def LBU : Load_ri<0b100, "lbu">, Sched<[WriteLDB, ReadMemBase]>; 618def LHU : Load_ri<0b101, "lhu">, Sched<[WriteLDH, ReadMemBase]>; 619 620def SB : Store_rri<0b000, "sb">, Sched<[WriteSTB, ReadStoreData, ReadMemBase]>; 621def SH : Store_rri<0b001, "sh">, Sched<[WriteSTH, ReadStoreData, ReadMemBase]>; 622def SW : Store_rri<0b010, "sw">, Sched<[WriteSTW, ReadStoreData, ReadMemBase]>; 623 624// ADDI isn't always rematerializable, but isReMaterializable will be used as 625// a hint which is verified in isReallyTriviallyReMaterializable. 626let isReMaterializable = 1, isAsCheapAsAMove = 1 in 627def ADDI : ALU_ri<0b000, "addi">; 628 629def SLTI : ALU_ri<0b010, "slti">; 630def SLTIU : ALU_ri<0b011, "sltiu">; 631 632let isReMaterializable = 1, isAsCheapAsAMove = 1 in { 633def XORI : ALU_ri<0b100, "xori">; 634def ORI : ALU_ri<0b110, "ori">; 635} 636 637def ANDI : ALU_ri<0b111, "andi">; 638 639def SLLI : Shift_ri<0b00000, 0b001, "slli">; 640def SRLI : Shift_ri<0b00000, 0b101, "srli">; 641def SRAI : Shift_ri<0b01000, 0b101, "srai">; 642 643def ADD : ALU_rr<0b0000000, 0b000, "add", /*Commutable*/1>, 644 Sched<[WriteIALU, ReadIALU, ReadIALU]>; 645def SUB : ALU_rr<0b0100000, 0b000, "sub">, 646 Sched<[WriteIALU, ReadIALU, ReadIALU]>; 647def SLL : ALU_rr<0b0000000, 0b001, "sll">, 648 Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 649def SLT : ALU_rr<0b0000000, 0b010, "slt">, 650 Sched<[WriteIALU, ReadIALU, ReadIALU]>; 651def SLTU : ALU_rr<0b0000000, 0b011, "sltu">, 652 Sched<[WriteIALU, ReadIALU, ReadIALU]>; 653def XOR : ALU_rr<0b0000000, 0b100, "xor", /*Commutable*/1>, 654 Sched<[WriteIALU, ReadIALU, ReadIALU]>; 655def SRL : ALU_rr<0b0000000, 0b101, "srl">, 656 Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 657def SRA : ALU_rr<0b0100000, 0b101, "sra">, 658 Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 659def OR : ALU_rr<0b0000000, 0b110, "or", /*Commutable*/1>, 660 Sched<[WriteIALU, ReadIALU, ReadIALU]>; 661def AND : ALU_rr<0b0000000, 0b111, "and", /*Commutable*/1>, 662 Sched<[WriteIALU, ReadIALU, ReadIALU]>; 663 664let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { 665def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs), 666 (ins fencearg:$pred, fencearg:$succ), 667 "fence", "$pred, $succ">, Sched<[]> { 668 bits<4> pred; 669 bits<4> succ; 670 671 let rs1 = 0; 672 let rd = 0; 673 let imm12 = {0b0000,pred,succ}; 674} 675 676def FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", "">, Sched<[]> { 677 let rs1 = 0; 678 let rd = 0; 679 let imm12 = {0b1000,0b0011,0b0011}; 680} 681 682def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", "">, Sched<[]> { 683 let rs1 = 0; 684 let rd = 0; 685 let imm12 = 0; 686} 687 688def ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", "">, Sched<[WriteJmp]> { 689 let rs1 = 0; 690 let rd = 0; 691 let imm12 = 0; 692} 693 694def EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", "">, 695 Sched<[]> { 696 let rs1 = 0; 697 let rd = 0; 698 let imm12 = 1; 699} 700 701// This is a de facto standard (as set by GNU binutils) 32-bit unimplemented 702// instruction (i.e., it should always trap, if your implementation has invalid 703// instruction traps). 704def UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", "">, 705 Sched<[]> { 706 let rs1 = 0; 707 let rd = 0; 708 let imm12 = 0b110000000000; 709} 710} // hasSideEffects = 1, mayLoad = 0, mayStore = 0 711 712def CSRRW : CSR_ir<0b001, "csrrw">; 713def CSRRS : CSR_ir<0b010, "csrrs">; 714def CSRRC : CSR_ir<0b011, "csrrc">; 715 716def CSRRWI : CSR_ii<0b101, "csrrwi">; 717def CSRRSI : CSR_ii<0b110, "csrrsi">; 718def CSRRCI : CSR_ii<0b111, "csrrci">; 719 720/// RV64I instructions 721 722let Predicates = [IsRV64] in { 723def LWU : Load_ri<0b110, "lwu">, Sched<[WriteLDWU, ReadMemBase]>; 724def LD : Load_ri<0b011, "ld">, Sched<[WriteLDD, ReadMemBase]>; 725def SD : Store_rri<0b011, "sd">, Sched<[WriteSTD, ReadStoreData, ReadMemBase]>; 726 727let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 728def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd), 729 (ins GPR:$rs1, simm12:$imm12), 730 "addiw", "$rd, $rs1, $imm12">, 731 Sched<[WriteIALU32, ReadIALU32]>; 732 733def SLLIW : ShiftW_ri<0b0000000, 0b001, "slliw">; 734def SRLIW : ShiftW_ri<0b0000000, 0b101, "srliw">; 735def SRAIW : ShiftW_ri<0b0100000, 0b101, "sraiw">; 736 737def ADDW : ALUW_rr<0b0000000, 0b000, "addw", /*Commutable*/1>, 738 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 739def SUBW : ALUW_rr<0b0100000, 0b000, "subw">, 740 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 741def SLLW : ALUW_rr<0b0000000, 0b001, "sllw">, 742 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 743def SRLW : ALUW_rr<0b0000000, 0b101, "srlw">, 744 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 745def SRAW : ALUW_rr<0b0100000, 0b101, "sraw">, 746 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 747} // Predicates = [IsRV64] 748 749//===----------------------------------------------------------------------===// 750// Privileged instructions 751//===----------------------------------------------------------------------===// 752 753let isBarrier = 1, isReturn = 1, isTerminator = 1 in { 754def URET : Priv<"uret", 0b0000000>, Sched<[]> { 755 let rd = 0; 756 let rs1 = 0; 757 let rs2 = 0b00010; 758} 759 760def SRET : Priv<"sret", 0b0001000>, Sched<[]> { 761 let rd = 0; 762 let rs1 = 0; 763 let rs2 = 0b00010; 764} 765 766def MRET : Priv<"mret", 0b0011000>, Sched<[]> { 767 let rd = 0; 768 let rs1 = 0; 769 let rs2 = 0b00010; 770} 771} // isBarrier = 1, isReturn = 1, isTerminator = 1 772 773def WFI : Priv<"wfi", 0b0001000>, Sched<[]> { 774 let rd = 0; 775 let rs1 = 0; 776 let rs2 = 0b00101; 777} 778 779def SFENCE_W_INVAL : Priv<"sfence.w.inval", 0b0001100>, Sched<[]> { 780 let rd = 0; 781 let rs1 = 0; 782 let rs2 = 0; 783} 784 785def SFENCE_INVAL_IR : Priv<"sfence.inval.ir", 0b0001100>, Sched<[]> { 786 let rd = 0; 787 let rs1 = 0; 788 let rs2 = 0b00001; 789} 790 791def SFENCE_VMA : Priv_rr<"sfence.vma", 0b0001001>, Sched<[]>; 792def SINVAL_VMA : Priv_rr<"sinval.vma", 0b0001011>, Sched<[]>; 793def HFENCE_VVMA : Priv_rr<"hfence.vvma", 0b0010001>, Sched<[]>; 794def HFENCE_GVMA : Priv_rr<"hfence.gvma", 0b0110001>, Sched<[]>; 795def HINVAL_VVMA : Priv_rr<"hinval.vvma", 0b0010011>, Sched<[]>; 796def HINVAL_GVMA : Priv_rr<"hinval.gvma", 0b0110011>, Sched<[]>; 797 798def HLV_B : HLoad_r<0b0110000, 0b00000, "hlv.b">, Sched<[]>; 799def HLV_BU : HLoad_r<0b0110000, 0b00001, "hlv.bu">, Sched<[]>; 800def HLV_H : HLoad_r<0b0110010, 0b00000, "hlv.h">, Sched<[]>; 801def HLV_HU : HLoad_r<0b0110010, 0b00001, "hlv.hu">, Sched<[]>; 802def HLVX_HU : HLoad_r<0b0110010, 0b00011, "hlvx.hu">, Sched<[]>; 803def HLV_W : HLoad_r<0b0110100, 0b00000, "hlv.w">, Sched<[]>; 804def HLVX_WU : HLoad_r<0b0110100, 0b00011, "hlvx.wu">, Sched<[]>; 805def HSV_B : HStore_rr<0b0110001, "hsv.b">, Sched<[]>; 806def HSV_H : HStore_rr<0b0110011, "hsv.h">, Sched<[]>; 807def HSV_W : HStore_rr<0b0110101, "hsv.w">, Sched<[]>; 808 809let Predicates = [IsRV64] in { 810def HLV_WU : HLoad_r<0b0110100, 0b00001, "hlv.wu">, Sched<[]>; 811def HLV_D : HLoad_r<0b0110110, 0b00000, "hlv.d">, Sched<[]>; 812def HSV_D : HStore_rr<0b0110111, "hsv.d">, Sched<[]>; 813} 814 815//===----------------------------------------------------------------------===// 816// Debug instructions 817//===----------------------------------------------------------------------===// 818 819let isBarrier = 1, isReturn = 1, isTerminator = 1 in { 820def DRET : Priv<"dret", 0b0111101>, Sched<[]> { 821 let rd = 0; 822 let rs1 = 0; 823 let rs2 = 0b10010; 824} 825} // isBarrier = 1, isReturn = 1, isTerminator = 1 826 827//===----------------------------------------------------------------------===// 828// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) 829//===----------------------------------------------------------------------===// 830 831def : InstAlias<"nop", (ADDI X0, X0, 0)>; 832 833// Note that the size is 32 because up to 8 32-bit instructions are needed to 834// generate an arbitrary 64-bit immediate. However, the size does not really 835// matter since PseudoLI is currently only used in the AsmParser where it gets 836// expanded to real instructions immediately. 837let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32, 838 isCodeGenOnly = 0, isAsmParserOnly = 1 in 839def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [], 840 "li", "$rd, $imm">; 841 842def PseudoLB : PseudoLoad<"lb">; 843def PseudoLBU : PseudoLoad<"lbu">; 844def PseudoLH : PseudoLoad<"lh">; 845def PseudoLHU : PseudoLoad<"lhu">; 846def PseudoLW : PseudoLoad<"lw">; 847 848def PseudoSB : PseudoStore<"sb">; 849def PseudoSH : PseudoStore<"sh">; 850def PseudoSW : PseudoStore<"sw">; 851 852let Predicates = [IsRV64] in { 853def PseudoLWU : PseudoLoad<"lwu">; 854def PseudoLD : PseudoLoad<"ld">; 855def PseudoSD : PseudoStore<"sd">; 856} // Predicates = [IsRV64] 857 858def : InstAlias<"li $rd, $imm", (ADDI GPR:$rd, X0, simm12:$imm)>; 859def : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>; 860def : InstAlias<"not $rd, $rs", (XORI GPR:$rd, GPR:$rs, -1)>; 861def : InstAlias<"neg $rd, $rs", (SUB GPR:$rd, X0, GPR:$rs)>; 862 863let Predicates = [IsRV64] in { 864def : InstAlias<"negw $rd, $rs", (SUBW GPR:$rd, X0, GPR:$rs)>; 865def : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs, 0)>; 866} // Predicates = [IsRV64] 867 868def : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs, 1)>; 869def : InstAlias<"snez $rd, $rs", (SLTU GPR:$rd, X0, GPR:$rs)>; 870def : InstAlias<"sltz $rd, $rs", (SLT GPR:$rd, GPR:$rs, X0)>; 871def : InstAlias<"sgtz $rd, $rs", (SLT GPR:$rd, X0, GPR:$rs)>; 872 873// sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu 874// form will always be printed. Therefore, set a zero weight. 875def : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>; 876def : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>; 877 878def : InstAlias<"beqz $rs, $offset", 879 (BEQ GPR:$rs, X0, simm13_lsb0:$offset)>; 880def : InstAlias<"bnez $rs, $offset", 881 (BNE GPR:$rs, X0, simm13_lsb0:$offset)>; 882def : InstAlias<"blez $rs, $offset", 883 (BGE X0, GPR:$rs, simm13_lsb0:$offset)>; 884def : InstAlias<"bgez $rs, $offset", 885 (BGE GPR:$rs, X0, simm13_lsb0:$offset)>; 886def : InstAlias<"bltz $rs, $offset", 887 (BLT GPR:$rs, X0, simm13_lsb0:$offset)>; 888def : InstAlias<"bgtz $rs, $offset", 889 (BLT X0, GPR:$rs, simm13_lsb0:$offset)>; 890 891// Always output the canonical mnemonic for the pseudo branch instructions. 892// The GNU tools emit the canonical mnemonic for the branch pseudo instructions 893// as well (e.g. "bgt" will be recognised by the assembler but never printed by 894// objdump). Match this behaviour by setting a zero weight. 895def : InstAlias<"bgt $rs, $rt, $offset", 896 (BLT GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 897def : InstAlias<"ble $rs, $rt, $offset", 898 (BGE GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 899def : InstAlias<"bgtu $rs, $rt, $offset", 900 (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 901def : InstAlias<"bleu $rs, $rt, $offset", 902 (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 903 904def : InstAlias<"j $offset", (JAL X0, simm21_lsb0_jal:$offset)>; 905def : InstAlias<"jal $offset", (JAL X1, simm21_lsb0_jal:$offset)>; 906 907// Non-zero offset aliases of "jalr" are the lowest weight, followed by the 908// two-register form, then the one-register forms and finally "ret". 909def : InstAlias<"jr $rs", (JALR X0, GPR:$rs, 0), 3>; 910def : InstAlias<"jr ${offset}(${rs})", (JALR X0, GPR:$rs, simm12:$offset)>; 911def : InstAlias<"jalr $rs", (JALR X1, GPR:$rs, 0), 3>; 912def : InstAlias<"jalr ${offset}(${rs})", (JALR X1, GPR:$rs, simm12:$offset)>; 913def : InstAlias<"jalr $rd, $rs", (JALR GPR:$rd, GPR:$rs, 0), 2>; 914def : InstAlias<"ret", (JALR X0, X1, 0), 4>; 915 916// Non-canonical forms for jump targets also accepted by the assembler. 917def : InstAlias<"jr $rs, $offset", (JALR X0, GPR:$rs, simm12:$offset), 0>; 918def : InstAlias<"jalr $rs, $offset", (JALR X1, GPR:$rs, simm12:$offset), 0>; 919def : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12:$offset), 0>; 920 921def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw 922 923let Predicates = [HasStdExtZihintpause] in 924def : InstAlias<"pause", (FENCE 0x1, 0x0)>; // 0x1 == w 925 926def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>; 927def : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, CYCLE.Encoding, X0)>; 928def : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, TIME.Encoding, X0)>; 929 930let Predicates = [IsRV32] in { 931def : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, INSTRETH.Encoding, X0)>; 932def : InstAlias<"rdcycleh $rd", (CSRRS GPR:$rd, CYCLEH.Encoding, X0)>; 933def : InstAlias<"rdtimeh $rd", (CSRRS GPR:$rd, TIMEH.Encoding, X0)>; 934} // Predicates = [IsRV32] 935 936def : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, csr_sysreg:$csr, X0)>; 937def : InstAlias<"csrw $csr, $rs", (CSRRW X0, csr_sysreg:$csr, GPR:$rs)>; 938def : InstAlias<"csrs $csr, $rs", (CSRRS X0, csr_sysreg:$csr, GPR:$rs)>; 939def : InstAlias<"csrc $csr, $rs", (CSRRC X0, csr_sysreg:$csr, GPR:$rs)>; 940 941def : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>; 942def : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>; 943def : InstAlias<"csrci $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>; 944 945let EmitPriority = 0 in { 946def : InstAlias<"csrw $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>; 947def : InstAlias<"csrs $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>; 948def : InstAlias<"csrc $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>; 949 950def : InstAlias<"csrrw $rd, $csr, $imm", (CSRRWI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 951def : InstAlias<"csrrs $rd, $csr, $imm", (CSRRSI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 952def : InstAlias<"csrrc $rd, $csr, $imm", (CSRRCI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 953} 954 955def : InstAlias<"sfence.vma", (SFENCE_VMA X0, X0)>; 956def : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>; 957 958def : InstAlias<"hfence.gvma", (HFENCE_GVMA X0, X0)>; 959def : InstAlias<"hfence.gvma $rs", (HFENCE_GVMA GPR:$rs, X0)>; 960 961def : InstAlias<"hfence.vvma", (HFENCE_VVMA X0, X0)>; 962def : InstAlias<"hfence.vvma $rs", (HFENCE_VVMA GPR:$rs, X0)>; 963 964let EmitPriority = 0 in { 965def : InstAlias<"lb $rd, (${rs1})", 966 (LB GPR:$rd, GPR:$rs1, 0)>; 967def : InstAlias<"lh $rd, (${rs1})", 968 (LH GPR:$rd, GPR:$rs1, 0)>; 969def : InstAlias<"lw $rd, (${rs1})", 970 (LW GPR:$rd, GPR:$rs1, 0)>; 971def : InstAlias<"lbu $rd, (${rs1})", 972 (LBU GPR:$rd, GPR:$rs1, 0)>; 973def : InstAlias<"lhu $rd, (${rs1})", 974 (LHU GPR:$rd, GPR:$rs1, 0)>; 975 976def : InstAlias<"sb $rs2, (${rs1})", 977 (SB GPR:$rs2, GPR:$rs1, 0)>; 978def : InstAlias<"sh $rs2, (${rs1})", 979 (SH GPR:$rs2, GPR:$rs1, 0)>; 980def : InstAlias<"sw $rs2, (${rs1})", 981 (SW GPR:$rs2, GPR:$rs1, 0)>; 982 983def : InstAlias<"add $rd, $rs1, $imm12", 984 (ADDI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 985def : InstAlias<"and $rd, $rs1, $imm12", 986 (ANDI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 987def : InstAlias<"xor $rd, $rs1, $imm12", 988 (XORI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 989def : InstAlias<"or $rd, $rs1, $imm12", 990 (ORI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 991def : InstAlias<"sll $rd, $rs1, $shamt", 992 (SLLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 993def : InstAlias<"srl $rd, $rs1, $shamt", 994 (SRLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 995def : InstAlias<"sra $rd, $rs1, $shamt", 996 (SRAI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 997let Predicates = [IsRV64] in { 998def : InstAlias<"lwu $rd, (${rs1})", 999 (LWU GPR:$rd, GPR:$rs1, 0)>; 1000def : InstAlias<"ld $rd, (${rs1})", 1001 (LD GPR:$rd, GPR:$rs1, 0)>; 1002def : InstAlias<"sd $rs2, (${rs1})", 1003 (SD GPR:$rs2, GPR:$rs1, 0)>; 1004 1005def : InstAlias<"addw $rd, $rs1, $imm12", 1006 (ADDIW GPR:$rd, GPR:$rs1, simm12:$imm12)>; 1007def : InstAlias<"sllw $rd, $rs1, $shamt", 1008 (SLLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 1009def : InstAlias<"srlw $rd, $rs1, $shamt", 1010 (SRLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 1011def : InstAlias<"sraw $rd, $rs1, $shamt", 1012 (SRAIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 1013} // Predicates = [IsRV64] 1014def : InstAlias<"slt $rd, $rs1, $imm12", 1015 (SLTI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 1016def : InstAlias<"sltu $rd, $rs1, $imm12", 1017 (SLTIU GPR:$rd, GPR:$rs1, simm12:$imm12)>; 1018} 1019 1020def : MnemonicAlias<"move", "mv">; 1021 1022// The SCALL and SBREAK instructions wererenamed to ECALL and EBREAK in 1023// version 2.1 of the user-level ISA. Like the GNU toolchain, we still accept 1024// the old name for backwards compatibility. 1025def : MnemonicAlias<"scall", "ecall">; 1026def : MnemonicAlias<"sbreak", "ebreak">; 1027 1028// This alias was added to the spec in December 2020. Don't print it by default 1029// to allow assembly we print to be compatible with versions of GNU assembler 1030// that don't support this alias. 1031def : InstAlias<"zext.b $rd, $rs", (ANDI GPR:$rd, GPR:$rs, 0xFF), 0>; 1032 1033//===----------------------------------------------------------------------===// 1034// .insn directive instructions 1035//===----------------------------------------------------------------------===// 1036 1037// isCodeGenOnly = 1 to hide them from the tablegened assembly parser. 1038let isCodeGenOnly = 1, hasSideEffects = 1, mayLoad = 1, mayStore = 1, 1039 hasNoSchedulingInfo = 1 in { 1040def InsnR : DirectiveInsnR<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1041 uimm7:$funct7, AnyReg:$rs1, 1042 AnyReg:$rs2), 1043 "$opcode, $funct3, $funct7, $rd, $rs1, $rs2">; 1044def InsnR4 : DirectiveInsnR4<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1045 uimm3:$funct3, 1046 uimm2:$funct2, 1047 AnyReg:$rs1, AnyReg:$rs2, 1048 AnyReg:$rs3), 1049 "$opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3">; 1050def InsnI : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1051 AnyReg:$rs1, simm12:$imm12), 1052 "$opcode, $funct3, $rd, $rs1, $imm12">; 1053def InsnI_Mem : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1054 uimm3:$funct3, 1055 AnyReg:$rs1, 1056 simm12:$imm12), 1057 "$opcode, $funct3, $rd, ${imm12}(${rs1})">; 1058def InsnB : DirectiveInsnB<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1059 AnyReg:$rs1, AnyReg:$rs2, 1060 simm13_lsb0:$imm12), 1061 "$opcode, $funct3, $rs1, $rs2, $imm12">; 1062def InsnU : DirectiveInsnU<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1063 uimm20_lui:$imm20), 1064 "$opcode, $rd, $imm20">; 1065def InsnJ : DirectiveInsnJ<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1066 simm21_lsb0_jal:$imm20), 1067 "$opcode, $rd, $imm20">; 1068def InsnS : DirectiveInsnS<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1069 AnyReg:$rs2, AnyReg:$rs1, 1070 simm12:$imm12), 1071 "$opcode, $funct3, $rs2, ${imm12}(${rs1})">; 1072} 1073 1074// Use InstAliases to match these so that we can combine the insn and format 1075// into a mnemonic to use as the key for the tablegened asm matcher table. The 1076// parser will take care of creating these fake mnemonics and will only do it 1077// for known formats. 1078let EmitPriority = 0 in { 1079def : InstAlias<".insn_r $opcode, $funct3, $funct7, $rd, $rs1, $rs2", 1080 (InsnR AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm7:$funct7, 1081 AnyReg:$rs1, AnyReg:$rs2)>; 1082// Accept 4 register form of ".insn r" as alias for ".insn r4". 1083def : InstAlias<".insn_r $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3", 1084 (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2, 1085 AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>; 1086def : InstAlias<".insn_r4 $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3", 1087 (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2, 1088 AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>; 1089def : InstAlias<".insn_i $opcode, $funct3, $rd, $rs1, $imm12", 1090 (InsnI AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 1091 simm12:$imm12)>; 1092def : InstAlias<".insn_i $opcode, $funct3, $rd, ${imm12}(${rs1})", 1093 (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, 1094 AnyReg:$rs1, simm12:$imm12)>; 1095def : InstAlias<".insn_b $opcode, $funct3, $rs1, $rs2, $imm12", 1096 (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 1097 AnyReg:$rs2, simm13_lsb0:$imm12)>; 1098// Accept sb as an alias for b. 1099def : InstAlias<".insn_sb $opcode, $funct3, $rs1, $rs2, $imm12", 1100 (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 1101 AnyReg:$rs2, simm13_lsb0:$imm12)>; 1102def : InstAlias<".insn_u $opcode, $rd, $imm20", 1103 (InsnU AnyReg:$rd, uimm7_opcode:$opcode, uimm20_lui:$imm20)>; 1104def : InstAlias<".insn_j $opcode, $rd, $imm20", 1105 (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>; 1106// Accept uj as an alias for j. 1107def : InstAlias<".insn_uj $opcode, $rd, $imm20", 1108 (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>; 1109def : InstAlias<".insn_s $opcode, $funct3, $rs2, ${imm12}(${rs1})", 1110 (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2, 1111 AnyReg:$rs1, simm12:$imm12)>; 1112} 1113 1114//===----------------------------------------------------------------------===// 1115// Pseudo-instructions and codegen patterns 1116// 1117// Naming convention: For 'generic' pattern classes, we use the naming 1118// convention PatTy1Ty2. For pattern classes which offer a more complex 1119// expansion, prefix the class name, e.g. BccPat. 1120//===----------------------------------------------------------------------===// 1121 1122/// Generic pattern classes 1123 1124class PatGpr<SDPatternOperator OpNode, RVInst Inst> 1125 : Pat<(OpNode GPR:$rs1), (Inst GPR:$rs1)>; 1126class PatGprGpr<SDPatternOperator OpNode, RVInst Inst> 1127 : Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>; 1128 1129class PatGprImm<SDPatternOperator OpNode, RVInst Inst, ImmLeaf ImmType> 1130 : Pat<(XLenVT (OpNode (XLenVT GPR:$rs1), ImmType:$imm)), 1131 (Inst GPR:$rs1, ImmType:$imm)>; 1132class PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst> 1133 : PatGprImm<OpNode, Inst, simm12>; 1134class PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst> 1135 : PatGprImm<OpNode, Inst, uimmlog2xlen>; 1136 1137/// Predicates 1138 1139def assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{ 1140 return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32); 1141}]>; 1142def sexti32 : ComplexPattern<i64, 1, "selectSExti32">; 1143def assertzexti32 : PatFrag<(ops node:$src), (assertzext node:$src), [{ 1144 return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32); 1145}]>; 1146def zexti32 : ComplexPattern<i64, 1, "selectZExti32">; 1147 1148class binop_oneuse<SDPatternOperator operator> 1149 : PatFrag<(ops node:$A, node:$B), 1150 (operator node:$A, node:$B), [{ 1151 return N->hasOneUse(); 1152}]>; 1153 1154def add_oneuse : binop_oneuse<add>; 1155def mul_oneuse : binop_oneuse<mul>; 1156 1157def mul_const_oneuse : PatFrag<(ops node:$A, node:$B), 1158 (mul node:$A, node:$B), [{ 1159 if (auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1))) 1160 if (N1C->hasOneUse()) 1161 return true; 1162 return false; 1163}]>; 1164 1165class unop_oneuse<SDPatternOperator operator> 1166 : PatFrag<(ops node:$A), 1167 (operator node:$A), [{ 1168 return N->hasOneUse(); 1169}]>; 1170 1171def sext_oneuse : unop_oneuse<sext>; 1172def zext_oneuse : unop_oneuse<zext>; 1173def anyext_oneuse : unop_oneuse<anyext>; 1174def fpext_oneuse : unop_oneuse<any_fpextend>; 1175 1176/// Simple arithmetic operations 1177 1178def : PatGprGpr<add, ADD>; 1179def : PatGprSimm12<add, ADDI>; 1180def : PatGprGpr<sub, SUB>; 1181def : PatGprGpr<or, OR>; 1182def : PatGprSimm12<or, ORI>; 1183def : PatGprGpr<and, AND>; 1184def : PatGprSimm12<and, ANDI>; 1185def : PatGprGpr<xor, XOR>; 1186def : PatGprSimm12<xor, XORI>; 1187def : PatGprUimmLog2XLen<shl, SLLI>; 1188def : PatGprUimmLog2XLen<srl, SRLI>; 1189def : PatGprUimmLog2XLen<sra, SRAI>; 1190 1191// AND with leading/trailing ones mask exceeding simm32/simm12. 1192def : Pat<(i64 (and GPR:$rs, LeadingOnesMask:$mask)), 1193 (SLLI (SRLI $rs, LeadingOnesMask:$mask), LeadingOnesMask:$mask)>; 1194def : Pat<(XLenVT (and GPR:$rs, TrailingOnesMask:$mask)), 1195 (SRLI (SLLI $rs, TrailingOnesMask:$mask), TrailingOnesMask:$mask)>; 1196 1197// Match both a plain shift and one where the shift amount is masked (this is 1198// typically introduced when the legalizer promotes the shift amount and 1199// zero-extends it). For RISC-V, the mask is unnecessary as shifts in the base 1200// ISA only read the least significant 5 bits (RV32I) or 6 bits (RV64I). 1201def shiftMaskXLen : ComplexPattern<XLenVT, 1, "selectShiftMaskXLen", [], [], 0>; 1202def shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>; 1203 1204class shiftop<SDPatternOperator operator> 1205 : PatFrag<(ops node:$val, node:$count), 1206 (operator node:$val, (XLenVT (shiftMaskXLen node:$count)))>; 1207class shiftopw<SDPatternOperator operator> 1208 : PatFrag<(ops node:$val, node:$count), 1209 (operator node:$val, (i64 (shiftMask32 node:$count)))>; 1210 1211def : PatGprGpr<shiftop<shl>, SLL>; 1212def : PatGprGpr<shiftop<srl>, SRL>; 1213def : PatGprGpr<shiftop<sra>, SRA>; 1214 1215// This is a special case of the ADD instruction used to facilitate the use of a 1216// fourth operand to emit a relocation on a symbol relating to this instruction. 1217// The relocation does not affect any bits of the instruction itself but is used 1218// as a hint to the linker. 1219let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in 1220def PseudoAddTPRel : Pseudo<(outs GPR:$rd), 1221 (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [], 1222 "add", "$rd, $rs1, $rs2, $src">; 1223 1224/// FrameIndex calculations 1225 1226def : Pat<(FrameAddrRegImm GPR:$rs1, simm12:$imm12), 1227 (ADDI GPR:$rs1, simm12:$imm12)>; 1228 1229/// HI and ADD_LO address nodes. 1230 1231def : Pat<(riscv_hi tglobaladdr:$in), (LUI tglobaladdr:$in)>; 1232def : Pat<(riscv_hi tblockaddress:$in), (LUI tblockaddress:$in)>; 1233def : Pat<(riscv_hi tjumptable:$in), (LUI tjumptable:$in)>; 1234def : Pat<(riscv_hi tconstpool:$in), (LUI tconstpool:$in)>; 1235 1236def : Pat<(riscv_add_lo GPR:$hi, tglobaladdr:$lo), 1237 (ADDI GPR:$hi, tglobaladdr:$lo)>; 1238def : Pat<(riscv_add_lo GPR:$hi, tblockaddress:$lo), 1239 (ADDI GPR:$hi, tblockaddress:$lo)>; 1240def : Pat<(riscv_add_lo GPR:$hi, tjumptable:$lo), 1241 (ADDI GPR:$hi, tjumptable:$lo)>; 1242def : Pat<(riscv_add_lo GPR:$hi, tconstpool:$lo), 1243 (ADDI GPR:$hi, tconstpool:$lo)>; 1244 1245/// TLS address nodes. 1246 1247def : Pat<(riscv_hi tglobaltlsaddr:$in), (LUI tglobaltlsaddr:$in)>; 1248def : Pat<(riscv_add_tprel GPR:$rs1, GPR:$rs2, tglobaltlsaddr:$src), 1249 (PseudoAddTPRel GPR:$rs1, GPR:$rs2, tglobaltlsaddr:$src)>; 1250def : Pat<(riscv_add_lo GPR:$src, tglobaltlsaddr:$lo), 1251 (ADDI GPR:$src, tglobaltlsaddr:$lo)>; 1252 1253/// Setcc 1254 1255def : PatGprGpr<setlt, SLT>; 1256def : PatGprSimm12<setlt, SLTI>; 1257def : PatGprGpr<setult, SLTU>; 1258def : PatGprSimm12<setult, SLTIU>; 1259 1260// Define pattern expansions for setcc operations that aren't directly 1261// handled by a RISC-V instruction. 1262def : Pat<(seteq GPR:$rs1, 0), (SLTIU GPR:$rs1, 1)>; 1263def : Pat<(seteq GPR:$rs1, GPR:$rs2), (SLTIU (XOR GPR:$rs1, GPR:$rs2), 1)>; 1264def : Pat<(seteq GPR:$rs1, simm12_plus1:$imm12), 1265 (SLTIU (ADDI GPR:$rs1, (NegImm simm12_plus1:$imm12)), 1)>; 1266def : Pat<(setne GPR:$rs1, 0), (SLTU X0, GPR:$rs1)>; 1267def : Pat<(setne GPR:$rs1, GPR:$rs2), (SLTU X0, (XOR GPR:$rs1, GPR:$rs2))>; 1268def : Pat<(setne GPR:$rs1, simm12_plus1:$imm12), 1269 (SLTU X0, (ADDI GPR:$rs1, (NegImm simm12_plus1:$imm12)))>; 1270def : Pat<(setugt GPR:$rs1, GPR:$rs2), (SLTU GPR:$rs2, GPR:$rs1)>; 1271def : Pat<(setuge GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs1, GPR:$rs2), 1)>; 1272def : Pat<(setule GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs2, GPR:$rs1), 1)>; 1273def : Pat<(setgt GPR:$rs1, GPR:$rs2), (SLT GPR:$rs2, GPR:$rs1)>; 1274def : Pat<(setge GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs1, GPR:$rs2), 1)>; 1275def : Pat<(setle GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs2, GPR:$rs1), 1)>; 1276def : Pat<(setgt GPR:$rs1, simm12_minus1_nonzero:$imm), 1277 (XORI (SLTI GPR:$rs1, (ImmPlus1 simm12_minus1_nonzero:$imm)), 1)>; 1278def : Pat<(setugt GPR:$rs1, simm12_minus1_nonzero:$imm), 1279 (XORI (SLTIU GPR:$rs1, (ImmPlus1 simm12_minus1_nonzero:$imm)), 1)>; 1280 1281// If negating a pattern that requires an XORI above, we can fold the XORI with 1282// the NEG. The XORI is equivalent to 1-X and negating gives X-1. 1283def : Pat<(ineg (setuge GPR:$rs1, GPR:$rs2)), (ADDI (SLTU GPR:$rs1, GPR:$rs2), -1)>; 1284def : Pat<(ineg (setule GPR:$rs1, GPR:$rs2)), (ADDI (SLTU GPR:$rs2, GPR:$rs1), -1)>; 1285def : Pat<(ineg (setge GPR:$rs1, GPR:$rs2)), (ADDI (SLT GPR:$rs1, GPR:$rs2), -1)>; 1286def : Pat<(ineg (setle GPR:$rs1, GPR:$rs2)), (ADDI (SLT GPR:$rs2, GPR:$rs1), -1)>; 1287 1288def IntCCtoRISCVCC : SDNodeXForm<riscv_selectcc, [{ 1289 ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get(); 1290 RISCVCC::CondCode BrCC = getRISCVCCForIntCC(CC); 1291 return CurDAG->getTargetConstant(BrCC, SDLoc(N), Subtarget->getXLenVT()); 1292}]>; 1293 1294def riscv_selectcc_frag : PatFrag<(ops node:$lhs, node:$rhs, node:$cc, 1295 node:$truev, node:$falsev), 1296 (riscv_selectcc node:$lhs, node:$rhs, 1297 node:$cc, node:$truev, 1298 node:$falsev), [{}], 1299 IntCCtoRISCVCC>; 1300 1301let usesCustomInserter = 1 in 1302class SelectCC_rrirr<RegisterClass valty, RegisterClass cmpty> 1303 : Pseudo<(outs valty:$dst), 1304 (ins cmpty:$lhs, cmpty:$rhs, ixlenimm:$imm, 1305 valty:$truev, valty:$falsev), 1306 [(set valty:$dst, 1307 (riscv_selectcc_frag:$imm cmpty:$lhs, cmpty:$rhs, cond, 1308 valty:$truev, valty:$falsev))]>; 1309 1310def Select_GPR_Using_CC_GPR : SelectCC_rrirr<GPR, GPR>; 1311 1312/// Branches and jumps 1313 1314// Match `riscv_brcc` and lower to the appropriate RISC-V branch instruction. 1315class BccPat<CondCode Cond, RVInstB Inst> 1316 : Pat<(riscv_brcc GPR:$rs1, GPR:$rs2, Cond, bb:$imm12), 1317 (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>; 1318 1319def : BccPat<SETEQ, BEQ>; 1320def : BccPat<SETNE, BNE>; 1321def : BccPat<SETLT, BLT>; 1322def : BccPat<SETGE, BGE>; 1323def : BccPat<SETULT, BLTU>; 1324def : BccPat<SETUGE, BGEU>; 1325 1326let isBarrier = 1, isBranch = 1, isTerminator = 1 in 1327def PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>, 1328 PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>; 1329 1330let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in 1331def PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12:$imm12), []>, 1332 PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; 1333 1334def : Pat<(brind GPRJALR:$rs1), (PseudoBRIND GPRJALR:$rs1, 0)>; 1335def : Pat<(brind (add GPRJALR:$rs1, simm12:$imm12)), 1336 (PseudoBRIND GPRJALR:$rs1, simm12:$imm12)>; 1337 1338// PseudoCALLReg is a generic pseudo instruction for calls which will eventually 1339// expand to auipc and jalr while encoding, with any given register used as the 1340// destination. 1341// Define AsmString to print "call" when compile with -S flag. 1342// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 1343let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, Size = 8, hasSideEffects = 0, 1344 mayStore = 0, mayLoad = 0 in 1345def PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), []>, 1346 Sched<[WriteIALU, WriteJalr, ReadJalr]> { 1347 let AsmString = "call\t$rd, $func"; 1348} 1349 1350// PseudoCALL is a pseudo instruction which will eventually expand to auipc 1351// and jalr while encoding. This is desirable, as an auipc+jalr pair with 1352// R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker 1353// if the offset fits in a signed 21-bit immediate. 1354// Define AsmString to print "call" when compile with -S flag. 1355// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 1356let isCall = 1, Defs = [X1], isCodeGenOnly = 0, Size = 8 in 1357def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), []>, 1358 Sched<[WriteIALU, WriteJalr, ReadJalr]> { 1359 let AsmString = "call\t$func"; 1360} 1361 1362def : Pat<(riscv_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>; 1363def : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>; 1364 1365def : Pat<(riscv_uret_flag), (URET X0, X0)>; 1366def : Pat<(riscv_sret_flag), (SRET X0, X0)>; 1367def : Pat<(riscv_mret_flag), (MRET X0, X0)>; 1368 1369let isCall = 1, Defs = [X1] in 1370def PseudoCALLIndirect : Pseudo<(outs), (ins GPRJALR:$rs1), 1371 [(riscv_call GPRJALR:$rs1)]>, 1372 PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>; 1373 1374let isBarrier = 1, isReturn = 1, isTerminator = 1 in 1375def PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_flag)]>, 1376 PseudoInstExpansion<(JALR X0, X1, 0)>; 1377 1378// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually 1379// expand to auipc and jalr while encoding. 1380// Define AsmString to print "tail" when compile with -S flag. 1381let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2], 1382 Size = 8, isCodeGenOnly = 0 in 1383def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), []>, 1384 Sched<[WriteIALU, WriteJalr, ReadJalr]> { 1385 let AsmString = "tail\t$dst"; 1386} 1387 1388let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in 1389def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1), 1390 [(riscv_tail GPRTC:$rs1)]>, 1391 PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>; 1392 1393def : Pat<(riscv_tail (iPTR tglobaladdr:$dst)), 1394 (PseudoTAIL tglobaladdr:$dst)>; 1395def : Pat<(riscv_tail (iPTR texternalsym:$dst)), 1396 (PseudoTAIL texternalsym:$dst)>; 1397 1398let isCall = 0, isBarrier = 1, isBranch = 1, isTerminator = 1, Size = 8, 1399 isCodeGenOnly = 0, hasSideEffects = 0, mayStore = 0, mayLoad = 0 in 1400def PseudoJump : Pseudo<(outs GPR:$rd), (ins pseudo_jump_symbol:$target), []>, 1401 Sched<[WriteIALU, WriteJalr, ReadJalr]> { 1402 let AsmString = "jump\t$target, $rd"; 1403} 1404 1405let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0, 1406 isAsmParserOnly = 1 in 1407def PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1408 "lla", "$dst, $src">; 1409 1410def : Pat<(riscv_lla tglobaladdr:$in), (PseudoLLA tglobaladdr:$in)>; 1411def : Pat<(riscv_lla tblockaddress:$in), (PseudoLLA tblockaddress:$in)>; 1412def : Pat<(riscv_lla tjumptable:$in), (PseudoLLA tjumptable:$in)>; 1413def : Pat<(riscv_lla tconstpool:$in), (PseudoLLA tconstpool:$in)>; 1414 1415let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0, 1416 isAsmParserOnly = 1 in 1417def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1418 "la", "$dst, $src">; 1419 1420def : Pat<(riscv_la tglobaladdr:$in), (PseudoLA tglobaladdr:$in)>; 1421 1422let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0, 1423 isAsmParserOnly = 1 in 1424def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1425 "la.tls.ie", "$dst, $src">; 1426 1427def : Pat<(riscv_la_tls_ie tglobaltlsaddr:$in), 1428 (PseudoLA_TLS_IE tglobaltlsaddr:$in)>; 1429 1430let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0, 1431 isAsmParserOnly = 1 in 1432def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1433 "la.tls.gd", "$dst, $src">; 1434 1435def : Pat<(riscv_la_tls_gd tglobaltlsaddr:$in), 1436 (PseudoLA_TLS_GD tglobaltlsaddr:$in)>; 1437 1438/// Sign/Zero Extends 1439 1440// There are single-instruction versions of these in Zbb, so disable these 1441// Pseudos if that extension is present. 1442let hasSideEffects = 0, mayLoad = 0, 1443 mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in { 1444def PseudoSEXT_B : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.b", "$rd, $rs">; 1445def PseudoSEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.h", "$rd, $rs">; 1446// rv64's sext.w is defined above, using InstAlias<"sext.w ... 1447// zext.b is defined above, using InstAlias<"zext.b ... 1448def PseudoZEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.h", "$rd, $rs">; 1449} // hasSideEffects = 0, ... 1450 1451let Predicates = [IsRV64], hasSideEffects = 0, mayLoad = 0, mayStore = 0, 1452 isCodeGenOnly = 0, isAsmParserOnly = 1 in { 1453def PseudoZEXT_W : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.w", "$rd, $rs">; 1454} // Predicates = [IsRV64], ... 1455 1456/// Loads 1457 1458multiclass LdPat<PatFrag LoadOp, RVInst Inst, ValueType vt = XLenVT> { 1459 def : Pat<(vt (LoadOp (AddrRegImm GPR:$rs1, simm12:$imm12))), 1460 (Inst GPR:$rs1, simm12:$imm12)>; 1461} 1462 1463defm : LdPat<sextloadi8, LB>; 1464defm : LdPat<extloadi8, LB>; 1465defm : LdPat<sextloadi16, LH>; 1466defm : LdPat<extloadi16, LH>; 1467defm : LdPat<load, LW, i32>, Requires<[IsRV32]>; 1468defm : LdPat<zextloadi8, LBU>; 1469defm : LdPat<zextloadi16, LHU>; 1470 1471/// Stores 1472 1473multiclass StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy, 1474 ValueType vt> { 1475 def : Pat<(StoreOp (vt StTy:$rs2), (AddrRegImm GPR:$rs1, simm12:$imm12)), 1476 (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>; 1477} 1478 1479defm : StPat<truncstorei8, SB, GPR, XLenVT>; 1480defm : StPat<truncstorei16, SH, GPR, XLenVT>; 1481defm : StPat<store, SW, GPR, i32>, Requires<[IsRV32]>; 1482 1483/// Fences 1484 1485// Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set 1486// Manual: Volume I. 1487 1488// fence acquire -> fence r, rw 1489def : Pat<(atomic_fence (XLenVT 4), (timm)), (FENCE 0b10, 0b11)>; 1490// fence release -> fence rw, w 1491def : Pat<(atomic_fence (XLenVT 5), (timm)), (FENCE 0b11, 0b1)>; 1492// fence acq_rel -> fence.tso 1493def : Pat<(atomic_fence (XLenVT 6), (timm)), (FENCE_TSO)>; 1494// fence seq_cst -> fence rw, rw 1495def : Pat<(atomic_fence (XLenVT 7), (timm)), (FENCE 0b11, 0b11)>; 1496 1497// Lowering for atomic load and store is defined in RISCVInstrInfoA.td. 1498// Although these are lowered to fence+load/store instructions defined in the 1499// base RV32I/RV64I ISA, this lowering is only used when the A extension is 1500// present. This is necessary as it isn't valid to mix __atomic_* libcalls 1501// with inline atomic operations for the same object. 1502 1503/// Access to system registers 1504 1505// Helpers for defining specific operations. They are defined for each system 1506// register separately. Side effect is not used because dependencies are 1507// expressed via use-def properties. 1508 1509class ReadSysReg<SysReg SR, list<Register> Regs> 1510 : Pseudo<(outs GPR:$rd), (ins), 1511 [(set GPR:$rd, (riscv_read_csr (XLenVT SR.Encoding)))]>, 1512 PseudoInstExpansion<(CSRRS GPR:$rd, SR.Encoding, X0)> { 1513 let hasSideEffects = 0; 1514 let Uses = Regs; 1515} 1516 1517class WriteSysReg<SysReg SR, list<Register> Regs> 1518 : Pseudo<(outs), (ins GPR:$val), 1519 [(riscv_write_csr (XLenVT SR.Encoding), GPR:$val)]>, 1520 PseudoInstExpansion<(CSRRW X0, SR.Encoding, GPR:$val)> { 1521 let hasSideEffects = 0; 1522 let Defs = Regs; 1523} 1524 1525class WriteSysRegImm<SysReg SR, list<Register> Regs> 1526 : Pseudo<(outs), (ins uimm5:$val), 1527 [(riscv_write_csr (XLenVT SR.Encoding), uimm5:$val)]>, 1528 PseudoInstExpansion<(CSRRWI X0, SR.Encoding, uimm5:$val)> { 1529 let hasSideEffects = 0; 1530 let Defs = Regs; 1531} 1532 1533class SwapSysReg<SysReg SR, list<Register> Regs> 1534 : Pseudo<(outs GPR:$rd), (ins GPR:$val), 1535 [(set GPR:$rd, (riscv_swap_csr (XLenVT SR.Encoding), GPR:$val))]>, 1536 PseudoInstExpansion<(CSRRW GPR:$rd, SR.Encoding, GPR:$val)> { 1537 let hasSideEffects = 0; 1538 let Uses = Regs; 1539 let Defs = Regs; 1540} 1541 1542class SwapSysRegImm<SysReg SR, list<Register> Regs> 1543 : Pseudo<(outs GPR:$rd), (ins uimm5:$val), 1544 [(set GPR:$rd, (riscv_swap_csr (XLenVT SR.Encoding), uimm5:$val))]>, 1545 PseudoInstExpansion<(CSRRWI GPR:$rd, SR.Encoding, uimm5:$val)> { 1546 let hasSideEffects = 0; 1547 let Uses = Regs; 1548 let Defs = Regs; 1549} 1550 1551def ReadFRM : ReadSysReg<SysRegFRM, [FRM]>; 1552def WriteFRM : WriteSysReg<SysRegFRM, [FRM]>; 1553def WriteFRMImm : WriteSysRegImm<SysRegFRM, [FRM]>; 1554 1555let hasSideEffects = true in { 1556def ReadFFLAGS : ReadSysReg<SysRegFFLAGS, [FFLAGS]>; 1557def WriteFFLAGS : WriteSysReg<SysRegFFLAGS, [FFLAGS]>; 1558} 1559/// Other pseudo-instructions 1560 1561// Pessimistically assume the stack pointer will be clobbered 1562let Defs = [X2], Uses = [X2] in { 1563def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 1564 [(callseq_start timm:$amt1, timm:$amt2)]>; 1565def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 1566 [(callseq_end timm:$amt1, timm:$amt2)]>; 1567} // Defs = [X2], Uses = [X2] 1568 1569/// RV64 patterns 1570 1571let Predicates = [IsRV64, NotHasStdExtZba] in { 1572def : Pat<(i64 (and GPR:$rs1, 0xffffffff)), (SRLI (SLLI GPR:$rs1, 32), 32)>; 1573 1574// If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2 1575// shifts instead of 3. This can occur when unsigned is used to index an array. 1576def : Pat<(i64 (shl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)), 1577 (SRLI (SLLI GPR:$rs1, 32), (ImmSubFrom32 uimm5:$shamt))>; 1578} 1579 1580// PatFrag to allow ADDW/SUBW/MULW/SLLW to be selected from i64 add/sub/mul/shl 1581// if only the lower 32 bits of their result is used. 1582class binop_allwusers<SDPatternOperator operator> 1583 : PatFrag<(ops node:$lhs, node:$rhs), 1584 (i64 (operator node:$lhs, node:$rhs)), [{ 1585 return hasAllWUsers(Node); 1586}]>; 1587 1588def sexti32_allwusers : PatFrag<(ops node:$src), 1589 (sext_inreg node:$src, i32), [{ 1590 return hasAllWUsers(Node); 1591}]>; 1592 1593let Predicates = [IsRV64] in { 1594 1595/// sext and zext 1596 1597// Sign extend is not needed if all users are W instructions. 1598def : Pat<(sexti32_allwusers GPR:$rs1), (XLenVT GPR:$rs1)>; 1599 1600def : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>; 1601 1602/// ALU operations 1603 1604def : Pat<(i64 (srl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)), 1605 (SRLIW GPR:$rs1, uimm5:$shamt)>; 1606def : Pat<(i64 (srl (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)), 1607 (SRLIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>; 1608def : Pat<(sra (sext_inreg GPR:$rs1, i32), uimm5:$shamt), 1609 (SRAIW GPR:$rs1, uimm5:$shamt)>; 1610def : Pat<(i64 (sra (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)), 1611 (SRAIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>; 1612 1613def : PatGprGpr<shiftopw<riscv_sllw>, SLLW>; 1614def : PatGprGpr<shiftopw<riscv_srlw>, SRLW>; 1615def : PatGprGpr<shiftopw<riscv_sraw>, SRAW>; 1616 1617// Select W instructions if only the lower 32 bits of the result are used. 1618def : PatGprGpr<binop_allwusers<add>, ADDW>; 1619def : PatGprSimm12<binop_allwusers<add>, ADDIW>; 1620def : PatGprGpr<binop_allwusers<sub>, SUBW>; 1621def : PatGprImm<binop_allwusers<shl>, SLLIW, uimm5>; 1622 1623// If this is a shr of a value sign extended from i32, and all the users only 1624// use the lower 32 bits, we can use an sraiw to remove the sext_inreg. This 1625// occurs because SimplifyDemandedBits prefers srl over sra. 1626def : Pat<(binop_allwusers<srl> (sext_inreg GPR:$rs1, i32), uimm5:$shamt), 1627 (SRAIW GPR:$rs1, uimm5:$shamt)>; 1628 1629/// Loads 1630 1631defm : LdPat<sextloadi32, LW, i64>; 1632defm : LdPat<extloadi32, LW, i64>; 1633defm : LdPat<zextloadi32, LWU, i64>; 1634defm : LdPat<load, LD, i64>; 1635 1636/// Stores 1637 1638defm : StPat<truncstorei32, SW, GPR, i64>; 1639defm : StPat<store, SD, GPR, i64>; 1640} // Predicates = [IsRV64] 1641 1642/// readcyclecounter 1643// On RV64, we can directly read the 64-bit "cycle" CSR. 1644let Predicates = [IsRV64] in 1645def : Pat<(i64 (readcyclecounter)), (CSRRS CYCLE.Encoding, X0)>; 1646// On RV32, ReadCycleWide will be expanded to the suggested loop reading both 1647// halves of the 64-bit "cycle" CSR. 1648let Predicates = [IsRV32], usesCustomInserter = 1, hasNoSchedulingInfo = 1 in 1649def ReadCycleWide : Pseudo<(outs GPR:$lo, GPR:$hi), (ins), 1650 [(set GPR:$lo, GPR:$hi, (riscv_read_cycle_wide))], 1651 "", "">; 1652 1653/// traps 1654 1655// We lower `trap` to `unimp`, as this causes a hard exception on nearly all 1656// systems. 1657def : Pat<(trap), (UNIMP)>; 1658 1659// We lower `debugtrap` to `ebreak`, as this will get the attention of the 1660// debugger if possible. 1661def : Pat<(debugtrap), (EBREAK)>; 1662 1663/// Simple optimization 1664def : Pat<(add GPR:$rs1, (AddiPair:$rs2)), 1665 (ADDI (ADDI GPR:$rs1, (AddiPairImmLarge AddiPair:$rs2)), 1666 (AddiPairImmSmall GPR:$rs2))>; 1667 1668let Predicates = [IsRV64] in { 1669// Select W instructions if only the lower 32-bits of the result are used. 1670def : Pat<(binop_allwusers<add> GPR:$rs1, (AddiPair:$rs2)), 1671 (ADDIW (ADDIW GPR:$rs1, (AddiPairImmLarge AddiPair:$rs2)), 1672 (AddiPairImmSmall AddiPair:$rs2))>; 1673} 1674 1675//===----------------------------------------------------------------------===// 1676// Standard extensions 1677//===----------------------------------------------------------------------===// 1678 1679include "RISCVInstrInfoM.td" 1680include "RISCVInstrInfoA.td" 1681include "RISCVInstrInfoF.td" 1682include "RISCVInstrInfoD.td" 1683include "RISCVInstrInfoC.td" 1684include "RISCVInstrInfoZb.td" 1685include "RISCVInstrInfoZk.td" 1686include "RISCVInstrInfoV.td" 1687include "RISCVInstrInfoZfh.td" 1688include "RISCVInstrInfoZicbo.td" 1689