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