1//===-- RISCVInstrInfo.td - Target Description for RISCV ---*- tablegen -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file describes the RISC-V instructions in TableGen format. 11// 12//===----------------------------------------------------------------------===// 13 14include "RISCVInstrFormats.td" 15 16//===----------------------------------------------------------------------===// 17// RISC-V specific DAG Nodes. 18//===----------------------------------------------------------------------===// 19 20def SDT_RISCVCall : SDTypeProfile<0, -1, [SDTCisVT<0, XLenVT>]>; 21def SDT_RISCVCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, 22 SDTCisVT<1, i32>]>; 23def SDT_RISCVCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, 24 SDTCisVT<1, i32>]>; 25def SDT_RISCVSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>, 26 SDTCisSameAs<0, 4>, 27 SDTCisSameAs<4, 5>]>; 28 29 30def Call : SDNode<"RISCVISD::CALL", SDT_RISCVCall, 31 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 32 SDNPVariadic]>; 33def CallSeqStart : SDNode<"ISD::CALLSEQ_START", SDT_RISCVCallSeqStart, 34 [SDNPHasChain, SDNPOutGlue]>; 35def CallSeqEnd : SDNode<"ISD::CALLSEQ_END", SDT_RISCVCallSeqEnd, 36 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; 37def RetFlag : SDNode<"RISCVISD::RET_FLAG", SDTNone, 38 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; 39def URetFlag : SDNode<"RISCVISD::URET_FLAG", SDTNone, 40 [SDNPHasChain, SDNPOptInGlue]>; 41def SRetFlag : SDNode<"RISCVISD::SRET_FLAG", SDTNone, 42 [SDNPHasChain, SDNPOptInGlue]>; 43def MRetFlag : SDNode<"RISCVISD::MRET_FLAG", SDTNone, 44 [SDNPHasChain, SDNPOptInGlue]>; 45def SelectCC : SDNode<"RISCVISD::SELECT_CC", SDT_RISCVSelectCC, 46 [SDNPInGlue]>; 47def Tail : SDNode<"RISCVISD::TAIL", SDT_RISCVCall, 48 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 49 SDNPVariadic]>; 50 51//===----------------------------------------------------------------------===// 52// Operand and SDNode transformation definitions. 53//===----------------------------------------------------------------------===// 54 55class ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass { 56 let Name = prefix # "ImmXLen" # suffix; 57 let RenderMethod = "addImmOperands"; 58 let DiagnosticType = !strconcat("Invalid", Name); 59} 60 61class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass { 62 let Name = prefix # "Imm" # width # suffix; 63 let RenderMethod = "addImmOperands"; 64 let DiagnosticType = !strconcat("Invalid", Name); 65} 66 67class SImmAsmOperand<int width, string suffix = ""> 68 : ImmAsmOperand<"S", width, suffix> { 69} 70 71class UImmAsmOperand<int width, string suffix = ""> 72 : ImmAsmOperand<"U", width, suffix> { 73} 74 75def FenceArg : AsmOperandClass { 76 let Name = "FenceArg"; 77 let RenderMethod = "addFenceArgOperands"; 78 let DiagnosticType = "InvalidFenceArg"; 79} 80 81def fencearg : Operand<XLenVT> { 82 let ParserMatchClass = FenceArg; 83 let PrintMethod = "printFenceArg"; 84 let DecoderMethod = "decodeUImmOperand<4>"; 85} 86 87def UImmLog2XLenAsmOperand : AsmOperandClass { 88 let Name = "UImmLog2XLen"; 89 let RenderMethod = "addImmOperands"; 90 let DiagnosticType = "InvalidUImmLog2XLen"; 91} 92 93def uimmlog2xlen : Operand<XLenVT>, ImmLeaf<XLenVT, [{ 94 if (Subtarget->is64Bit()) 95 return isUInt<6>(Imm); 96 return isUInt<5>(Imm); 97}]> { 98 let ParserMatchClass = UImmLog2XLenAsmOperand; 99 // TODO: should ensure invalid shamt is rejected when decoding. 100 let DecoderMethod = "decodeUImmOperand<6>"; 101 let MCOperandPredicate = [{ 102 int64_t Imm; 103 if (!MCOp.evaluateAsConstantImm(Imm)) 104 return false; 105 if (STI.getTargetTriple().isArch64Bit()) 106 return isUInt<6>(Imm); 107 return isUInt<5>(Imm); 108 }]; 109} 110 111def uimm5 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> { 112 let ParserMatchClass = UImmAsmOperand<5>; 113 let DecoderMethod = "decodeUImmOperand<5>"; 114} 115 116def simm12 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isInt<12>(Imm);}]> { 117 let ParserMatchClass = SImmAsmOperand<12>; 118 let EncoderMethod = "getImmOpValue"; 119 let DecoderMethod = "decodeSImmOperand<12>"; 120 let MCOperandPredicate = [{ 121 int64_t Imm; 122 if (MCOp.evaluateAsConstantImm(Imm)) 123 return isInt<12>(Imm); 124 return MCOp.isBareSymbolRef(); 125 }]; 126} 127 128def uimm12 : Operand<XLenVT> { 129 let ParserMatchClass = UImmAsmOperand<12>; 130 let DecoderMethod = "decodeUImmOperand<12>"; 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 146def uimm20 : Operand<XLenVT> { 147 let ParserMatchClass = UImmAsmOperand<20>; 148 let EncoderMethod = "getImmOpValue"; 149 let DecoderMethod = "decodeUImmOperand<20>"; 150 let MCOperandPredicate = [{ 151 int64_t Imm; 152 if (MCOp.evaluateAsConstantImm(Imm)) 153 return isUInt<20>(Imm); 154 return MCOp.isBareSymbolRef(); 155 }]; 156} 157 158// A 21-bit signed immediate where the least significant bit is zero. 159def simm21_lsb0 : Operand<OtherVT> { 160 let ParserMatchClass = SImmAsmOperand<21, "Lsb0">; 161 let EncoderMethod = "getImmOpValueAsr1"; 162 let DecoderMethod = "decodeSImmOperandAndLsl1<21>"; 163 let MCOperandPredicate = [{ 164 int64_t Imm; 165 if (MCOp.evaluateAsConstantImm(Imm)) 166 return isShiftedInt<20, 1>(Imm); 167 return MCOp.isBareSymbolRef(); 168 }]; 169} 170 171def BareSymbol : AsmOperandClass { 172 let Name = "BareSymbol"; 173 let RenderMethod = "addImmOperands"; 174 let DiagnosticType = "InvalidBareSymbol"; 175} 176 177// A bare symbol. 178def bare_symbol : Operand<XLenVT> { 179 let ParserMatchClass = BareSymbol; 180 let MCOperandPredicate = [{ 181 return MCOp.isBareSymbolRef(); 182 }]; 183} 184 185// A parameterized register class alternative to i32imm/i64imm from Target.td. 186def ixlenimm : Operand<XLenVT> { 187 let ParserMatchClass = ImmXLenAsmOperand<"">; 188} 189 190// Standalone (codegen-only) immleaf patterns. 191def simm32 : ImmLeaf<XLenVT, [{return isInt<32>(Imm);}]>; 192def simm32hi20 : ImmLeaf<XLenVT, [{return isShiftedInt<20, 12>(Imm);}]>; 193 194// Addressing modes. 195// Necessary because a frameindex can't be matched directly in a pattern. 196def AddrFI : ComplexPattern<iPTR, 1, "SelectAddrFI", [frameindex], []>; 197 198// Extract least significant 12 bits from an immediate value and sign extend 199// them. 200def LO12Sext : SDNodeXForm<imm, [{ 201 return CurDAG->getTargetConstant(SignExtend64<12>(N->getZExtValue()), 202 SDLoc(N), N->getValueType(0)); 203}]>; 204 205// Extract the most significant 20 bits from an immediate value. Add 1 if bit 206// 11 is 1, to compensate for the low 12 bits in the matching immediate addi 207// or ld/st being negative. 208def HI20 : SDNodeXForm<imm, [{ 209 return CurDAG->getTargetConstant(((N->getZExtValue()+0x800) >> 12) & 0xfffff, 210 SDLoc(N), N->getValueType(0)); 211}]>; 212 213//===----------------------------------------------------------------------===// 214// Instruction Class Templates 215//===----------------------------------------------------------------------===// 216 217let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 218class BranchCC_rri<bits<3> funct3, string opcodestr> 219 : RVInstB<funct3, OPC_BRANCH, (outs), 220 (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12), 221 opcodestr, "$rs1, $rs2, $imm12"> { 222 let isBranch = 1; 223 let isTerminator = 1; 224} 225 226let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in 227class Load_ri<bits<3> funct3, string opcodestr> 228 : RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), 229 opcodestr, "$rd, ${imm12}(${rs1})">; 230 231// Operands for stores are in the order srcreg, base, offset rather than 232// reflecting the order these fields are specified in the instruction 233// encoding. 234let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in 235class Store_rri<bits<3> funct3, string opcodestr> 236 : RVInstS<funct3, OPC_STORE, (outs), 237 (ins GPR:$rs2, GPR:$rs1, simm12:$imm12), 238 opcodestr, "$rs2, ${imm12}(${rs1})">; 239 240let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 241class ALU_ri<bits<3> funct3, string opcodestr> 242 : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), 243 opcodestr, "$rd, $rs1, $imm12">; 244 245let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 246class Shift_ri<bit arithshift, bits<3> funct3, string opcodestr> 247 : RVInstIShift<arithshift, funct3, OPC_OP_IMM, (outs GPR:$rd), 248 (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr, 249 "$rd, $rs1, $shamt">; 250 251let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 252class ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr> 253 : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), 254 opcodestr, "$rd, $rs1, $rs2">; 255 256let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 257class CSR_ir<bits<3> funct3, string opcodestr> 258 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins uimm12:$imm12, GPR:$rs1), 259 opcodestr, "$rd, $imm12, $rs1">; 260 261let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 262class CSR_ii<bits<3> funct3, string opcodestr> 263 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), 264 (ins uimm12:$imm12, uimm5:$rs1), 265 opcodestr, "$rd, $imm12, $rs1">; 266 267let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 268class ShiftW_ri<bit arithshift, bits<3> funct3, string opcodestr> 269 : RVInstIShiftW<arithshift, funct3, OPC_OP_IMM_32, (outs GPR:$rd), 270 (ins GPR:$rs1, uimm5:$shamt), opcodestr, 271 "$rd, $rs1, $shamt">; 272 273let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 274class ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr> 275 : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd), 276 (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2">; 277 278let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 279class Priv<string opcodestr, bits<7> funct7> 280 : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2), 281 opcodestr, "">; 282 283//===----------------------------------------------------------------------===// 284// Instructions 285//===----------------------------------------------------------------------===// 286 287let hasSideEffects = 0, isReMaterializable = 1, mayLoad = 0, mayStore = 0 in { 288def LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20:$imm20), 289 "lui", "$rd, $imm20">; 290 291def AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20:$imm20), 292 "auipc", "$rd, $imm20">; 293 294let isCall = 1 in 295def JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0:$imm20), 296 "jal", "$rd, $imm20">; 297 298let isCall = 1 in 299def JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd), 300 (ins GPR:$rs1, simm12:$imm12), 301 "jalr", "$rd, $rs1, $imm12">; 302} // hasSideEffects = 0, mayLoad = 0, mayStore = 0 303 304def BEQ : BranchCC_rri<0b000, "beq">; 305def BNE : BranchCC_rri<0b001, "bne">; 306def BLT : BranchCC_rri<0b100, "blt">; 307def BGE : BranchCC_rri<0b101, "bge">; 308def BLTU : BranchCC_rri<0b110, "bltu">; 309def BGEU : BranchCC_rri<0b111, "bgeu">; 310 311def LB : Load_ri<0b000, "lb">; 312def LH : Load_ri<0b001, "lh">; 313def LW : Load_ri<0b010, "lw">; 314def LBU : Load_ri<0b100, "lbu">; 315def LHU : Load_ri<0b101, "lhu">; 316 317def SB : Store_rri<0b000, "sb">; 318def SH : Store_rri<0b001, "sh">; 319def SW : Store_rri<0b010, "sw">; 320 321// ADDI isn't always rematerializable, but isReMaterializable will be used as 322// a hint which is verified in isReallyTriviallyReMaterializable. 323let isReMaterializable = 1 in 324def ADDI : ALU_ri<0b000, "addi">; 325 326def SLTI : ALU_ri<0b010, "slti">; 327def SLTIU : ALU_ri<0b011, "sltiu">; 328def XORI : ALU_ri<0b100, "xori">; 329def ORI : ALU_ri<0b110, "ori">; 330def ANDI : ALU_ri<0b111, "andi">; 331 332def SLLI : Shift_ri<0, 0b001, "slli">; 333def SRLI : Shift_ri<0, 0b101, "srli">; 334def SRAI : Shift_ri<1, 0b101, "srai">; 335 336def ADD : ALU_rr<0b0000000, 0b000, "add">; 337def SUB : ALU_rr<0b0100000, 0b000, "sub">; 338def SLL : ALU_rr<0b0000000, 0b001, "sll">; 339def SLT : ALU_rr<0b0000000, 0b010, "slt">; 340def SLTU : ALU_rr<0b0000000, 0b011, "sltu">; 341def XOR : ALU_rr<0b0000000, 0b100, "xor">; 342def SRL : ALU_rr<0b0000000, 0b101, "srl">; 343def SRA : ALU_rr<0b0100000, 0b101, "sra">; 344def OR : ALU_rr<0b0000000, 0b110, "or">; 345def AND : ALU_rr<0b0000000, 0b111, "and">; 346 347let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { 348def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs), 349 (ins fencearg:$pred, fencearg:$succ), 350 "fence", "$pred, $succ"> { 351 bits<4> pred; 352 bits<4> succ; 353 354 let rs1 = 0; 355 let rd = 0; 356 let imm12 = {0b0000,pred,succ}; 357} 358 359def FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", ""> { 360 let rs1 = 0; 361 let rd = 0; 362 let imm12 = {0b1000,0b0011,0b0011}; 363} 364 365def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", ""> { 366 let rs1 = 0; 367 let rd = 0; 368 let imm12 = 0; 369} 370 371def ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", ""> { 372 let rs1 = 0; 373 let rd = 0; 374 let imm12 = 0; 375} 376 377def EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", ""> { 378 let rs1 = 0; 379 let rd = 0; 380 let imm12 = 1; 381} 382} // hasSideEffects = 1, mayLoad = 0, mayStore = 0 383 384def CSRRW : CSR_ir<0b001, "csrrw">; 385def CSRRS : CSR_ir<0b010, "csrrs">; 386def CSRRC : CSR_ir<0b011, "csrrc">; 387 388def CSRRWI : CSR_ii<0b101, "csrrwi">; 389def CSRRSI : CSR_ii<0b110, "csrrsi">; 390def CSRRCI : CSR_ii<0b111, "csrrci">; 391 392/// RV64I instructions 393 394let Predicates = [IsRV64] in { 395def LWU : Load_ri<0b110, "lwu">; 396def LD : Load_ri<0b011, "ld">; 397def SD : Store_rri<0b011, "sd">; 398 399let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 400def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd), 401 (ins GPR:$rs1, simm12:$imm12), 402 "addiw", "$rd, $rs1, $imm12">; 403 404def SLLIW : ShiftW_ri<0, 0b001, "slliw">; 405def SRLIW : ShiftW_ri<0, 0b101, "srliw">; 406def SRAIW : ShiftW_ri<1, 0b101, "sraiw">; 407 408def ADDW : ALUW_rr<0b0000000, 0b000, "addw">; 409def SUBW : ALUW_rr<0b0100000, 0b000, "subw">; 410def SLLW : ALUW_rr<0b0000000, 0b001, "sllw">; 411def SRLW : ALUW_rr<0b0000000, 0b101, "srlw">; 412def SRAW : ALUW_rr<0b0100000, 0b101, "sraw">; 413} // Predicates = [IsRV64] 414 415//===----------------------------------------------------------------------===// 416// Privileged instructions 417//===----------------------------------------------------------------------===// 418 419let isBarrier = 1, isReturn = 1, isTerminator = 1 in { 420def URET : Priv<"uret", 0b0000000> { 421 let rd = 0; 422 let rs1 = 0; 423 let rs2 = 0b00010; 424} 425 426def SRET : Priv<"sret", 0b0001000> { 427 let rd = 0; 428 let rs1 = 0; 429 let rs2 = 0b00010; 430} 431 432def MRET : Priv<"mret", 0b0011000> { 433 let rd = 0; 434 let rs1 = 0; 435 let rs2 = 0b00010; 436} 437} // isBarrier = 1, isReturn = 1, isTerminator = 1 438 439def WFI : Priv<"wfi", 0b0001000> { 440 let rd = 0; 441 let rs1 = 0; 442 let rs2 = 0b00101; 443} 444 445let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 446def SFENCE_VMA : RVInstR<0b0001001, 0b000, OPC_SYSTEM, (outs), 447 (ins GPR:$rs1, GPR:$rs2), 448 "sfence.vma", "$rs1, $rs2"> { 449 let rd = 0; 450} 451 452//===----------------------------------------------------------------------===// 453// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) 454//===----------------------------------------------------------------------===// 455 456// TODO la 457// TODO lb lh lw 458// TODO RV64I: ld 459// TODO sb sh sw 460// TODO RV64I: sd 461 462def : InstAlias<"nop", (ADDI X0, X0, 0)>; 463 464// Note that the size is 32 because up to 8 32-bit instructions are needed to 465// generate an arbitrary 64-bit immediate. However, the size does not really 466// matter since PseudoLI is currently only used in the AsmParser where it gets 467// expanded to real instructions immediately. 468let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32, 469 isCodeGenOnly = 0, isAsmParserOnly = 1 in 470def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm:$imm), [], 471 "li", "$rd, $imm">; 472 473def : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>; 474def : InstAlias<"not $rd, $rs", (XORI GPR:$rd, GPR:$rs, -1)>; 475def : InstAlias<"neg $rd, $rs", (SUB GPR:$rd, X0, GPR:$rs)>; 476 477let Predicates = [IsRV64] in { 478def : InstAlias<"negw $rd, $rs", (SUBW GPR:$rd, X0, GPR:$rs)>; 479def : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs, 0)>; 480} // Predicates = [IsRV64] 481 482def : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs, 1)>; 483def : InstAlias<"snez $rd, $rs", (SLTU GPR:$rd, X0, GPR:$rs)>; 484def : InstAlias<"sltz $rd, $rs", (SLT GPR:$rd, GPR:$rs, X0)>; 485def : InstAlias<"sgtz $rd, $rs", (SLT GPR:$rd, X0, GPR:$rs)>; 486 487// sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu 488// form will always be printed. Therefore, set a zero weight. 489def : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>; 490def : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>; 491 492def : InstAlias<"beqz $rs, $offset", 493 (BEQ GPR:$rs, X0, simm13_lsb0:$offset)>; 494def : InstAlias<"bnez $rs, $offset", 495 (BNE GPR:$rs, X0, simm13_lsb0:$offset)>; 496def : InstAlias<"blez $rs, $offset", 497 (BGE X0, GPR:$rs, simm13_lsb0:$offset)>; 498def : InstAlias<"bgez $rs, $offset", 499 (BGE GPR:$rs, X0, simm13_lsb0:$offset)>; 500def : InstAlias<"bltz $rs, $offset", 501 (BLT GPR:$rs, X0, simm13_lsb0:$offset)>; 502def : InstAlias<"bgtz $rs, $offset", 503 (BLT X0, GPR:$rs, simm13_lsb0:$offset)>; 504 505// Always output the canonical mnemonic for the pseudo branch instructions. 506// The GNU tools emit the canonical mnemonic for the branch pseudo instructions 507// as well (e.g. "bgt" will be recognised by the assembler but never printed by 508// objdump). Match this behaviour by setting a zero weight. 509def : InstAlias<"bgt $rs, $rt, $offset", 510 (BLT GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 511def : InstAlias<"ble $rs, $rt, $offset", 512 (BGE GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 513def : InstAlias<"bgtu $rs, $rt, $offset", 514 (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 515def : InstAlias<"bleu $rs, $rt, $offset", 516 (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 517 518// "ret" has more weight since "ret" and "jr" alias the same "jalr" instruction. 519def : InstAlias<"j $offset", (JAL X0, simm21_lsb0:$offset)>; 520def : InstAlias<"jal $offset", (JAL X1, simm21_lsb0:$offset)>; 521def : InstAlias<"jr $rs", (JALR X0, GPR:$rs, 0)>; 522def : InstAlias<"jalr $rs", (JALR X1, GPR:$rs, 0)>; 523def : InstAlias<"ret", (JALR X0, X1, 0), 2>; 524// TODO call 525// TODO tail 526 527def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw 528 529// CSR Addresses: 0xC00 == cycle, 0xC01 == time, 0xC02 == instret 530// 0xC80 == cycleh, 0xC81 == timeh, 0xC82 == instreth 531def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, 0xC02, X0)>; 532def : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, 0xC00, X0)>; 533def : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, 0xC01, X0)>; 534 535let Predicates = [IsRV32] in { 536def : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, 0xC82, X0)>; 537def : InstAlias<"rdcycleh $rd", (CSRRS GPR:$rd, 0xC80, X0)>; 538def : InstAlias<"rdtimeh $rd", (CSRRS GPR:$rd, 0xC81, X0)>; 539} // Predicates = [IsRV32] 540 541def : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, uimm12:$csr, X0)>; 542def : InstAlias<"csrw $csr, $rs", (CSRRW X0, uimm12:$csr, GPR:$rs)>; 543def : InstAlias<"csrs $csr, $rs", (CSRRS X0, uimm12:$csr, GPR:$rs)>; 544def : InstAlias<"csrc $csr, $rs", (CSRRC X0, uimm12:$csr, GPR:$rs)>; 545 546def : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, uimm12:$csr, uimm5:$imm)>; 547def : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, uimm12:$csr, uimm5:$imm)>; 548def : InstAlias<"csrci $csr, $imm", (CSRRCI X0, uimm12:$csr, uimm5:$imm)>; 549 550def : InstAlias<"sfence.vma", (SFENCE_VMA X0, X0)>; 551def : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>; 552 553//===----------------------------------------------------------------------===// 554// Pseudo-instructions and codegen patterns 555// 556// Naming convention: For 'generic' pattern classes, we use the naming 557// convention PatTy1Ty2. For pattern classes which offer a more complex 558// expension, prefix the class name, e.g. BccPat. 559//===----------------------------------------------------------------------===// 560 561/// Generic pattern classes 562 563class PatGprGpr<SDPatternOperator OpNode, RVInstR Inst> 564 : Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>; 565class PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst> 566 : Pat<(OpNode GPR:$rs1, simm12:$imm12), (Inst GPR:$rs1, simm12:$imm12)>; 567class PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst> 568 : Pat<(OpNode GPR:$rs1, uimmlog2xlen:$shamt), 569 (Inst GPR:$rs1, uimmlog2xlen:$shamt)>; 570 571/// Predicates 572 573def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{ 574 return isOrEquivalentToAdd(N); 575}]>; 576 577/// Immediates 578 579def : Pat<(simm12:$imm), (ADDI X0, simm12:$imm)>; 580def : Pat<(simm32hi20:$imm), (LUI (HI20 imm:$imm))>; 581def : Pat<(simm32:$imm), (ADDI (LUI (HI20 imm:$imm)), (LO12Sext imm:$imm))>; 582 583/// Simple arithmetic operations 584 585def : PatGprGpr<add, ADD>; 586def : PatGprSimm12<add, ADDI>; 587def : PatGprGpr<sub, SUB>; 588def : PatGprGpr<or, OR>; 589def : PatGprSimm12<or, ORI>; 590def : PatGprGpr<and, AND>; 591def : PatGprSimm12<and, ANDI>; 592def : PatGprGpr<xor, XOR>; 593def : PatGprSimm12<xor, XORI>; 594def : PatGprGpr<shl, SLL>; 595def : PatGprUimmLog2XLen<shl, SLLI>; 596def : PatGprGpr<srl, SRL>; 597def : PatGprUimmLog2XLen<srl, SRLI>; 598def : PatGprGpr<sra, SRA>; 599def : PatGprUimmLog2XLen<sra, SRAI>; 600 601/// FrameIndex calculations 602 603def : Pat<(add (i32 AddrFI:$Rs), simm12:$imm12), 604 (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>; 605def : Pat<(IsOrAdd (i32 AddrFI:$Rs), simm12:$imm12), 606 (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>; 607 608/// Setcc 609 610def : PatGprGpr<setlt, SLT>; 611def : PatGprSimm12<setlt, SLTI>; 612def : PatGprGpr<setult, SLTU>; 613def : PatGprSimm12<setult, SLTIU>; 614 615// Define pattern expansions for setcc operations that aren't directly 616// handled by a RISC-V instruction. 617def : Pat<(seteq GPR:$rs1, GPR:$rs2), (SLTIU (XOR GPR:$rs1, GPR:$rs2), 1)>; 618def : Pat<(setne GPR:$rs1, GPR:$rs2), (SLTU X0, (XOR GPR:$rs1, GPR:$rs2))>; 619def : Pat<(setugt GPR:$rs1, GPR:$rs2), (SLTU GPR:$rs2, GPR:$rs1)>; 620def : Pat<(setuge GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs1, GPR:$rs2), 1)>; 621def : Pat<(setule GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs2, GPR:$rs1), 1)>; 622def : Pat<(setgt GPR:$rs1, GPR:$rs2), (SLT GPR:$rs2, GPR:$rs1)>; 623def : Pat<(setge GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs1, GPR:$rs2), 1)>; 624def : Pat<(setle GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs2, GPR:$rs1), 1)>; 625 626let usesCustomInserter = 1 in 627class SelectCC_rrirr<RegisterClass valty, RegisterClass cmpty> 628 : Pseudo<(outs valty:$dst), 629 (ins cmpty:$lhs, cmpty:$rhs, ixlenimm:$imm, 630 valty:$truev, valty:$falsev), 631 [(set valty:$dst, (SelectCC cmpty:$lhs, cmpty:$rhs, 632 (XLenVT imm:$imm), valty:$truev, valty:$falsev))]>; 633 634def Select_GPR_Using_CC_GPR : SelectCC_rrirr<GPR, GPR>; 635 636/// Branches and jumps 637 638// Match `(brcond (CondOp ..), ..)` and lower to the appropriate RISC-V branch 639// instruction. 640class BccPat<PatFrag CondOp, RVInstB Inst> 641 : Pat<(brcond (i32 (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12), 642 (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>; 643 644def : BccPat<seteq, BEQ>; 645def : BccPat<setne, BNE>; 646def : BccPat<setlt, BLT>; 647def : BccPat<setge, BGE>; 648def : BccPat<setult, BLTU>; 649def : BccPat<setuge, BGEU>; 650 651class BccSwapPat<PatFrag CondOp, RVInst InstBcc> 652 : Pat<(brcond (i32 (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12), 653 (InstBcc GPR:$rs2, GPR:$rs1, bb:$imm12)>; 654 655// Condition codes that don't have matching RISC-V branch instructions, but 656// are trivially supported by swapping the two input operands 657def : BccSwapPat<setgt, BLT>; 658def : BccSwapPat<setle, BGE>; 659def : BccSwapPat<setugt, BLTU>; 660def : BccSwapPat<setule, BGEU>; 661 662// An extra pattern is needed for a brcond without a setcc (i.e. where the 663// condition was calculated elsewhere). 664def : Pat<(brcond GPR:$cond, bb:$imm12), (BNE GPR:$cond, X0, bb:$imm12)>; 665 666let isBarrier = 1, isBranch = 1, isTerminator = 1 in 667def PseudoBR : Pseudo<(outs), (ins simm21_lsb0:$imm20), [(br bb:$imm20)]>, 668 PseudoInstExpansion<(JAL X0, simm21_lsb0:$imm20)>; 669 670let isCall = 1, Defs=[X1] in 671let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in 672def PseudoBRIND : Pseudo<(outs), (ins GPR:$rs1, simm12:$imm12), []>, 673 PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; 674 675def : Pat<(brind GPR:$rs1), (PseudoBRIND GPR:$rs1, 0)>; 676def : Pat<(brind (add GPR:$rs1, simm12:$imm12)), 677 (PseudoBRIND GPR:$rs1, simm12:$imm12)>; 678 679// PseudoCALL is a pseudo instruction which will eventually expand to auipc 680// and jalr while encoding. This is desirable, as an auipc+jalr pair with 681// R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker 682// if the offset fits in a signed 21-bit immediate. 683// Define AsmString to print "call" when compile with -S flag. 684// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 685let isCall = 1, Defs = [X1], isCodeGenOnly = 0 in 686def PseudoCALL : Pseudo<(outs), (ins bare_symbol:$func), 687 [(Call tglobaladdr:$func)]> { 688 let AsmString = "call\t$func"; 689} 690 691def : Pat<(Call texternalsym:$func), (PseudoCALL texternalsym:$func)>; 692 693def : Pat<(URetFlag), (URET X0, X0)>; 694def : Pat<(SRetFlag), (SRET X0, X0)>; 695def : Pat<(MRetFlag), (MRET X0, X0)>; 696 697let isCall = 1, Defs = [X1] in 698def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rs1), [(Call GPR:$rs1)]>, 699 PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>; 700 701let isBarrier = 1, isReturn = 1, isTerminator = 1 in 702def PseudoRET : Pseudo<(outs), (ins), [(RetFlag)]>, 703 PseudoInstExpansion<(JALR X0, X1, 0)>; 704 705// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually 706// expand to auipc and jalr while encoding. 707// Define AsmString to print "tail" when compile with -S flag. 708let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2], 709 isCodeGenOnly = 0 in 710def PseudoTAIL : Pseudo<(outs), (ins bare_symbol:$dst), []> { 711 let AsmString = "tail\t$dst"; 712} 713 714let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in 715def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1), [(Tail GPRTC:$rs1)]>, 716 PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>; 717 718def : Pat<(Tail (iPTR tglobaladdr:$dst)), 719 (PseudoTAIL texternalsym:$dst)>; 720def : Pat<(Tail (iPTR texternalsym:$dst)), 721 (PseudoTAIL texternalsym:$dst)>; 722 723/// Loads 724 725multiclass LdPat<PatFrag LoadOp, RVInst Inst> { 726 def : Pat<(LoadOp GPR:$rs1), (Inst GPR:$rs1, 0)>; 727 def : Pat<(LoadOp AddrFI:$rs1), (Inst AddrFI:$rs1, 0)>; 728 def : Pat<(LoadOp (add GPR:$rs1, simm12:$imm12)), 729 (Inst GPR:$rs1, simm12:$imm12)>; 730 def : Pat<(LoadOp (add AddrFI:$rs1, simm12:$imm12)), 731 (Inst AddrFI:$rs1, simm12:$imm12)>; 732 def : Pat<(LoadOp (IsOrAdd AddrFI:$rs1, simm12:$imm12)), 733 (Inst AddrFI:$rs1, simm12:$imm12)>; 734} 735 736defm : LdPat<sextloadi8, LB>; 737defm : LdPat<extloadi8, LB>; 738defm : LdPat<sextloadi16, LH>; 739defm : LdPat<extloadi16, LH>; 740defm : LdPat<load, LW>; 741defm : LdPat<zextloadi8, LBU>; 742defm : LdPat<zextloadi16, LHU>; 743 744/// Stores 745 746multiclass StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy> { 747 def : Pat<(StoreOp StTy:$rs2, GPR:$rs1), (Inst StTy:$rs2, GPR:$rs1, 0)>; 748 def : Pat<(StoreOp StTy:$rs2, AddrFI:$rs1), (Inst StTy:$rs2, AddrFI:$rs1, 0)>; 749 def : Pat<(StoreOp StTy:$rs2, (add GPR:$rs1, simm12:$imm12)), 750 (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>; 751 def : Pat<(StoreOp StTy:$rs2, (add AddrFI:$rs1, simm12:$imm12)), 752 (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>; 753 def : Pat<(StoreOp StTy:$rs2, (IsOrAdd AddrFI:$rs1, simm12:$imm12)), 754 (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>; 755} 756 757defm : StPat<truncstorei8, SB, GPR>; 758defm : StPat<truncstorei16, SH, GPR>; 759defm : StPat<store, SW, GPR>; 760 761/// Fences 762 763// Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set 764// Manual: Volume I. 765 766// fence acquire -> fence r, rw 767def : Pat<(atomic_fence (i32 4), (imm)), (FENCE 0b10, 0b11)>; 768// fence release -> fence rw, w 769def : Pat<(atomic_fence (i32 5), (imm)), (FENCE 0b11, 0b1)>; 770// fence acq_rel -> fence.tso 771def : Pat<(atomic_fence (i32 6), (imm)), (FENCE_TSO)>; 772// fence seq_cst -> fence rw, rw 773def : Pat<(atomic_fence (i32 7), (imm)), (FENCE 0b11, 0b11)>; 774 775// Lowering for atomic load and store is defined in RISCVInstrInfoA.td. 776// Although these are lowered to fence+load/store instructions defined in the 777// base RV32I/RV64I ISA, this lowering is only used when the A extension is 778// present. This is necessary as it isn't valid to mix __atomic_* libcalls 779// with inline atomic operations for the same object. 780 781/// Other pseudo-instructions 782 783// Pessimistically assume the stack pointer will be clobbered 784let Defs = [X2], Uses = [X2] in { 785def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 786 [(CallSeqStart timm:$amt1, timm:$amt2)]>; 787def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 788 [(CallSeqEnd timm:$amt1, timm:$amt2)]>; 789} // Defs = [X2], Uses = [X2] 790 791//===----------------------------------------------------------------------===// 792// Standard extensions 793//===----------------------------------------------------------------------===// 794 795include "RISCVInstrInfoM.td" 796include "RISCVInstrInfoA.td" 797include "RISCVInstrInfoF.td" 798include "RISCVInstrInfoD.td" 799include "RISCVInstrInfoC.td" 800