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