106c3fb27SDimitry Andric//===-- RISCVInstrInfo.td - Target Description for RISC-V --*- tablegen -*-===// 20b57cec5SDimitry Andric// 30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric// 70b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric// 90b57cec5SDimitry Andric// This file describes the RISC-V instructions in TableGen format. 100b57cec5SDimitry Andric// 110b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric// RISC-V specific DAG Nodes. 150b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric// Target-independent type requirements, but with target-specific formats. 180b57cec5SDimitry Andricdef SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, 190b57cec5SDimitry Andric SDTCisVT<1, i32>]>; 200b57cec5SDimitry Andricdef SDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, 210b57cec5SDimitry Andric SDTCisVT<1, i32>]>; 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric// Target-dependent type requirements. 240b57cec5SDimitry Andricdef SDT_RISCVCall : SDTypeProfile<0, -1, [SDTCisVT<0, XLenVT>]>; 250b57cec5SDimitry Andricdef SDT_RISCVSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>, 26349cc55cSDimitry Andric SDTCisVT<3, OtherVT>, 270b57cec5SDimitry Andric SDTCisSameAs<0, 4>, 280b57cec5SDimitry Andric SDTCisSameAs<4, 5>]>; 29fe6060f1SDimitry Andricdef SDT_RISCVBrCC : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>, 30fe6060f1SDimitry Andric SDTCisVT<2, OtherVT>, 31fe6060f1SDimitry Andric SDTCisVT<3, OtherVT>]>; 32fe6060f1SDimitry Andricdef SDT_RISCVReadCSR : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisInt<1>]>; 33fe6060f1SDimitry Andricdef SDT_RISCVWriteCSR : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisInt<1>]>; 34fe6060f1SDimitry Andricdef SDT_RISCVSwapCSR : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisInt<1>, 35fe6060f1SDimitry Andric SDTCisInt<2>]>; 36e8d8bef9SDimitry Andricdef SDT_RISCVReadCycleWide : SDTypeProfile<2, 0, [SDTCisVT<0, i32>, 37e8d8bef9SDimitry Andric SDTCisVT<1, i32>]>; 38fe6060f1SDimitry Andricdef SDT_RISCVIntUnaryOpW : SDTypeProfile<1, 1, [ 39fe6060f1SDimitry Andric SDTCisSameAs<0, 1>, SDTCisVT<0, i64> 40fe6060f1SDimitry Andric]>; 41fe6060f1SDimitry Andricdef SDT_RISCVIntBinOpW : SDTypeProfile<1, 2, [ 42fe6060f1SDimitry Andric SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64> 43fe6060f1SDimitry Andric]>; 44fe6060f1SDimitry Andricdef SDT_RISCVIntShiftDOpW : SDTypeProfile<1, 3, [ 45fe6060f1SDimitry Andric SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64>, SDTCisVT<3, i64> 46fe6060f1SDimitry Andric]>; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric// Target-independent nodes, but with target-specific formats. 490b57cec5SDimitry Andricdef callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart, 500b57cec5SDimitry Andric [SDNPHasChain, SDNPOutGlue]>; 510b57cec5SDimitry Andricdef callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd, 520b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric// Target-dependent nodes. 550b57cec5SDimitry Andricdef riscv_call : SDNode<"RISCVISD::CALL", SDT_RISCVCall, 560b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 570b57cec5SDimitry Andric SDNPVariadic]>; 5806c3fb27SDimitry Andricdef riscv_ret_glue : SDNode<"RISCVISD::RET_GLUE", SDTNone, 590b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; 6006c3fb27SDimitry Andricdef riscv_sret_glue : SDNode<"RISCVISD::SRET_GLUE", SDTNone, 610b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue]>; 6206c3fb27SDimitry Andricdef riscv_mret_glue : SDNode<"RISCVISD::MRET_GLUE", SDTNone, 630b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue]>; 64e8d8bef9SDimitry Andricdef riscv_selectcc : SDNode<"RISCVISD::SELECT_CC", SDT_RISCVSelectCC>; 65fe6060f1SDimitry Andricdef riscv_brcc : SDNode<"RISCVISD::BR_CC", SDT_RISCVBrCC, 66fe6060f1SDimitry Andric [SDNPHasChain]>; 670b57cec5SDimitry Andricdef riscv_tail : SDNode<"RISCVISD::TAIL", SDT_RISCVCall, 680b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 690b57cec5SDimitry Andric SDNPVariadic]>; 70fe6060f1SDimitry Andricdef riscv_sllw : SDNode<"RISCVISD::SLLW", SDT_RISCVIntBinOpW>; 71fe6060f1SDimitry Andricdef riscv_sraw : SDNode<"RISCVISD::SRAW", SDT_RISCVIntBinOpW>; 72fe6060f1SDimitry Andricdef riscv_srlw : SDNode<"RISCVISD::SRLW", SDT_RISCVIntBinOpW>; 73fe6060f1SDimitry Andricdef riscv_read_csr : SDNode<"RISCVISD::READ_CSR", SDT_RISCVReadCSR, 74fe6060f1SDimitry Andric [SDNPHasChain]>; 75fe6060f1SDimitry Andricdef riscv_write_csr : SDNode<"RISCVISD::WRITE_CSR", SDT_RISCVWriteCSR, 76fe6060f1SDimitry Andric [SDNPHasChain]>; 77fe6060f1SDimitry Andricdef riscv_swap_csr : SDNode<"RISCVISD::SWAP_CSR", SDT_RISCVSwapCSR, 78fe6060f1SDimitry Andric [SDNPHasChain]>; 790b57cec5SDimitry Andric 80e8d8bef9SDimitry Andricdef riscv_read_cycle_wide : SDNode<"RISCVISD::READ_CYCLE_WIDE", 81e8d8bef9SDimitry Andric SDT_RISCVReadCycleWide, 82e8d8bef9SDimitry Andric [SDNPHasChain, SDNPSideEffect]>; 83e8d8bef9SDimitry Andric 8481ad6265SDimitry Andricdef riscv_add_lo : SDNode<"RISCVISD::ADD_LO", SDTIntBinOp>; 8581ad6265SDimitry Andricdef riscv_hi : SDNode<"RISCVISD::HI", SDTIntUnaryOp>; 8681ad6265SDimitry Andricdef riscv_lla : SDNode<"RISCVISD::LLA", SDTIntUnaryOp>; 8781ad6265SDimitry Andricdef riscv_add_tprel : SDNode<"RISCVISD::ADD_TPREL", 8881ad6265SDimitry Andric SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, 8981ad6265SDimitry Andric SDTCisSameAs<0, 2>, 9081ad6265SDimitry Andric SDTCisSameAs<0, 3>, 9181ad6265SDimitry Andric SDTCisInt<0>]>>; 9281ad6265SDimitry Andric 930b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 940b57cec5SDimitry Andric// Operand and SDNode transformation definitions. 950b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 960b57cec5SDimitry Andric 970b57cec5SDimitry Andricclass ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass { 980b57cec5SDimitry Andric let Name = prefix # "ImmXLen" # suffix; 990b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 1000b57cec5SDimitry Andric let DiagnosticType = !strconcat("Invalid", Name); 1010b57cec5SDimitry Andric} 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andricclass ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass { 1040b57cec5SDimitry Andric let Name = prefix # "Imm" # width # suffix; 1050b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 1060b57cec5SDimitry Andric let DiagnosticType = !strconcat("Invalid", Name); 1070b57cec5SDimitry Andric} 1080b57cec5SDimitry Andric 1098bcb0991SDimitry Andricdef ImmZeroAsmOperand : AsmOperandClass { 1108bcb0991SDimitry Andric let Name = "ImmZero"; 1118bcb0991SDimitry Andric let RenderMethod = "addImmOperands"; 1128bcb0991SDimitry Andric let DiagnosticType = !strconcat("Invalid", Name); 1138bcb0991SDimitry Andric} 1148bcb0991SDimitry Andric 11581ad6265SDimitry Andric// A parse method for (${gpr}) or 0(${gpr}), where the 0 is be silently ignored. 11681ad6265SDimitry Andricdef ZeroOffsetMemOpOperand : AsmOperandClass { 11781ad6265SDimitry Andric let Name = "ZeroOffsetMemOpOperand"; 11881ad6265SDimitry Andric let RenderMethod = "addRegOperands"; 11981ad6265SDimitry Andric let PredicateMethod = "isGPR"; 12081ad6265SDimitry Andric let ParserMethod = "parseZeroOffsetMemOp"; 12181ad6265SDimitry Andric} 12281ad6265SDimitry Andric 123bdd1243dSDimitry Andricclass MemOperand<RegisterClass regClass> : RegisterOperand<regClass>{ 124bdd1243dSDimitry Andric let OperandType = "OPERAND_MEMORY"; 125bdd1243dSDimitry Andric} 126bdd1243dSDimitry Andric 127bdd1243dSDimitry Andricdef GPRMemZeroOffset : MemOperand<GPR> { 12881ad6265SDimitry Andric let ParserMatchClass = ZeroOffsetMemOpOperand; 12981ad6265SDimitry Andric let PrintMethod = "printZeroOffsetMemOp"; 13081ad6265SDimitry Andric} 13181ad6265SDimitry Andric 132bdd1243dSDimitry Andricdef GPRMem : MemOperand<GPR>; 133bdd1243dSDimitry Andric 134bdd1243dSDimitry Andricdef SPMem : MemOperand<SP>; 135bdd1243dSDimitry Andric 136bdd1243dSDimitry Andricdef GPRCMem : MemOperand<GPRC>; 137bdd1243dSDimitry Andric 1380b57cec5SDimitry Andricclass SImmAsmOperand<int width, string suffix = ""> 1390b57cec5SDimitry Andric : ImmAsmOperand<"S", width, suffix> { 1400b57cec5SDimitry Andric} 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andricclass UImmAsmOperand<int width, string suffix = ""> 1430b57cec5SDimitry Andric : ImmAsmOperand<"U", width, suffix> { 1440b57cec5SDimitry Andric} 1450b57cec5SDimitry Andric 1465f757f3fSDimitry Andricclass RISCVOp<ValueType vt = XLenVT> : Operand<vt> { 1475f757f3fSDimitry Andric let OperandNamespace = "RISCVOp"; 1485f757f3fSDimitry Andric} 1495f757f3fSDimitry Andric 1505f757f3fSDimitry Andricclass RISCVUImmOp<int bitsNum> : RISCVOp { 1515f757f3fSDimitry Andric let ParserMatchClass = UImmAsmOperand<bitsNum>; 1525f757f3fSDimitry Andric let DecoderMethod = "decodeUImmOperand<" # bitsNum # ">"; 1535f757f3fSDimitry Andric let OperandType = "OPERAND_UIMM" # bitsNum; 1545f757f3fSDimitry Andric} 1555f757f3fSDimitry Andric 1565f757f3fSDimitry Andricclass RISCVUImmLeafOp<int bitsNum> : 1575f757f3fSDimitry Andric RISCVUImmOp<bitsNum>, ImmLeaf<XLenVT, "return isUInt<" # bitsNum # ">(Imm);">; 1585f757f3fSDimitry Andric 1595f757f3fSDimitry Andricclass RISCVSImmOp<int bitsNum> : RISCVOp { 1605f757f3fSDimitry Andric let ParserMatchClass = SImmAsmOperand<bitsNum>; 1615f757f3fSDimitry Andric let EncoderMethod = "getImmOpValue"; 1625f757f3fSDimitry Andric let DecoderMethod = "decodeSImmOperand<" # bitsNum # ">"; 1635f757f3fSDimitry Andric let OperandType = "OPERAND_SIMM" # bitsNum; 1645f757f3fSDimitry Andric} 1655f757f3fSDimitry Andric 1665f757f3fSDimitry Andricclass RISCVSImmLeafOp<int bitsNum> : 1675f757f3fSDimitry Andric RISCVSImmOp<bitsNum>, ImmLeaf<XLenVT, "return isInt<" # bitsNum # ">(Imm);">; 1685f757f3fSDimitry Andric 1690b57cec5SDimitry Andricdef FenceArg : AsmOperandClass { 1700b57cec5SDimitry Andric let Name = "FenceArg"; 1710b57cec5SDimitry Andric let RenderMethod = "addFenceArgOperands"; 17206c3fb27SDimitry Andric let ParserMethod = "parseFenceArg"; 1730b57cec5SDimitry Andric} 1740b57cec5SDimitry Andric 1755f757f3fSDimitry Andricdef fencearg : RISCVOp { 1760b57cec5SDimitry Andric let ParserMatchClass = FenceArg; 1770b57cec5SDimitry Andric let PrintMethod = "printFenceArg"; 1780b57cec5SDimitry Andric let DecoderMethod = "decodeUImmOperand<4>"; 1798bcb0991SDimitry Andric let OperandType = "OPERAND_UIMM4"; 1800b57cec5SDimitry Andric} 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andricdef UImmLog2XLenAsmOperand : AsmOperandClass { 1830b57cec5SDimitry Andric let Name = "UImmLog2XLen"; 1840b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 1850b57cec5SDimitry Andric let DiagnosticType = "InvalidUImmLog2XLen"; 1860b57cec5SDimitry Andric} 1870b57cec5SDimitry Andric 1885f757f3fSDimitry Andricdef uimmlog2xlen : RISCVOp, ImmLeaf<XLenVT, [{ 1890b57cec5SDimitry Andric if (Subtarget->is64Bit()) 1900b57cec5SDimitry Andric return isUInt<6>(Imm); 1910b57cec5SDimitry Andric return isUInt<5>(Imm); 1920b57cec5SDimitry Andric}]> { 1930b57cec5SDimitry Andric let ParserMatchClass = UImmLog2XLenAsmOperand; 1940b57cec5SDimitry Andric // TODO: should ensure invalid shamt is rejected when decoding. 1950b57cec5SDimitry Andric let DecoderMethod = "decodeUImmOperand<6>"; 1960b57cec5SDimitry Andric let MCOperandPredicate = [{ 1970b57cec5SDimitry Andric int64_t Imm; 1980b57cec5SDimitry Andric if (!MCOp.evaluateAsConstantImm(Imm)) 1990b57cec5SDimitry Andric return false; 2000b57cec5SDimitry Andric if (STI.getTargetTriple().isArch64Bit()) 2010b57cec5SDimitry Andric return isUInt<6>(Imm); 2020b57cec5SDimitry Andric return isUInt<5>(Imm); 2030b57cec5SDimitry Andric }]; 2048bcb0991SDimitry Andric let OperandType = "OPERAND_UIMMLOG2XLEN"; 2050b57cec5SDimitry Andric} 2060b57cec5SDimitry Andric 2070eae32dcSDimitry Andricdef InsnDirectiveOpcode : AsmOperandClass { 2080eae32dcSDimitry Andric let Name = "InsnDirectiveOpcode"; 2090eae32dcSDimitry Andric let ParserMethod = "parseInsnDirectiveOpcode"; 2100eae32dcSDimitry Andric let RenderMethod = "addImmOperands"; 2110eae32dcSDimitry Andric let PredicateMethod = "isImm"; 2120eae32dcSDimitry Andric} 2130eae32dcSDimitry Andric 2145f757f3fSDimitry Andricdef uimm1 : RISCVUImmLeafOp<1>; 2155f757f3fSDimitry Andricdef uimm2 : RISCVUImmLeafOp<2> { 2165f757f3fSDimitry Andric let MCOperandPredicate = [{ 2175f757f3fSDimitry Andric int64_t Imm; 2185f757f3fSDimitry Andric if (!MCOp.evaluateAsConstantImm(Imm)) 2195f757f3fSDimitry Andric return false; 2205f757f3fSDimitry Andric return isUInt<2>(Imm); 2215f757f3fSDimitry Andric }]; 22206c3fb27SDimitry Andric} 2235f757f3fSDimitry Andricdef uimm3 : RISCVUImmOp<3>; 2245f757f3fSDimitry Andricdef uimm4 : RISCVUImmOp<4>; 2255f757f3fSDimitry Andricdef uimm5 : RISCVUImmLeafOp<5>; 2265f757f3fSDimitry Andricdef uimm6 : RISCVUImmLeafOp<6>; 2275f757f3fSDimitry Andricdef uimm7_opcode : RISCVUImmOp<7> { 2280eae32dcSDimitry Andric let ParserMatchClass = InsnDirectiveOpcode; 2290eae32dcSDimitry Andric} 2305f757f3fSDimitry Andricdef uimm7 : RISCVUImmOp<7>; 2315f757f3fSDimitry Andricdef uimm8 : RISCVUImmOp<8>; 2325f757f3fSDimitry Andricdef simm12 : RISCVSImmLeafOp<12> { 2330b57cec5SDimitry Andric let MCOperandPredicate = [{ 2340b57cec5SDimitry Andric int64_t Imm; 2350b57cec5SDimitry Andric if (MCOp.evaluateAsConstantImm(Imm)) 2360b57cec5SDimitry Andric return isInt<12>(Imm); 2370b57cec5SDimitry Andric return MCOp.isBareSymbolRef(); 2380b57cec5SDimitry Andric }]; 2390b57cec5SDimitry Andric} 2400b57cec5SDimitry Andric 241bdd1243dSDimitry Andric// A 12-bit signed immediate which cannot fit in 6-bit signed immediate, 242bdd1243dSDimitry Andric// but even negative value fit in 12-bit. 243bdd1243dSDimitry Andricdef simm12_no6 : ImmLeaf<XLenVT, [{ 244bdd1243dSDimitry Andric return isInt<12>(Imm) && !isInt<6>(Imm) && isInt<12>(-Imm);}]>; 245bdd1243dSDimitry Andric 2460b57cec5SDimitry Andric// A 13-bit signed immediate where the least significant bit is zero. 2470b57cec5SDimitry Andricdef simm13_lsb0 : Operand<OtherVT> { 2480b57cec5SDimitry Andric let ParserMatchClass = SImmAsmOperand<13, "Lsb0">; 249e8d8bef9SDimitry Andric let PrintMethod = "printBranchOperand"; 2500b57cec5SDimitry Andric let EncoderMethod = "getImmOpValueAsr1"; 2510b57cec5SDimitry Andric let DecoderMethod = "decodeSImmOperandAndLsl1<13>"; 2520b57cec5SDimitry Andric let MCOperandPredicate = [{ 2530b57cec5SDimitry Andric int64_t Imm; 2540b57cec5SDimitry Andric if (MCOp.evaluateAsConstantImm(Imm)) 2550b57cec5SDimitry Andric return isShiftedInt<12, 1>(Imm); 2560b57cec5SDimitry Andric return MCOp.isBareSymbolRef(); 2570b57cec5SDimitry Andric }]; 258e8d8bef9SDimitry Andric let OperandType = "OPERAND_PCREL"; 2590b57cec5SDimitry Andric} 2600b57cec5SDimitry Andric 2615f757f3fSDimitry Andricclass UImm20Operand : RISCVOp { 2620b57cec5SDimitry Andric let EncoderMethod = "getImmOpValue"; 2630b57cec5SDimitry Andric let DecoderMethod = "decodeUImmOperand<20>"; 2645f757f3fSDimitry Andric let OperandType = "OPERAND_UIMM20"; 2655f757f3fSDimitry Andric} 2665f757f3fSDimitry Andric 2675f757f3fSDimitry Andricclass UImm20OperandMaybeSym : UImm20Operand { 2680b57cec5SDimitry Andric let MCOperandPredicate = [{ 2690b57cec5SDimitry Andric int64_t Imm; 2700b57cec5SDimitry Andric if (MCOp.evaluateAsConstantImm(Imm)) 2710b57cec5SDimitry Andric return isUInt<20>(Imm); 2720b57cec5SDimitry Andric return MCOp.isBareSymbolRef(); 2730b57cec5SDimitry Andric }]; 2740b57cec5SDimitry Andric} 2750b57cec5SDimitry Andric 2765f757f3fSDimitry Andricdef uimm20_lui : UImm20OperandMaybeSym { 2770b57cec5SDimitry Andric let ParserMatchClass = UImmAsmOperand<20, "LUI">; 2780b57cec5SDimitry Andric} 2795f757f3fSDimitry Andricdef uimm20_auipc : UImm20OperandMaybeSym { 2800b57cec5SDimitry Andric let ParserMatchClass = UImmAsmOperand<20, "AUIPC">; 2810b57cec5SDimitry Andric} 2820b57cec5SDimitry Andric 2835f757f3fSDimitry Andricdef uimm20 : UImm20Operand { 2845f757f3fSDimitry Andric let ParserMatchClass = UImmAsmOperand<20>; 2855f757f3fSDimitry Andric let MCOperandPredicate = [{ 2865f757f3fSDimitry Andric int64_t Imm; 2875f757f3fSDimitry Andric if (!MCOp.evaluateAsConstantImm(Imm)) 2885f757f3fSDimitry Andric return false; 2895f757f3fSDimitry Andric return isUInt<20>(Imm); 2905f757f3fSDimitry Andric }]; 2915f757f3fSDimitry Andric} 2925f757f3fSDimitry Andric 2930b57cec5SDimitry Andricdef Simm21Lsb0JALAsmOperand : SImmAsmOperand<21, "Lsb0JAL"> { 2940b57cec5SDimitry Andric let ParserMethod = "parseJALOffset"; 2950b57cec5SDimitry Andric} 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric// A 21-bit signed immediate where the least significant bit is zero. 2980b57cec5SDimitry Andricdef simm21_lsb0_jal : Operand<OtherVT> { 2990b57cec5SDimitry Andric let ParserMatchClass = Simm21Lsb0JALAsmOperand; 300e8d8bef9SDimitry Andric let PrintMethod = "printBranchOperand"; 3010b57cec5SDimitry Andric let EncoderMethod = "getImmOpValueAsr1"; 3020b57cec5SDimitry Andric let DecoderMethod = "decodeSImmOperandAndLsl1<21>"; 3030b57cec5SDimitry Andric let MCOperandPredicate = [{ 3040b57cec5SDimitry Andric int64_t Imm; 3050b57cec5SDimitry Andric if (MCOp.evaluateAsConstantImm(Imm)) 3060b57cec5SDimitry Andric return isShiftedInt<20, 1>(Imm); 3070b57cec5SDimitry Andric return MCOp.isBareSymbolRef(); 3080b57cec5SDimitry Andric }]; 309e8d8bef9SDimitry Andric let OperandType = "OPERAND_PCREL"; 3100b57cec5SDimitry Andric} 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andricdef BareSymbol : AsmOperandClass { 3130b57cec5SDimitry Andric let Name = "BareSymbol"; 3140b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 3150b57cec5SDimitry Andric let DiagnosticType = "InvalidBareSymbol"; 3160b57cec5SDimitry Andric let ParserMethod = "parseBareSymbol"; 3170b57cec5SDimitry Andric} 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric// A bare symbol. 3200b57cec5SDimitry Andricdef bare_symbol : Operand<XLenVT> { 3210b57cec5SDimitry Andric let ParserMatchClass = BareSymbol; 3220b57cec5SDimitry Andric} 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andricdef CallSymbol : AsmOperandClass { 3250b57cec5SDimitry Andric let Name = "CallSymbol"; 3260b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 3270b57cec5SDimitry Andric let DiagnosticType = "InvalidCallSymbol"; 3280b57cec5SDimitry Andric let ParserMethod = "parseCallSymbol"; 3290b57cec5SDimitry Andric} 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric// A bare symbol used in call/tail only. 3320b57cec5SDimitry Andricdef call_symbol : Operand<XLenVT> { 3330b57cec5SDimitry Andric let ParserMatchClass = CallSymbol; 3340b57cec5SDimitry Andric} 3350b57cec5SDimitry Andric 3365ffd83dbSDimitry Andricdef PseudoJumpSymbol : AsmOperandClass { 3375ffd83dbSDimitry Andric let Name = "PseudoJumpSymbol"; 3385ffd83dbSDimitry Andric let RenderMethod = "addImmOperands"; 3395ffd83dbSDimitry Andric let DiagnosticType = "InvalidPseudoJumpSymbol"; 3405ffd83dbSDimitry Andric let ParserMethod = "parsePseudoJumpSymbol"; 3415ffd83dbSDimitry Andric} 3425ffd83dbSDimitry Andric 3435ffd83dbSDimitry Andric// A bare symbol used for pseudo jumps only. 3445ffd83dbSDimitry Andricdef pseudo_jump_symbol : Operand<XLenVT> { 3455ffd83dbSDimitry Andric let ParserMatchClass = PseudoJumpSymbol; 3465ffd83dbSDimitry Andric} 3475ffd83dbSDimitry Andric 3480b57cec5SDimitry Andricdef TPRelAddSymbol : AsmOperandClass { 3490b57cec5SDimitry Andric let Name = "TPRelAddSymbol"; 3500b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 3510b57cec5SDimitry Andric let DiagnosticType = "InvalidTPRelAddSymbol"; 3520b57cec5SDimitry Andric let ParserMethod = "parseOperandWithModifier"; 3530b57cec5SDimitry Andric} 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric// A bare symbol with the %tprel_add variant. 3560b57cec5SDimitry Andricdef tprel_add_symbol : Operand<XLenVT> { 3570b57cec5SDimitry Andric let ParserMatchClass = TPRelAddSymbol; 3580b57cec5SDimitry Andric} 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andricdef CSRSystemRegister : AsmOperandClass { 3610b57cec5SDimitry Andric let Name = "CSRSystemRegister"; 3620b57cec5SDimitry Andric let ParserMethod = "parseCSRSystemRegister"; 3630b57cec5SDimitry Andric let DiagnosticType = "InvalidCSRSystemRegister"; 3640b57cec5SDimitry Andric} 3650b57cec5SDimitry Andric 3665f757f3fSDimitry Andricdef csr_sysreg : RISCVOp { 3670b57cec5SDimitry Andric let ParserMatchClass = CSRSystemRegister; 3680b57cec5SDimitry Andric let PrintMethod = "printCSRSystemRegister"; 3690b57cec5SDimitry Andric let DecoderMethod = "decodeUImmOperand<12>"; 3708bcb0991SDimitry Andric let OperandType = "OPERAND_UIMM12"; 3710b57cec5SDimitry Andric} 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric// A parameterized register class alternative to i32imm/i64imm from Target.td. 3740b57cec5SDimitry Andricdef ixlenimm : Operand<XLenVT>; 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andricdef ixlenimm_li : Operand<XLenVT> { 3770b57cec5SDimitry Andric let ParserMatchClass = ImmXLenAsmOperand<"", "LI">; 3780b57cec5SDimitry Andric} 3790b57cec5SDimitry Andric 38006c3fb27SDimitry Andric// Accepts subset of LI operands, used by LAImm and LLAImm 38106c3fb27SDimitry Andricdef ixlenimm_li_restricted : Operand<XLenVT> { 38206c3fb27SDimitry Andric let ParserMatchClass = ImmXLenAsmOperand<"", "LI_Restricted">; 38306c3fb27SDimitry Andric} 384fe6060f1SDimitry Andric 38506c3fb27SDimitry Andric// Standalone (codegen-only) immleaf patterns. 3860b57cec5SDimitry Andric 387e8d8bef9SDimitry Andric// A 6-bit constant greater than 32. 388e8d8bef9SDimitry Andricdef uimm6gt32 : ImmLeaf<XLenVT, [{ 389e8d8bef9SDimitry Andric return isUInt<6>(Imm) && Imm > 32; 390e8d8bef9SDimitry Andric}]>; 391e8d8bef9SDimitry Andric 3920b57cec5SDimitry Andric// Addressing modes. 3930b57cec5SDimitry Andric// Necessary because a frameindex can't be matched directly in a pattern. 39481ad6265SDimitry Andricdef FrameAddrRegImm : ComplexPattern<iPTR, 2, "SelectFrameAddrRegImm", 39581ad6265SDimitry Andric [frameindex, or, add]>; 39681ad6265SDimitry Andricdef AddrRegImm : ComplexPattern<iPTR, 2, "SelectAddrRegImm">; 3970b57cec5SDimitry Andric 3985ffd83dbSDimitry Andric// Return the negation of an immediate value. 3995ffd83dbSDimitry Andricdef NegImm : SDNodeXForm<imm, [{ 4005ffd83dbSDimitry Andric return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N), 4015ffd83dbSDimitry Andric N->getValueType(0)); 4025ffd83dbSDimitry Andric}]>; 4035ffd83dbSDimitry Andric 404e8d8bef9SDimitry Andric// Return an immediate value minus 32. 405e8d8bef9SDimitry Andricdef ImmSub32 : SDNodeXForm<imm, [{ 406e8d8bef9SDimitry Andric return CurDAG->getTargetConstant(N->getSExtValue() - 32, SDLoc(N), 407e8d8bef9SDimitry Andric N->getValueType(0)); 408e8d8bef9SDimitry Andric}]>; 409e8d8bef9SDimitry Andric 410e8d8bef9SDimitry Andric// Return an immediate subtracted from XLen. 411e8d8bef9SDimitry Andricdef ImmSubFromXLen : SDNodeXForm<imm, [{ 412e8d8bef9SDimitry Andric uint64_t XLen = Subtarget->getXLen(); 413e8d8bef9SDimitry Andric return CurDAG->getTargetConstant(XLen - N->getZExtValue(), SDLoc(N), 414e8d8bef9SDimitry Andric N->getValueType(0)); 415e8d8bef9SDimitry Andric}]>; 416e8d8bef9SDimitry Andric 417e8d8bef9SDimitry Andric// Return an immediate subtracted from 32. 418e8d8bef9SDimitry Andricdef ImmSubFrom32 : SDNodeXForm<imm, [{ 419e8d8bef9SDimitry Andric return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N), 420e8d8bef9SDimitry Andric N->getValueType(0)); 421e8d8bef9SDimitry Andric}]>; 422e8d8bef9SDimitry Andric 423fe6060f1SDimitry Andric// Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1), 42481ad6265SDimitry Andric// in which imm = imm0 + imm1 and both imm0 and imm1 are simm12. We make imm0 42581ad6265SDimitry Andric// as large as possible and imm1 as small as possible so that we might be able 42681ad6265SDimitry Andric// to use c.addi for the small immediate. 427fe6060f1SDimitry Andricdef AddiPair : PatLeaf<(imm), [{ 428fe6060f1SDimitry Andric if (!N->hasOneUse()) 429fe6060f1SDimitry Andric return false; 430fe6060f1SDimitry Andric // The immediate operand must be in range [-4096,-2049] or [2048,4094]. 431fe6060f1SDimitry Andric int64_t Imm = N->getSExtValue(); 432fe6060f1SDimitry Andric return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094); 433fe6060f1SDimitry Andric}]>; 434fe6060f1SDimitry Andric 43581ad6265SDimitry Andric// Return imm - (imm < 0 ? -2048 : 2047). 43681ad6265SDimitry Andricdef AddiPairImmSmall : SDNodeXForm<imm, [{ 43781ad6265SDimitry Andric int64_t Imm = N->getSExtValue(); 43881ad6265SDimitry Andric int64_t Adj = N->getSExtValue() < 0 ? -2048 : 2047; 43981ad6265SDimitry Andric return CurDAG->getTargetConstant(Imm - Adj, SDLoc(N), 440fe6060f1SDimitry Andric N->getValueType(0)); 441fe6060f1SDimitry Andric}]>; 442fe6060f1SDimitry Andric 44381ad6265SDimitry Andric// Return -2048 if immediate is negative or 2047 if positive. These are the 44481ad6265SDimitry Andric// largest simm12 values. 44581ad6265SDimitry Andricdef AddiPairImmLarge : SDNodeXForm<imm, [{ 44681ad6265SDimitry Andric int64_t Imm = N->getSExtValue() < 0 ? -2048 : 2047; 44781ad6265SDimitry Andric return CurDAG->getTargetConstant(Imm, SDLoc(N), 448fe6060f1SDimitry Andric N->getValueType(0)); 449fe6060f1SDimitry Andric}]>; 450fe6060f1SDimitry Andric 45181ad6265SDimitry Andricdef TrailingZeros : SDNodeXForm<imm, [{ 45206c3fb27SDimitry Andric return CurDAG->getTargetConstant(llvm::countr_zero(N->getZExtValue()), 45381ad6265SDimitry Andric SDLoc(N), N->getValueType(0)); 45481ad6265SDimitry Andric}]>; 45581ad6265SDimitry Andric 45604eeddc0SDimitry Andricdef XLenSubTrailingOnes : SDNodeXForm<imm, [{ 45704eeddc0SDimitry Andric uint64_t XLen = Subtarget->getXLen(); 45806c3fb27SDimitry Andric uint64_t TrailingOnes = llvm::countr_one(N->getZExtValue()); 45904eeddc0SDimitry Andric return CurDAG->getTargetConstant(XLen - TrailingOnes, SDLoc(N), 46004eeddc0SDimitry Andric N->getValueType(0)); 46104eeddc0SDimitry Andric}]>; 46204eeddc0SDimitry Andric 46304eeddc0SDimitry Andric// Checks if this mask is a non-empty sequence of ones starting at the 46481ad6265SDimitry Andric// most/least significant bit with the remainder zero and exceeds simm32/simm12. 46581ad6265SDimitry Andricdef LeadingOnesMask : PatLeaf<(imm), [{ 46681ad6265SDimitry Andric if (!N->hasOneUse()) 46781ad6265SDimitry Andric return false; 46881ad6265SDimitry Andric return !isInt<32>(N->getSExtValue()) && isMask_64(~N->getSExtValue()); 46981ad6265SDimitry Andric}], TrailingZeros>; 47081ad6265SDimitry Andric 47104eeddc0SDimitry Andricdef TrailingOnesMask : PatLeaf<(imm), [{ 47204eeddc0SDimitry Andric if (!N->hasOneUse()) 47304eeddc0SDimitry Andric return false; 47404eeddc0SDimitry Andric return !isInt<12>(N->getSExtValue()) && isMask_64(N->getZExtValue()); 47504eeddc0SDimitry Andric}], XLenSubTrailingOnes>; 47604eeddc0SDimitry Andric 477bdd1243dSDimitry Andric// Similar to LeadingOnesMask, but only consider leading ones in the lower 32 478bdd1243dSDimitry Andric// bits. 479bdd1243dSDimitry Andricdef LeadingOnesWMask : PatLeaf<(imm), [{ 480bdd1243dSDimitry Andric if (!N->hasOneUse()) 481bdd1243dSDimitry Andric return false; 482bdd1243dSDimitry Andric // If the value is a uint32 but not an int32, it must have bit 31 set and 483bdd1243dSDimitry Andric // bits 63:32 cleared. After that we're looking for a shifted mask but not 484bdd1243dSDimitry Andric // an all ones mask. 485bdd1243dSDimitry Andric int64_t Imm = N->getSExtValue(); 486bdd1243dSDimitry Andric return !isInt<32>(Imm) && isUInt<32>(Imm) && isShiftedMask_64(Imm) && 487bdd1243dSDimitry Andric Imm != UINT64_C(0xffffffff); 488bdd1243dSDimitry Andric}], TrailingZeros>; 489bdd1243dSDimitry Andric 4900b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 4910b57cec5SDimitry Andric// Instruction Formats 4920b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 4930b57cec5SDimitry Andric 4940b57cec5SDimitry Andricinclude "RISCVInstrFormats.td" 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 4970b57cec5SDimitry Andric// Instruction Class Templates 4980b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 5010b57cec5SDimitry Andricclass BranchCC_rri<bits<3> funct3, string opcodestr> 5020b57cec5SDimitry Andric : RVInstB<funct3, OPC_BRANCH, (outs), 5030b57cec5SDimitry Andric (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12), 50413138422SDimitry Andric opcodestr, "$rs1, $rs2, $imm12">, 5055ffd83dbSDimitry Andric Sched<[WriteJmp, ReadJmp, ReadJmp]> { 5060b57cec5SDimitry Andric let isBranch = 1; 5070b57cec5SDimitry Andric let isTerminator = 1; 5080b57cec5SDimitry Andric} 5090b57cec5SDimitry Andric 51081ad6265SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { 5110b57cec5SDimitry Andricclass Load_ri<bits<3> funct3, string opcodestr> 512bdd1243dSDimitry Andric : RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPRMem:$rs1, simm12:$imm12), 5130b57cec5SDimitry Andric opcodestr, "$rd, ${imm12}(${rs1})">; 5140b57cec5SDimitry Andric 51581ad6265SDimitry Andricclass HLoad_r<bits<7> funct7, bits<5> funct5, string opcodestr> 51681ad6265SDimitry Andric : RVInstR<funct7, 0b100, OPC_SYSTEM, (outs GPR:$rd), 51781ad6265SDimitry Andric (ins GPRMemZeroOffset:$rs1), opcodestr, "$rd, $rs1"> { 51881ad6265SDimitry Andric let rs2 = funct5; 51981ad6265SDimitry Andric} 52081ad6265SDimitry Andric} 52181ad6265SDimitry Andric 5220b57cec5SDimitry Andric// Operands for stores are in the order srcreg, base, offset rather than 5230b57cec5SDimitry Andric// reflecting the order these fields are specified in the instruction 5240b57cec5SDimitry Andric// encoding. 52581ad6265SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 1 in { 5260b57cec5SDimitry Andricclass Store_rri<bits<3> funct3, string opcodestr> 5270b57cec5SDimitry Andric : RVInstS<funct3, OPC_STORE, (outs), 528bdd1243dSDimitry Andric (ins GPR:$rs2, GPRMem:$rs1, simm12:$imm12), 5290b57cec5SDimitry Andric opcodestr, "$rs2, ${imm12}(${rs1})">; 5300b57cec5SDimitry Andric 53181ad6265SDimitry Andricclass HStore_rr<bits<7> funct7, string opcodestr> 53281ad6265SDimitry Andric : RVInstR<funct7, 0b100, OPC_SYSTEM, (outs), 53381ad6265SDimitry Andric (ins GPR:$rs2, GPRMemZeroOffset:$rs1), 53481ad6265SDimitry Andric opcodestr, "$rs2, $rs1"> { 53581ad6265SDimitry Andric let rd = 0; 53681ad6265SDimitry Andric} 53781ad6265SDimitry Andric} 53881ad6265SDimitry Andric 5390b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 5400b57cec5SDimitry Andricclass ALU_ri<bits<3> funct3, string opcodestr> 5410b57cec5SDimitry Andric : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), 54213138422SDimitry Andric opcodestr, "$rd, $rs1, $imm12">, 54313138422SDimitry Andric Sched<[WriteIALU, ReadIALU]>; 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 546fe6060f1SDimitry Andricclass Shift_ri<bits<5> imm11_7, bits<3> funct3, string opcodestr> 547fe6060f1SDimitry Andric : RVInstIShift<imm11_7, funct3, OPC_OP_IMM, (outs GPR:$rd), 5480b57cec5SDimitry Andric (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr, 54913138422SDimitry Andric "$rd, $rs1, $shamt">, 550fe6060f1SDimitry Andric Sched<[WriteShiftImm, ReadShiftImm]>; 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 55381ad6265SDimitry Andricclass ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr, 55481ad6265SDimitry Andric bit Commutable = 0> 5550b57cec5SDimitry Andric : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), 55681ad6265SDimitry Andric opcodestr, "$rd, $rs1, $rs2"> { 55781ad6265SDimitry Andric let isCommutable = Commutable; 55881ad6265SDimitry Andric} 5590b57cec5SDimitry Andric 560e8d8bef9SDimitry Andriclet hasNoSchedulingInfo = 1, 561e8d8bef9SDimitry Andric hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 5620b57cec5SDimitry Andricclass CSR_ir<bits<3> funct3, string opcodestr> 5630b57cec5SDimitry Andric : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins csr_sysreg:$imm12, GPR:$rs1), 56413138422SDimitry Andric opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR, ReadCSR]>; 5650b57cec5SDimitry Andric 566e8d8bef9SDimitry Andriclet hasNoSchedulingInfo = 1, 567e8d8bef9SDimitry Andric hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 5680b57cec5SDimitry Andricclass CSR_ii<bits<3> funct3, string opcodestr> 5690b57cec5SDimitry Andric : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), 5700b57cec5SDimitry Andric (ins csr_sysreg:$imm12, uimm5:$rs1), 57113138422SDimitry Andric opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR]>; 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 574fe6060f1SDimitry Andricclass ShiftW_ri<bits<7> imm11_5, bits<3> funct3, string opcodestr> 575fe6060f1SDimitry Andric : RVInstIShiftW<imm11_5, funct3, OPC_OP_IMM_32, (outs GPR:$rd), 5760b57cec5SDimitry Andric (ins GPR:$rs1, uimm5:$shamt), opcodestr, 57713138422SDimitry Andric "$rd, $rs1, $shamt">, 578fe6060f1SDimitry Andric Sched<[WriteShiftImm32, ReadShiftImm32]>; 5790b57cec5SDimitry Andric 5800b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 58181ad6265SDimitry Andricclass ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr, 58281ad6265SDimitry Andric bit Commutable = 0> 5830b57cec5SDimitry Andric : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd), 58481ad6265SDimitry Andric (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2"> { 58581ad6265SDimitry Andric let isCommutable = Commutable; 58681ad6265SDimitry Andric} 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andriclet hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 5890b57cec5SDimitry Andricclass Priv<string opcodestr, bits<7> funct7> 5900b57cec5SDimitry Andric : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2), 5910b57cec5SDimitry Andric opcodestr, "">; 5920b57cec5SDimitry Andric 59381ad6265SDimitry Andriclet hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 59481ad6265SDimitry Andricclass Priv_rr<string opcodestr, bits<7> funct7> 59581ad6265SDimitry Andric : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2), 59681ad6265SDimitry Andric opcodestr, "$rs1, $rs2"> { 59781ad6265SDimitry Andric let rd = 0; 59881ad6265SDimitry Andric} 59981ad6265SDimitry Andric 6000b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 6010b57cec5SDimitry Andric// Instructions 6020b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { 605bdd1243dSDimitry Andriclet isReMaterializable = 1, isAsCheapAsAMove = 1, 606bdd1243dSDimitry Andric IsSignExtendingOpW = 1 in 6070b57cec5SDimitry Andricdef LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20_lui:$imm20), 60813138422SDimitry Andric "lui", "$rd, $imm20">, Sched<[WriteIALU]>; 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andricdef AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20_auipc:$imm20), 61113138422SDimitry Andric "auipc", "$rd, $imm20">, Sched<[WriteIALU]>; 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andricdef JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20), 61413138422SDimitry Andric "jal", "$rd, $imm20">, Sched<[WriteJal]>; 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andricdef JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd), 6170b57cec5SDimitry Andric (ins GPR:$rs1, simm12:$imm12), 61813138422SDimitry Andric "jalr", "$rd, ${imm12}(${rs1})">, 61913138422SDimitry Andric Sched<[WriteJalr, ReadJalr]>; 6200b57cec5SDimitry Andric} // hasSideEffects = 0, mayLoad = 0, mayStore = 0 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andricdef BEQ : BranchCC_rri<0b000, "beq">; 6230b57cec5SDimitry Andricdef BNE : BranchCC_rri<0b001, "bne">; 6240b57cec5SDimitry Andricdef BLT : BranchCC_rri<0b100, "blt">; 6250b57cec5SDimitry Andricdef BGE : BranchCC_rri<0b101, "bge">; 6260b57cec5SDimitry Andricdef BLTU : BranchCC_rri<0b110, "bltu">; 6270b57cec5SDimitry Andricdef BGEU : BranchCC_rri<0b111, "bgeu">; 6280b57cec5SDimitry Andric 629bdd1243dSDimitry Andriclet IsSignExtendingOpW = 1 in { 63013138422SDimitry Andricdef LB : Load_ri<0b000, "lb">, Sched<[WriteLDB, ReadMemBase]>; 63113138422SDimitry Andricdef LH : Load_ri<0b001, "lh">, Sched<[WriteLDH, ReadMemBase]>; 63213138422SDimitry Andricdef LW : Load_ri<0b010, "lw">, Sched<[WriteLDW, ReadMemBase]>; 63313138422SDimitry Andricdef LBU : Load_ri<0b100, "lbu">, Sched<[WriteLDB, ReadMemBase]>; 63413138422SDimitry Andricdef LHU : Load_ri<0b101, "lhu">, Sched<[WriteLDH, ReadMemBase]>; 635bdd1243dSDimitry Andric} 6360b57cec5SDimitry Andric 63713138422SDimitry Andricdef SB : Store_rri<0b000, "sb">, Sched<[WriteSTB, ReadStoreData, ReadMemBase]>; 63813138422SDimitry Andricdef SH : Store_rri<0b001, "sh">, Sched<[WriteSTH, ReadStoreData, ReadMemBase]>; 63913138422SDimitry Andricdef SW : Store_rri<0b010, "sw">, Sched<[WriteSTW, ReadStoreData, ReadMemBase]>; 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric// ADDI isn't always rematerializable, but isReMaterializable will be used as 6420b57cec5SDimitry Andric// a hint which is verified in isReallyTriviallyReMaterializable. 6430b57cec5SDimitry Andriclet isReMaterializable = 1, isAsCheapAsAMove = 1 in 6440b57cec5SDimitry Andricdef ADDI : ALU_ri<0b000, "addi">; 6450b57cec5SDimitry Andric 646bdd1243dSDimitry Andriclet IsSignExtendingOpW = 1 in { 6470b57cec5SDimitry Andricdef SLTI : ALU_ri<0b010, "slti">; 6480b57cec5SDimitry Andricdef SLTIU : ALU_ri<0b011, "sltiu">; 649bdd1243dSDimitry Andric} 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andriclet isReMaterializable = 1, isAsCheapAsAMove = 1 in { 6520b57cec5SDimitry Andricdef XORI : ALU_ri<0b100, "xori">; 6530b57cec5SDimitry Andricdef ORI : ALU_ri<0b110, "ori">; 6540b57cec5SDimitry Andric} 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andricdef ANDI : ALU_ri<0b111, "andi">; 6570b57cec5SDimitry Andric 658fe6060f1SDimitry Andricdef SLLI : Shift_ri<0b00000, 0b001, "slli">; 659fe6060f1SDimitry Andricdef SRLI : Shift_ri<0b00000, 0b101, "srli">; 660fe6060f1SDimitry Andricdef SRAI : Shift_ri<0b01000, 0b101, "srai">; 6610b57cec5SDimitry Andric 66206c3fb27SDimitry Andricdef ADD : ALU_rr<0b0000000, 0b000, "add", Commutable=1>, 66381ad6265SDimitry Andric Sched<[WriteIALU, ReadIALU, ReadIALU]>; 66481ad6265SDimitry Andricdef SUB : ALU_rr<0b0100000, 0b000, "sub">, 66581ad6265SDimitry Andric Sched<[WriteIALU, ReadIALU, ReadIALU]>; 66681ad6265SDimitry Andricdef SLL : ALU_rr<0b0000000, 0b001, "sll">, 66781ad6265SDimitry Andric Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 668bdd1243dSDimitry Andriclet IsSignExtendingOpW = 1 in { 66981ad6265SDimitry Andricdef SLT : ALU_rr<0b0000000, 0b010, "slt">, 67081ad6265SDimitry Andric Sched<[WriteIALU, ReadIALU, ReadIALU]>; 67181ad6265SDimitry Andricdef SLTU : ALU_rr<0b0000000, 0b011, "sltu">, 67281ad6265SDimitry Andric Sched<[WriteIALU, ReadIALU, ReadIALU]>; 673bdd1243dSDimitry Andric} 67406c3fb27SDimitry Andricdef XOR : ALU_rr<0b0000000, 0b100, "xor", Commutable=1>, 67581ad6265SDimitry Andric Sched<[WriteIALU, ReadIALU, ReadIALU]>; 67681ad6265SDimitry Andricdef SRL : ALU_rr<0b0000000, 0b101, "srl">, 67781ad6265SDimitry Andric Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 67881ad6265SDimitry Andricdef SRA : ALU_rr<0b0100000, 0b101, "sra">, 67981ad6265SDimitry Andric Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 68006c3fb27SDimitry Andricdef OR : ALU_rr<0b0000000, 0b110, "or", Commutable=1>, 68181ad6265SDimitry Andric Sched<[WriteIALU, ReadIALU, ReadIALU]>; 68206c3fb27SDimitry Andricdef AND : ALU_rr<0b0000000, 0b111, "and", Commutable=1>, 68381ad6265SDimitry Andric Sched<[WriteIALU, ReadIALU, ReadIALU]>; 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andriclet hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { 6860b57cec5SDimitry Andricdef FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs), 6870b57cec5SDimitry Andric (ins fencearg:$pred, fencearg:$succ), 68813138422SDimitry Andric "fence", "$pred, $succ">, Sched<[]> { 6890b57cec5SDimitry Andric bits<4> pred; 6900b57cec5SDimitry Andric bits<4> succ; 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric let rs1 = 0; 6930b57cec5SDimitry Andric let rd = 0; 6940b57cec5SDimitry Andric let imm12 = {0b0000,pred,succ}; 6950b57cec5SDimitry Andric} 6960b57cec5SDimitry Andric 69713138422SDimitry Andricdef FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", "">, Sched<[]> { 6980b57cec5SDimitry Andric let rs1 = 0; 6990b57cec5SDimitry Andric let rd = 0; 7000b57cec5SDimitry Andric let imm12 = {0b1000,0b0011,0b0011}; 7010b57cec5SDimitry Andric} 7020b57cec5SDimitry Andric 70313138422SDimitry Andricdef FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", "">, Sched<[]> { 7040b57cec5SDimitry Andric let rs1 = 0; 7050b57cec5SDimitry Andric let rd = 0; 7060b57cec5SDimitry Andric let imm12 = 0; 7070b57cec5SDimitry Andric} 7080b57cec5SDimitry Andric 70913138422SDimitry Andricdef ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", "">, Sched<[WriteJmp]> { 7100b57cec5SDimitry Andric let rs1 = 0; 7110b57cec5SDimitry Andric let rd = 0; 7120b57cec5SDimitry Andric let imm12 = 0; 7130b57cec5SDimitry Andric} 7140b57cec5SDimitry Andric 71513138422SDimitry Andricdef EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", "">, 71613138422SDimitry Andric Sched<[]> { 7170b57cec5SDimitry Andric let rs1 = 0; 7180b57cec5SDimitry Andric let rd = 0; 7190b57cec5SDimitry Andric let imm12 = 1; 7200b57cec5SDimitry Andric} 7210b57cec5SDimitry Andric 7220b57cec5SDimitry Andric// This is a de facto standard (as set by GNU binutils) 32-bit unimplemented 7230b57cec5SDimitry Andric// instruction (i.e., it should always trap, if your implementation has invalid 7240b57cec5SDimitry Andric// instruction traps). 72513138422SDimitry Andricdef UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", "">, 72613138422SDimitry Andric Sched<[]> { 7270b57cec5SDimitry Andric let rs1 = 0; 7280b57cec5SDimitry Andric let rd = 0; 7290b57cec5SDimitry Andric let imm12 = 0b110000000000; 7300b57cec5SDimitry Andric} 731bdd1243dSDimitry Andric 7320b57cec5SDimitry Andric} // hasSideEffects = 1, mayLoad = 0, mayStore = 0 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andricdef CSRRW : CSR_ir<0b001, "csrrw">; 7350b57cec5SDimitry Andricdef CSRRS : CSR_ir<0b010, "csrrs">; 7360b57cec5SDimitry Andricdef CSRRC : CSR_ir<0b011, "csrrc">; 7370b57cec5SDimitry Andric 7380b57cec5SDimitry Andricdef CSRRWI : CSR_ii<0b101, "csrrwi">; 7390b57cec5SDimitry Andricdef CSRRSI : CSR_ii<0b110, "csrrsi">; 7400b57cec5SDimitry Andricdef CSRRCI : CSR_ii<0b111, "csrrci">; 7410b57cec5SDimitry Andric 7420b57cec5SDimitry Andric/// RV64I instructions 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 745bdd1243dSDimitry Andricdef LWU : Load_ri<0b110, "lwu">, Sched<[WriteLDW, ReadMemBase]>; 74613138422SDimitry Andricdef LD : Load_ri<0b011, "ld">, Sched<[WriteLDD, ReadMemBase]>; 74713138422SDimitry Andricdef SD : Store_rri<0b011, "sd">, Sched<[WriteSTD, ReadStoreData, ReadMemBase]>; 7480b57cec5SDimitry Andric 749bdd1243dSDimitry Andriclet IsSignExtendingOpW = 1 in { 7500b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 7510b57cec5SDimitry Andricdef ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd), 7520b57cec5SDimitry Andric (ins GPR:$rs1, simm12:$imm12), 75313138422SDimitry Andric "addiw", "$rd, $rs1, $imm12">, 75413138422SDimitry Andric Sched<[WriteIALU32, ReadIALU32]>; 7550b57cec5SDimitry Andric 756fe6060f1SDimitry Andricdef SLLIW : ShiftW_ri<0b0000000, 0b001, "slliw">; 757fe6060f1SDimitry Andricdef SRLIW : ShiftW_ri<0b0000000, 0b101, "srliw">; 758fe6060f1SDimitry Andricdef SRAIW : ShiftW_ri<0b0100000, 0b101, "sraiw">; 7590b57cec5SDimitry Andric 76006c3fb27SDimitry Andricdef ADDW : ALUW_rr<0b0000000, 0b000, "addw", Commutable=1>, 76113138422SDimitry Andric Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 76213138422SDimitry Andricdef SUBW : ALUW_rr<0b0100000, 0b000, "subw">, 76313138422SDimitry Andric Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 76413138422SDimitry Andricdef SLLW : ALUW_rr<0b0000000, 0b001, "sllw">, 765fe6060f1SDimitry Andric Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 76613138422SDimitry Andricdef SRLW : ALUW_rr<0b0000000, 0b101, "srlw">, 767fe6060f1SDimitry Andric Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 76813138422SDimitry Andricdef SRAW : ALUW_rr<0b0100000, 0b101, "sraw">, 769fe6060f1SDimitry Andric Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 770bdd1243dSDimitry Andric} // IsSignExtendingOpW = 1 7710b57cec5SDimitry Andric} // Predicates = [IsRV64] 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 7740b57cec5SDimitry Andric// Privileged instructions 7750b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 7760b57cec5SDimitry Andric 7770b57cec5SDimitry Andriclet isBarrier = 1, isReturn = 1, isTerminator = 1 in { 77813138422SDimitry Andricdef SRET : Priv<"sret", 0b0001000>, Sched<[]> { 7790b57cec5SDimitry Andric let rd = 0; 7800b57cec5SDimitry Andric let rs1 = 0; 7810b57cec5SDimitry Andric let rs2 = 0b00010; 7820b57cec5SDimitry Andric} 7830b57cec5SDimitry Andric 78413138422SDimitry Andricdef MRET : Priv<"mret", 0b0011000>, Sched<[]> { 7850b57cec5SDimitry Andric let rd = 0; 7860b57cec5SDimitry Andric let rs1 = 0; 7870b57cec5SDimitry Andric let rs2 = 0b00010; 7880b57cec5SDimitry Andric} 7890b57cec5SDimitry Andric} // isBarrier = 1, isReturn = 1, isTerminator = 1 7900b57cec5SDimitry Andric 79113138422SDimitry Andricdef WFI : Priv<"wfi", 0b0001000>, Sched<[]> { 7920b57cec5SDimitry Andric let rd = 0; 7930b57cec5SDimitry Andric let rs1 = 0; 7940b57cec5SDimitry Andric let rs2 = 0b00101; 7950b57cec5SDimitry Andric} 7960b57cec5SDimitry Andric 797bdd1243dSDimitry Andriclet Predicates = [HasStdExtSvinval] in { 79881ad6265SDimitry Andricdef SFENCE_W_INVAL : Priv<"sfence.w.inval", 0b0001100>, Sched<[]> { 7990b57cec5SDimitry Andric let rd = 0; 80081ad6265SDimitry Andric let rs1 = 0; 80181ad6265SDimitry Andric let rs2 = 0; 80281ad6265SDimitry Andric} 80381ad6265SDimitry Andric 80481ad6265SDimitry Andricdef SFENCE_INVAL_IR : Priv<"sfence.inval.ir", 0b0001100>, Sched<[]> { 80581ad6265SDimitry Andric let rd = 0; 80681ad6265SDimitry Andric let rs1 = 0; 80781ad6265SDimitry Andric let rs2 = 0b00001; 80881ad6265SDimitry Andric} 80981ad6265SDimitry Andricdef SINVAL_VMA : Priv_rr<"sinval.vma", 0b0001011>, Sched<[]>; 81081ad6265SDimitry Andricdef HINVAL_VVMA : Priv_rr<"hinval.vvma", 0b0010011>, Sched<[]>; 81181ad6265SDimitry Andricdef HINVAL_GVMA : Priv_rr<"hinval.gvma", 0b0110011>, Sched<[]>; 812bdd1243dSDimitry Andric} // Predicates = [HasStdExtSvinval] 813bdd1243dSDimitry Andric 814bdd1243dSDimitry Andricdef SFENCE_VMA : Priv_rr<"sfence.vma", 0b0001001>, Sched<[]>; 815bdd1243dSDimitry Andric 816bdd1243dSDimitry Andriclet Predicates = [HasStdExtH] in { 817bdd1243dSDimitry Andricdef HFENCE_VVMA : Priv_rr<"hfence.vvma", 0b0010001>, Sched<[]>; 818bdd1243dSDimitry Andricdef HFENCE_GVMA : Priv_rr<"hfence.gvma", 0b0110001>, Sched<[]>; 81981ad6265SDimitry Andric 82081ad6265SDimitry Andricdef HLV_B : HLoad_r<0b0110000, 0b00000, "hlv.b">, Sched<[]>; 82181ad6265SDimitry Andricdef HLV_BU : HLoad_r<0b0110000, 0b00001, "hlv.bu">, Sched<[]>; 82281ad6265SDimitry Andricdef HLV_H : HLoad_r<0b0110010, 0b00000, "hlv.h">, Sched<[]>; 82381ad6265SDimitry Andricdef HLV_HU : HLoad_r<0b0110010, 0b00001, "hlv.hu">, Sched<[]>; 82481ad6265SDimitry Andricdef HLVX_HU : HLoad_r<0b0110010, 0b00011, "hlvx.hu">, Sched<[]>; 82581ad6265SDimitry Andricdef HLV_W : HLoad_r<0b0110100, 0b00000, "hlv.w">, Sched<[]>; 82681ad6265SDimitry Andricdef HLVX_WU : HLoad_r<0b0110100, 0b00011, "hlvx.wu">, Sched<[]>; 82781ad6265SDimitry Andricdef HSV_B : HStore_rr<0b0110001, "hsv.b">, Sched<[]>; 82881ad6265SDimitry Andricdef HSV_H : HStore_rr<0b0110011, "hsv.h">, Sched<[]>; 82981ad6265SDimitry Andricdef HSV_W : HStore_rr<0b0110101, "hsv.w">, Sched<[]>; 830bdd1243dSDimitry Andric} 831bdd1243dSDimitry Andriclet Predicates = [IsRV64, HasStdExtH] in { 83281ad6265SDimitry Andricdef HLV_WU : HLoad_r<0b0110100, 0b00001, "hlv.wu">, Sched<[]>; 83381ad6265SDimitry Andricdef HLV_D : HLoad_r<0b0110110, 0b00000, "hlv.d">, Sched<[]>; 83481ad6265SDimitry Andricdef HSV_D : HStore_rr<0b0110111, "hsv.d">, Sched<[]>; 8350b57cec5SDimitry Andric} 8360b57cec5SDimitry Andric 8370b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 8385ffd83dbSDimitry Andric// Debug instructions 8395ffd83dbSDimitry Andric//===----------------------------------------------------------------------===// 8405ffd83dbSDimitry Andric 8415ffd83dbSDimitry Andriclet isBarrier = 1, isReturn = 1, isTerminator = 1 in { 8425ffd83dbSDimitry Andricdef DRET : Priv<"dret", 0b0111101>, Sched<[]> { 8435ffd83dbSDimitry Andric let rd = 0; 8445ffd83dbSDimitry Andric let rs1 = 0; 8455ffd83dbSDimitry Andric let rs2 = 0b10010; 8465ffd83dbSDimitry Andric} 8475ffd83dbSDimitry Andric} // isBarrier = 1, isReturn = 1, isTerminator = 1 8485ffd83dbSDimitry Andric 8495ffd83dbSDimitry Andric//===----------------------------------------------------------------------===// 8500b57cec5SDimitry Andric// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) 8510b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 8520b57cec5SDimitry Andric 8530b57cec5SDimitry Andricdef : InstAlias<"nop", (ADDI X0, X0, 0)>; 8540b57cec5SDimitry Andric 8550b57cec5SDimitry Andric// Note that the size is 32 because up to 8 32-bit instructions are needed to 8560b57cec5SDimitry Andric// generate an arbitrary 64-bit immediate. However, the size does not really 8570b57cec5SDimitry Andric// matter since PseudoLI is currently only used in the AsmParser where it gets 8580b57cec5SDimitry Andric// expanded to real instructions immediately. 8590b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32, 8600b57cec5SDimitry Andric isCodeGenOnly = 0, isAsmParserOnly = 1 in 8610b57cec5SDimitry Andricdef PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [], 8620b57cec5SDimitry Andric "li", "$rd, $imm">; 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andricdef PseudoLB : PseudoLoad<"lb">; 8650b57cec5SDimitry Andricdef PseudoLBU : PseudoLoad<"lbu">; 8660b57cec5SDimitry Andricdef PseudoLH : PseudoLoad<"lh">; 8670b57cec5SDimitry Andricdef PseudoLHU : PseudoLoad<"lhu">; 8680b57cec5SDimitry Andricdef PseudoLW : PseudoLoad<"lw">; 8690b57cec5SDimitry Andric 8700b57cec5SDimitry Andricdef PseudoSB : PseudoStore<"sb">; 8710b57cec5SDimitry Andricdef PseudoSH : PseudoStore<"sh">; 8720b57cec5SDimitry Andricdef PseudoSW : PseudoStore<"sw">; 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 8750b57cec5SDimitry Andricdef PseudoLWU : PseudoLoad<"lwu">; 8760b57cec5SDimitry Andricdef PseudoLD : PseudoLoad<"ld">; 8770b57cec5SDimitry Andricdef PseudoSD : PseudoStore<"sd">; 8780b57cec5SDimitry Andric} // Predicates = [IsRV64] 8790b57cec5SDimitry Andric 8804824e7fdSDimitry Andricdef : InstAlias<"li $rd, $imm", (ADDI GPR:$rd, X0, simm12:$imm)>; 8810b57cec5SDimitry Andricdef : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>; 8820b57cec5SDimitry Andricdef : InstAlias<"not $rd, $rs", (XORI GPR:$rd, GPR:$rs, -1)>; 8830b57cec5SDimitry Andricdef : InstAlias<"neg $rd, $rs", (SUB GPR:$rd, X0, GPR:$rs)>; 8840b57cec5SDimitry Andric 8850b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 8860b57cec5SDimitry Andricdef : InstAlias<"negw $rd, $rs", (SUBW GPR:$rd, X0, GPR:$rs)>; 8870b57cec5SDimitry Andricdef : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs, 0)>; 8880b57cec5SDimitry Andric} // Predicates = [IsRV64] 8890b57cec5SDimitry Andric 8900b57cec5SDimitry Andricdef : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs, 1)>; 8910b57cec5SDimitry Andricdef : InstAlias<"snez $rd, $rs", (SLTU GPR:$rd, X0, GPR:$rs)>; 8920b57cec5SDimitry Andricdef : InstAlias<"sltz $rd, $rs", (SLT GPR:$rd, GPR:$rs, X0)>; 8930b57cec5SDimitry Andricdef : InstAlias<"sgtz $rd, $rs", (SLT GPR:$rd, X0, GPR:$rs)>; 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric// sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu 8960b57cec5SDimitry Andric// form will always be printed. Therefore, set a zero weight. 8970b57cec5SDimitry Andricdef : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>; 8980b57cec5SDimitry Andricdef : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>; 8990b57cec5SDimitry Andric 9000b57cec5SDimitry Andricdef : InstAlias<"beqz $rs, $offset", 9010b57cec5SDimitry Andric (BEQ GPR:$rs, X0, simm13_lsb0:$offset)>; 9020b57cec5SDimitry Andricdef : InstAlias<"bnez $rs, $offset", 9030b57cec5SDimitry Andric (BNE GPR:$rs, X0, simm13_lsb0:$offset)>; 9040b57cec5SDimitry Andricdef : InstAlias<"blez $rs, $offset", 9050b57cec5SDimitry Andric (BGE X0, GPR:$rs, simm13_lsb0:$offset)>; 9060b57cec5SDimitry Andricdef : InstAlias<"bgez $rs, $offset", 9070b57cec5SDimitry Andric (BGE GPR:$rs, X0, simm13_lsb0:$offset)>; 9080b57cec5SDimitry Andricdef : InstAlias<"bltz $rs, $offset", 9090b57cec5SDimitry Andric (BLT GPR:$rs, X0, simm13_lsb0:$offset)>; 9100b57cec5SDimitry Andricdef : InstAlias<"bgtz $rs, $offset", 9110b57cec5SDimitry Andric (BLT X0, GPR:$rs, simm13_lsb0:$offset)>; 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric// Always output the canonical mnemonic for the pseudo branch instructions. 9140b57cec5SDimitry Andric// The GNU tools emit the canonical mnemonic for the branch pseudo instructions 9150b57cec5SDimitry Andric// as well (e.g. "bgt" will be recognised by the assembler but never printed by 9160b57cec5SDimitry Andric// objdump). Match this behaviour by setting a zero weight. 9170b57cec5SDimitry Andricdef : InstAlias<"bgt $rs, $rt, $offset", 9180b57cec5SDimitry Andric (BLT GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 9190b57cec5SDimitry Andricdef : InstAlias<"ble $rs, $rt, $offset", 9200b57cec5SDimitry Andric (BGE GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 9210b57cec5SDimitry Andricdef : InstAlias<"bgtu $rs, $rt, $offset", 9220b57cec5SDimitry Andric (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 9230b57cec5SDimitry Andricdef : InstAlias<"bleu $rs, $rt, $offset", 9240b57cec5SDimitry Andric (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 9250b57cec5SDimitry Andric 9260b57cec5SDimitry Andricdef : InstAlias<"j $offset", (JAL X0, simm21_lsb0_jal:$offset)>; 9270b57cec5SDimitry Andricdef : InstAlias<"jal $offset", (JAL X1, simm21_lsb0_jal:$offset)>; 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric// Non-zero offset aliases of "jalr" are the lowest weight, followed by the 9300b57cec5SDimitry Andric// two-register form, then the one-register forms and finally "ret". 9310b57cec5SDimitry Andricdef : InstAlias<"jr $rs", (JALR X0, GPR:$rs, 0), 3>; 9320b57cec5SDimitry Andricdef : InstAlias<"jr ${offset}(${rs})", (JALR X0, GPR:$rs, simm12:$offset)>; 9330b57cec5SDimitry Andricdef : InstAlias<"jalr $rs", (JALR X1, GPR:$rs, 0), 3>; 9340b57cec5SDimitry Andricdef : InstAlias<"jalr ${offset}(${rs})", (JALR X1, GPR:$rs, simm12:$offset)>; 9350b57cec5SDimitry Andricdef : InstAlias<"jalr $rd, $rs", (JALR GPR:$rd, GPR:$rs, 0), 2>; 9360b57cec5SDimitry Andricdef : InstAlias<"ret", (JALR X0, X1, 0), 4>; 9370b57cec5SDimitry Andric 9380b57cec5SDimitry Andric// Non-canonical forms for jump targets also accepted by the assembler. 9390b57cec5SDimitry Andricdef : InstAlias<"jr $rs, $offset", (JALR X0, GPR:$rs, simm12:$offset), 0>; 9400b57cec5SDimitry Andricdef : InstAlias<"jalr $rs, $offset", (JALR X1, GPR:$rs, simm12:$offset), 0>; 9410b57cec5SDimitry Andricdef : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12:$offset), 0>; 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andricdef : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw 9440b57cec5SDimitry Andric 94581ad6265SDimitry Andriclet Predicates = [HasStdExtZihintpause] in 94681ad6265SDimitry Andricdef : InstAlias<"pause", (FENCE 0x1, 0x0)>; // 0x1 == w 94781ad6265SDimitry Andric 9480b57cec5SDimitry Andricdef : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>; 9490b57cec5SDimitry Andricdef : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, CYCLE.Encoding, X0)>; 9500b57cec5SDimitry Andricdef : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, TIME.Encoding, X0)>; 9510b57cec5SDimitry Andric 9520b57cec5SDimitry Andriclet Predicates = [IsRV32] in { 9530b57cec5SDimitry Andricdef : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, INSTRETH.Encoding, X0)>; 9540b57cec5SDimitry Andricdef : InstAlias<"rdcycleh $rd", (CSRRS GPR:$rd, CYCLEH.Encoding, X0)>; 9550b57cec5SDimitry Andricdef : InstAlias<"rdtimeh $rd", (CSRRS GPR:$rd, TIMEH.Encoding, X0)>; 9560b57cec5SDimitry Andric} // Predicates = [IsRV32] 9570b57cec5SDimitry Andric 9580b57cec5SDimitry Andricdef : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, csr_sysreg:$csr, X0)>; 9590b57cec5SDimitry Andricdef : InstAlias<"csrw $csr, $rs", (CSRRW X0, csr_sysreg:$csr, GPR:$rs)>; 9600b57cec5SDimitry Andricdef : InstAlias<"csrs $csr, $rs", (CSRRS X0, csr_sysreg:$csr, GPR:$rs)>; 9610b57cec5SDimitry Andricdef : InstAlias<"csrc $csr, $rs", (CSRRC X0, csr_sysreg:$csr, GPR:$rs)>; 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andricdef : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>; 9640b57cec5SDimitry Andricdef : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>; 9650b57cec5SDimitry Andricdef : InstAlias<"csrci $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>; 9660b57cec5SDimitry Andric 9670b57cec5SDimitry Andriclet EmitPriority = 0 in { 9680b57cec5SDimitry Andricdef : InstAlias<"csrw $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>; 9690b57cec5SDimitry Andricdef : InstAlias<"csrs $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>; 9700b57cec5SDimitry Andricdef : InstAlias<"csrc $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>; 9710b57cec5SDimitry Andric 9720b57cec5SDimitry Andricdef : InstAlias<"csrrw $rd, $csr, $imm", (CSRRWI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 9730b57cec5SDimitry Andricdef : InstAlias<"csrrs $rd, $csr, $imm", (CSRRSI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 9740b57cec5SDimitry Andricdef : InstAlias<"csrrc $rd, $csr, $imm", (CSRRCI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 9750b57cec5SDimitry Andric} 9760b57cec5SDimitry Andric 9770b57cec5SDimitry Andricdef : InstAlias<"sfence.vma", (SFENCE_VMA X0, X0)>; 9780b57cec5SDimitry Andricdef : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>; 9790b57cec5SDimitry Andric 98081ad6265SDimitry Andricdef : InstAlias<"hfence.gvma", (HFENCE_GVMA X0, X0)>; 98181ad6265SDimitry Andricdef : InstAlias<"hfence.gvma $rs", (HFENCE_GVMA GPR:$rs, X0)>; 98281ad6265SDimitry Andric 98381ad6265SDimitry Andricdef : InstAlias<"hfence.vvma", (HFENCE_VVMA X0, X0)>; 98481ad6265SDimitry Andricdef : InstAlias<"hfence.vvma $rs", (HFENCE_VVMA GPR:$rs, X0)>; 98581ad6265SDimitry Andric 986bdd1243dSDimitry Andriclet Predicates = [HasStdExtZihintntl] in { 987bdd1243dSDimitry Andric def : InstAlias<"ntl.p1", (ADD X0, X0, X2)>; 988bdd1243dSDimitry Andric def : InstAlias<"ntl.pall", (ADD X0, X0, X3)>; 989bdd1243dSDimitry Andric def : InstAlias<"ntl.s1", (ADD X0, X0, X4)>; 990bdd1243dSDimitry Andric def : InstAlias<"ntl.all", (ADD X0, X0, X5)>; 991bdd1243dSDimitry Andric} // Predicates = [HasStdExtZihintntl] 992bdd1243dSDimitry Andric 9930b57cec5SDimitry Andriclet EmitPriority = 0 in { 9940b57cec5SDimitry Andricdef : InstAlias<"lb $rd, (${rs1})", 9950b57cec5SDimitry Andric (LB GPR:$rd, GPR:$rs1, 0)>; 9960b57cec5SDimitry Andricdef : InstAlias<"lh $rd, (${rs1})", 9970b57cec5SDimitry Andric (LH GPR:$rd, GPR:$rs1, 0)>; 9980b57cec5SDimitry Andricdef : InstAlias<"lw $rd, (${rs1})", 9990b57cec5SDimitry Andric (LW GPR:$rd, GPR:$rs1, 0)>; 10000b57cec5SDimitry Andricdef : InstAlias<"lbu $rd, (${rs1})", 10010b57cec5SDimitry Andric (LBU GPR:$rd, GPR:$rs1, 0)>; 10020b57cec5SDimitry Andricdef : InstAlias<"lhu $rd, (${rs1})", 10030b57cec5SDimitry Andric (LHU GPR:$rd, GPR:$rs1, 0)>; 10040b57cec5SDimitry Andric 10050b57cec5SDimitry Andricdef : InstAlias<"sb $rs2, (${rs1})", 10060b57cec5SDimitry Andric (SB GPR:$rs2, GPR:$rs1, 0)>; 10070b57cec5SDimitry Andricdef : InstAlias<"sh $rs2, (${rs1})", 10080b57cec5SDimitry Andric (SH GPR:$rs2, GPR:$rs1, 0)>; 10090b57cec5SDimitry Andricdef : InstAlias<"sw $rs2, (${rs1})", 10100b57cec5SDimitry Andric (SW GPR:$rs2, GPR:$rs1, 0)>; 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andricdef : InstAlias<"add $rd, $rs1, $imm12", 10130b57cec5SDimitry Andric (ADDI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 10140b57cec5SDimitry Andricdef : InstAlias<"and $rd, $rs1, $imm12", 10150b57cec5SDimitry Andric (ANDI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 10160b57cec5SDimitry Andricdef : InstAlias<"xor $rd, $rs1, $imm12", 10170b57cec5SDimitry Andric (XORI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 10180b57cec5SDimitry Andricdef : InstAlias<"or $rd, $rs1, $imm12", 10190b57cec5SDimitry Andric (ORI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 10200b57cec5SDimitry Andricdef : InstAlias<"sll $rd, $rs1, $shamt", 10210b57cec5SDimitry Andric (SLLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 10220b57cec5SDimitry Andricdef : InstAlias<"srl $rd, $rs1, $shamt", 10230b57cec5SDimitry Andric (SRLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 10240b57cec5SDimitry Andricdef : InstAlias<"sra $rd, $rs1, $shamt", 10250b57cec5SDimitry Andric (SRAI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 10260b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 10270b57cec5SDimitry Andricdef : InstAlias<"lwu $rd, (${rs1})", 10280b57cec5SDimitry Andric (LWU GPR:$rd, GPR:$rs1, 0)>; 10290b57cec5SDimitry Andricdef : InstAlias<"ld $rd, (${rs1})", 10300b57cec5SDimitry Andric (LD GPR:$rd, GPR:$rs1, 0)>; 10310b57cec5SDimitry Andricdef : InstAlias<"sd $rs2, (${rs1})", 10320b57cec5SDimitry Andric (SD GPR:$rs2, GPR:$rs1, 0)>; 10330b57cec5SDimitry Andric 10340b57cec5SDimitry Andricdef : InstAlias<"addw $rd, $rs1, $imm12", 10350b57cec5SDimitry Andric (ADDIW GPR:$rd, GPR:$rs1, simm12:$imm12)>; 10360b57cec5SDimitry Andricdef : InstAlias<"sllw $rd, $rs1, $shamt", 10370b57cec5SDimitry Andric (SLLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 10380b57cec5SDimitry Andricdef : InstAlias<"srlw $rd, $rs1, $shamt", 10390b57cec5SDimitry Andric (SRLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 10400b57cec5SDimitry Andricdef : InstAlias<"sraw $rd, $rs1, $shamt", 10410b57cec5SDimitry Andric (SRAIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 10420b57cec5SDimitry Andric} // Predicates = [IsRV64] 10430b57cec5SDimitry Andricdef : InstAlias<"slt $rd, $rs1, $imm12", 10440b57cec5SDimitry Andric (SLTI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 10450b57cec5SDimitry Andricdef : InstAlias<"sltu $rd, $rs1, $imm12", 10460b57cec5SDimitry Andric (SLTIU GPR:$rd, GPR:$rs1, simm12:$imm12)>; 10470b57cec5SDimitry Andric} 10480b57cec5SDimitry Andric 10490b57cec5SDimitry Andricdef : MnemonicAlias<"move", "mv">; 10500b57cec5SDimitry Andric 10510b57cec5SDimitry Andric// The SCALL and SBREAK instructions wererenamed to ECALL and EBREAK in 10520b57cec5SDimitry Andric// version 2.1 of the user-level ISA. Like the GNU toolchain, we still accept 10530b57cec5SDimitry Andric// the old name for backwards compatibility. 10540b57cec5SDimitry Andricdef : MnemonicAlias<"scall", "ecall">; 10550b57cec5SDimitry Andricdef : MnemonicAlias<"sbreak", "ebreak">; 10560b57cec5SDimitry Andric 1057e8d8bef9SDimitry Andric// This alias was added to the spec in December 2020. Don't print it by default 1058e8d8bef9SDimitry Andric// to allow assembly we print to be compatible with versions of GNU assembler 1059e8d8bef9SDimitry Andric// that don't support this alias. 1060e8d8bef9SDimitry Andricdef : InstAlias<"zext.b $rd, $rs", (ANDI GPR:$rd, GPR:$rs, 0xFF), 0>; 1061e8d8bef9SDimitry Andric 10625f757f3fSDimitry Andriclet Predicates = [HasStdExtZicfilp] in { 10635f757f3fSDimitry Andricdef : InstAlias<"lpad $imm20", (AUIPC X0, uimm20:$imm20)>; 10645f757f3fSDimitry Andric} 10655f757f3fSDimitry Andric 10660b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 1067349cc55cSDimitry Andric// .insn directive instructions 1068349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 1069349cc55cSDimitry Andric 107006c3fb27SDimitry Andricdef AnyRegOperand : AsmOperandClass { 107106c3fb27SDimitry Andric let Name = "AnyRegOperand"; 107206c3fb27SDimitry Andric let RenderMethod = "addRegOperands"; 107306c3fb27SDimitry Andric let PredicateMethod = "isAnyReg"; 107406c3fb27SDimitry Andric} 107506c3fb27SDimitry Andric 107606c3fb27SDimitry Andricdef AnyReg : Operand<XLenVT> { 107706c3fb27SDimitry Andric let OperandType = "OPERAND_REGISTER"; 107806c3fb27SDimitry Andric let ParserMatchClass = AnyRegOperand; 107906c3fb27SDimitry Andric} 108006c3fb27SDimitry Andric 1081349cc55cSDimitry Andric// isCodeGenOnly = 1 to hide them from the tablegened assembly parser. 1082349cc55cSDimitry Andriclet isCodeGenOnly = 1, hasSideEffects = 1, mayLoad = 1, mayStore = 1, 1083349cc55cSDimitry Andric hasNoSchedulingInfo = 1 in { 10840eae32dcSDimitry Andricdef InsnR : DirectiveInsnR<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1085349cc55cSDimitry Andric uimm7:$funct7, AnyReg:$rs1, 1086349cc55cSDimitry Andric AnyReg:$rs2), 1087349cc55cSDimitry Andric "$opcode, $funct3, $funct7, $rd, $rs1, $rs2">; 10880eae32dcSDimitry Andricdef InsnR4 : DirectiveInsnR4<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1089349cc55cSDimitry Andric uimm3:$funct3, 1090349cc55cSDimitry Andric uimm2:$funct2, 1091349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2, 1092349cc55cSDimitry Andric AnyReg:$rs3), 1093349cc55cSDimitry Andric "$opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3">; 10940eae32dcSDimitry Andricdef InsnI : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1095349cc55cSDimitry Andric AnyReg:$rs1, simm12:$imm12), 1096349cc55cSDimitry Andric "$opcode, $funct3, $rd, $rs1, $imm12">; 10970eae32dcSDimitry Andricdef InsnI_Mem : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1098349cc55cSDimitry Andric uimm3:$funct3, 1099349cc55cSDimitry Andric AnyReg:$rs1, 1100349cc55cSDimitry Andric simm12:$imm12), 1101349cc55cSDimitry Andric "$opcode, $funct3, $rd, ${imm12}(${rs1})">; 11020eae32dcSDimitry Andricdef InsnB : DirectiveInsnB<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1103349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2, 1104349cc55cSDimitry Andric simm13_lsb0:$imm12), 1105349cc55cSDimitry Andric "$opcode, $funct3, $rs1, $rs2, $imm12">; 11060eae32dcSDimitry Andricdef InsnU : DirectiveInsnU<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1107349cc55cSDimitry Andric uimm20_lui:$imm20), 1108349cc55cSDimitry Andric "$opcode, $rd, $imm20">; 11090eae32dcSDimitry Andricdef InsnJ : DirectiveInsnJ<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1110349cc55cSDimitry Andric simm21_lsb0_jal:$imm20), 1111349cc55cSDimitry Andric "$opcode, $rd, $imm20">; 11120eae32dcSDimitry Andricdef InsnS : DirectiveInsnS<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1113349cc55cSDimitry Andric AnyReg:$rs2, AnyReg:$rs1, 1114349cc55cSDimitry Andric simm12:$imm12), 1115349cc55cSDimitry Andric "$opcode, $funct3, $rs2, ${imm12}(${rs1})">; 1116349cc55cSDimitry Andric} 1117349cc55cSDimitry Andric 1118349cc55cSDimitry Andric// Use InstAliases to match these so that we can combine the insn and format 1119349cc55cSDimitry Andric// into a mnemonic to use as the key for the tablegened asm matcher table. The 1120349cc55cSDimitry Andric// parser will take care of creating these fake mnemonics and will only do it 1121349cc55cSDimitry Andric// for known formats. 1122349cc55cSDimitry Andriclet EmitPriority = 0 in { 1123349cc55cSDimitry Andricdef : InstAlias<".insn_r $opcode, $funct3, $funct7, $rd, $rs1, $rs2", 11240eae32dcSDimitry Andric (InsnR AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm7:$funct7, 1125349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2)>; 1126349cc55cSDimitry Andric// Accept 4 register form of ".insn r" as alias for ".insn r4". 1127349cc55cSDimitry Andricdef : InstAlias<".insn_r $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3", 11280eae32dcSDimitry Andric (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2, 1129349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>; 1130349cc55cSDimitry Andricdef : InstAlias<".insn_r4 $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3", 11310eae32dcSDimitry Andric (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2, 1132349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>; 1133349cc55cSDimitry Andricdef : InstAlias<".insn_i $opcode, $funct3, $rd, $rs1, $imm12", 11340eae32dcSDimitry Andric (InsnI AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 1135349cc55cSDimitry Andric simm12:$imm12)>; 1136349cc55cSDimitry Andricdef : InstAlias<".insn_i $opcode, $funct3, $rd, ${imm12}(${rs1})", 11370eae32dcSDimitry Andric (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, 1138349cc55cSDimitry Andric AnyReg:$rs1, simm12:$imm12)>; 1139349cc55cSDimitry Andricdef : InstAlias<".insn_b $opcode, $funct3, $rs1, $rs2, $imm12", 11400eae32dcSDimitry Andric (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 1141349cc55cSDimitry Andric AnyReg:$rs2, simm13_lsb0:$imm12)>; 1142349cc55cSDimitry Andric// Accept sb as an alias for b. 1143349cc55cSDimitry Andricdef : InstAlias<".insn_sb $opcode, $funct3, $rs1, $rs2, $imm12", 11440eae32dcSDimitry Andric (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 1145349cc55cSDimitry Andric AnyReg:$rs2, simm13_lsb0:$imm12)>; 1146349cc55cSDimitry Andricdef : InstAlias<".insn_u $opcode, $rd, $imm20", 11470eae32dcSDimitry Andric (InsnU AnyReg:$rd, uimm7_opcode:$opcode, uimm20_lui:$imm20)>; 1148349cc55cSDimitry Andricdef : InstAlias<".insn_j $opcode, $rd, $imm20", 11490eae32dcSDimitry Andric (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>; 1150349cc55cSDimitry Andric// Accept uj as an alias for j. 1151349cc55cSDimitry Andricdef : InstAlias<".insn_uj $opcode, $rd, $imm20", 11520eae32dcSDimitry Andric (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>; 1153349cc55cSDimitry Andricdef : InstAlias<".insn_s $opcode, $funct3, $rs2, ${imm12}(${rs1})", 11540eae32dcSDimitry Andric (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2, 1155349cc55cSDimitry Andric AnyReg:$rs1, simm12:$imm12)>; 1156349cc55cSDimitry Andric} 1157349cc55cSDimitry Andric 1158349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 11590b57cec5SDimitry Andric// Pseudo-instructions and codegen patterns 11600b57cec5SDimitry Andric// 11610b57cec5SDimitry Andric// Naming convention: For 'generic' pattern classes, we use the naming 11620b57cec5SDimitry Andric// convention PatTy1Ty2. For pattern classes which offer a more complex 11635ffd83dbSDimitry Andric// expansion, prefix the class name, e.g. BccPat. 11640b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 11650b57cec5SDimitry Andric 11660b57cec5SDimitry Andric/// Generic pattern classes 11670b57cec5SDimitry Andric 116806c3fb27SDimitry Andricclass PatGpr<SDPatternOperator OpNode, RVInst Inst, ValueType vt = XLenVT> 116906c3fb27SDimitry Andric : Pat<(vt (OpNode (vt GPR:$rs1))), (Inst GPR:$rs1)>; 11705f757f3fSDimitry Andricclass PatGprGpr<SDPatternOperator OpNode, RVInst Inst, ValueType vt1 = XLenVT, 11715f757f3fSDimitry Andric ValueType vt2 = XLenVT> 11725f757f3fSDimitry Andric : Pat<(vt1 (OpNode (vt1 GPR:$rs1), (vt2 GPR:$rs2))), (Inst GPR:$rs1, GPR:$rs2)>; 1173fe6060f1SDimitry Andric 11745f757f3fSDimitry Andricclass PatGprImm<SDPatternOperator OpNode, RVInst Inst, ImmLeaf ImmType, 11755f757f3fSDimitry Andric ValueType vt = XLenVT> 11765f757f3fSDimitry Andric : Pat<(vt (OpNode (vt GPR:$rs1), ImmType:$imm)), 1177fe6060f1SDimitry Andric (Inst GPR:$rs1, ImmType:$imm)>; 11780b57cec5SDimitry Andricclass PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst> 1179fe6060f1SDimitry Andric : PatGprImm<OpNode, Inst, simm12>; 11800b57cec5SDimitry Andricclass PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst> 1181fe6060f1SDimitry Andric : PatGprImm<OpNode, Inst, uimmlog2xlen>; 11820b57cec5SDimitry Andric 11830b57cec5SDimitry Andric/// Predicates 11840b57cec5SDimitry Andric 11850b57cec5SDimitry Andricdef assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{ 1186e8d8bef9SDimitry Andric return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32); 11870b57cec5SDimitry Andric}]>; 118806c3fb27SDimitry Andricdef sexti16 : ComplexPattern<XLenVT, 1, "selectSExtBits<16>">; 118906c3fb27SDimitry Andricdef sexti32 : ComplexPattern<i64, 1, "selectSExtBits<32>">; 11900b57cec5SDimitry Andricdef assertzexti32 : PatFrag<(ops node:$src), (assertzext node:$src), [{ 1191e8d8bef9SDimitry Andric return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32); 11920b57cec5SDimitry Andric}]>; 1193bdd1243dSDimitry Andricdef zexti32 : ComplexPattern<i64, 1, "selectZExtBits<32>">; 1194bdd1243dSDimitry Andricdef zexti16 : ComplexPattern<XLenVT, 1, "selectZExtBits<16>">; 11955f757f3fSDimitry Andricdef zexti16i32 : ComplexPattern<i32, 1, "selectZExtBits<16>">; 1196bdd1243dSDimitry Andricdef zexti8 : ComplexPattern<XLenVT, 1, "selectZExtBits<8>">; 11975f757f3fSDimitry Andricdef zexti8i32 : ComplexPattern<i32, 1, "selectZExtBits<8>">; 11980b57cec5SDimitry Andric 119906c3fb27SDimitry Andricdef ext : PatFrags<(ops node:$A), [(sext node:$A), (zext node:$A)]>; 120006c3fb27SDimitry Andric 120181ad6265SDimitry Andricclass binop_oneuse<SDPatternOperator operator> 120281ad6265SDimitry Andric : PatFrag<(ops node:$A, node:$B), 120381ad6265SDimitry Andric (operator node:$A, node:$B), [{ 1204fe6060f1SDimitry Andric return N->hasOneUse(); 1205e8d8bef9SDimitry Andric}]>; 1206e8d8bef9SDimitry Andric 1207bdd1243dSDimitry Andricdef and_oneuse : binop_oneuse<and>; 120881ad6265SDimitry Andricdef mul_oneuse : binop_oneuse<mul>; 1209e8d8bef9SDimitry Andric 1210349cc55cSDimitry Andricdef mul_const_oneuse : PatFrag<(ops node:$A, node:$B), 1211349cc55cSDimitry Andric (mul node:$A, node:$B), [{ 1212349cc55cSDimitry Andric if (auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1))) 121306c3fb27SDimitry Andric return N1C->hasOneUse(); 1214349cc55cSDimitry Andric return false; 1215349cc55cSDimitry Andric}]>; 1216349cc55cSDimitry Andric 121781ad6265SDimitry Andricclass unop_oneuse<SDPatternOperator operator> 121881ad6265SDimitry Andric : PatFrag<(ops node:$A), 121981ad6265SDimitry Andric (operator node:$A), [{ 122004eeddc0SDimitry Andric return N->hasOneUse(); 122104eeddc0SDimitry Andric}]>; 122204eeddc0SDimitry Andric 122381ad6265SDimitry Andricdef sext_oneuse : unop_oneuse<sext>; 122481ad6265SDimitry Andricdef zext_oneuse : unop_oneuse<zext>; 122581ad6265SDimitry Andricdef anyext_oneuse : unop_oneuse<anyext>; 122606c3fb27SDimitry Andricdef ext_oneuse : unop_oneuse<ext>; 122781ad6265SDimitry Andricdef fpext_oneuse : unop_oneuse<any_fpextend>; 122804eeddc0SDimitry Andric 12295f757f3fSDimitry Andricdef 33signbits_node : PatLeaf<(i64 GPR:$src), [{ 12305f757f3fSDimitry Andric return CurDAG->ComputeNumSignBits(SDValue(N, 0)) > 32; 12315f757f3fSDimitry Andric}]>; 12325f757f3fSDimitry Andric 12330b57cec5SDimitry Andric/// Simple arithmetic operations 12340b57cec5SDimitry Andric 12350b57cec5SDimitry Andricdef : PatGprGpr<add, ADD>; 12360b57cec5SDimitry Andricdef : PatGprSimm12<add, ADDI>; 12370b57cec5SDimitry Andricdef : PatGprGpr<sub, SUB>; 12380b57cec5SDimitry Andricdef : PatGprGpr<or, OR>; 12390b57cec5SDimitry Andricdef : PatGprSimm12<or, ORI>; 12400b57cec5SDimitry Andricdef : PatGprGpr<and, AND>; 12410b57cec5SDimitry Andricdef : PatGprSimm12<and, ANDI>; 12420b57cec5SDimitry Andricdef : PatGprGpr<xor, XOR>; 12430b57cec5SDimitry Andricdef : PatGprSimm12<xor, XORI>; 12440b57cec5SDimitry Andricdef : PatGprUimmLog2XLen<shl, SLLI>; 12450b57cec5SDimitry Andricdef : PatGprUimmLog2XLen<srl, SRLI>; 12460b57cec5SDimitry Andricdef : PatGprUimmLog2XLen<sra, SRAI>; 12470b57cec5SDimitry Andric 1248bdd1243dSDimitry Andric// Select 'or' as ADDI if the immediate bits are known to be 0 in $rs1. This 1249bdd1243dSDimitry Andric// can improve compressibility. 1250bdd1243dSDimitry Andricdef or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{ 1251bdd1243dSDimitry Andric KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0); 1252bdd1243dSDimitry Andric KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0); 1253bdd1243dSDimitry Andric return KnownBits::haveNoCommonBitsSet(Known0, Known1); 1254bdd1243dSDimitry Andric}]>; 1255bdd1243dSDimitry Andricdef : PatGprSimm12<or_is_add, ADDI>; 1256bdd1243dSDimitry Andric 1257bdd1243dSDimitry Andric// negate of low bit can be done via two (compressible) shifts. The negate 1258bdd1243dSDimitry Andric// is never compressible since rs1 and rd can't be the same register. 1259bdd1243dSDimitry Andricdef : Pat<(XLenVT (sub 0, (and_oneuse GPR:$rs, 1))), 1260bdd1243dSDimitry Andric (SRAI (SLLI $rs, (ImmSubFromXLen (XLenVT 1))), 1261bdd1243dSDimitry Andric (ImmSubFromXLen (XLenVT 1)))>; 1262bdd1243dSDimitry Andric 126381ad6265SDimitry Andric// AND with leading/trailing ones mask exceeding simm32/simm12. 126481ad6265SDimitry Andricdef : Pat<(i64 (and GPR:$rs, LeadingOnesMask:$mask)), 126581ad6265SDimitry Andric (SLLI (SRLI $rs, LeadingOnesMask:$mask), LeadingOnesMask:$mask)>; 126604eeddc0SDimitry Andricdef : Pat<(XLenVT (and GPR:$rs, TrailingOnesMask:$mask)), 126704eeddc0SDimitry Andric (SRLI (SLLI $rs, TrailingOnesMask:$mask), TrailingOnesMask:$mask)>; 126804eeddc0SDimitry Andric 12690b57cec5SDimitry Andric// Match both a plain shift and one where the shift amount is masked (this is 12700b57cec5SDimitry Andric// typically introduced when the legalizer promotes the shift amount and 12710b57cec5SDimitry Andric// zero-extends it). For RISC-V, the mask is unnecessary as shifts in the base 12720b57cec5SDimitry Andric// ISA only read the least significant 5 bits (RV32I) or 6 bits (RV64I). 1273fe6060f1SDimitry Andricdef shiftMaskXLen : ComplexPattern<XLenVT, 1, "selectShiftMaskXLen", [], [], 0>; 1274fe6060f1SDimitry Andricdef shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>; 1275fe6060f1SDimitry Andric 12760b57cec5SDimitry Andricclass shiftop<SDPatternOperator operator> 1277fe6060f1SDimitry Andric : PatFrag<(ops node:$val, node:$count), 1278fe6060f1SDimitry Andric (operator node:$val, (XLenVT (shiftMaskXLen node:$count)))>; 1279e8d8bef9SDimitry Andricclass shiftopw<SDPatternOperator operator> 1280fe6060f1SDimitry Andric : PatFrag<(ops node:$val, node:$count), 1281fe6060f1SDimitry Andric (operator node:$val, (i64 (shiftMask32 node:$count)))>; 12820b57cec5SDimitry Andric 12830b57cec5SDimitry Andricdef : PatGprGpr<shiftop<shl>, SLL>; 12840b57cec5SDimitry Andricdef : PatGprGpr<shiftop<srl>, SRL>; 12850b57cec5SDimitry Andricdef : PatGprGpr<shiftop<sra>, SRA>; 12860b57cec5SDimitry Andric 12870b57cec5SDimitry Andric// This is a special case of the ADD instruction used to facilitate the use of a 12880b57cec5SDimitry Andric// fourth operand to emit a relocation on a symbol relating to this instruction. 12890b57cec5SDimitry Andric// The relocation does not affect any bits of the instruction itself but is used 12900b57cec5SDimitry Andric// as a hint to the linker. 12910b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in 12920b57cec5SDimitry Andricdef PseudoAddTPRel : Pseudo<(outs GPR:$rd), 12930b57cec5SDimitry Andric (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [], 12940b57cec5SDimitry Andric "add", "$rd, $rs1, $rs2, $src">; 12950b57cec5SDimitry Andric 12960b57cec5SDimitry Andric/// FrameIndex calculations 12970b57cec5SDimitry Andric 129806c3fb27SDimitry Andricdef : Pat<(FrameAddrRegImm (iPTR GPR:$rs1), simm12:$imm12), 129981ad6265SDimitry Andric (ADDI GPR:$rs1, simm12:$imm12)>; 130081ad6265SDimitry Andric 130181ad6265SDimitry Andric/// HI and ADD_LO address nodes. 130281ad6265SDimitry Andric 130381ad6265SDimitry Andricdef : Pat<(riscv_hi tglobaladdr:$in), (LUI tglobaladdr:$in)>; 130481ad6265SDimitry Andricdef : Pat<(riscv_hi tblockaddress:$in), (LUI tblockaddress:$in)>; 130581ad6265SDimitry Andricdef : Pat<(riscv_hi tjumptable:$in), (LUI tjumptable:$in)>; 130681ad6265SDimitry Andricdef : Pat<(riscv_hi tconstpool:$in), (LUI tconstpool:$in)>; 130781ad6265SDimitry Andric 130881ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$hi, tglobaladdr:$lo), 130981ad6265SDimitry Andric (ADDI GPR:$hi, tglobaladdr:$lo)>; 131081ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$hi, tblockaddress:$lo), 131181ad6265SDimitry Andric (ADDI GPR:$hi, tblockaddress:$lo)>; 131281ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$hi, tjumptable:$lo), 131381ad6265SDimitry Andric (ADDI GPR:$hi, tjumptable:$lo)>; 131481ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$hi, tconstpool:$lo), 131581ad6265SDimitry Andric (ADDI GPR:$hi, tconstpool:$lo)>; 131681ad6265SDimitry Andric 131781ad6265SDimitry Andric/// TLS address nodes. 131881ad6265SDimitry Andric 131981ad6265SDimitry Andricdef : Pat<(riscv_hi tglobaltlsaddr:$in), (LUI tglobaltlsaddr:$in)>; 132081ad6265SDimitry Andricdef : Pat<(riscv_add_tprel GPR:$rs1, GPR:$rs2, tglobaltlsaddr:$src), 132181ad6265SDimitry Andric (PseudoAddTPRel GPR:$rs1, GPR:$rs2, tglobaltlsaddr:$src)>; 132281ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$src, tglobaltlsaddr:$lo), 132381ad6265SDimitry Andric (ADDI GPR:$src, tglobaltlsaddr:$lo)>; 13240b57cec5SDimitry Andric 13250b57cec5SDimitry Andric/// Setcc 13260b57cec5SDimitry Andric 13270b57cec5SDimitry Andricdef : PatGprGpr<setlt, SLT>; 13280b57cec5SDimitry Andricdef : PatGprSimm12<setlt, SLTI>; 13290b57cec5SDimitry Andricdef : PatGprGpr<setult, SLTU>; 13300b57cec5SDimitry Andricdef : PatGprSimm12<setult, SLTIU>; 13310b57cec5SDimitry Andric 133206c3fb27SDimitry Andric// RISC-V doesn't have general instructions for integer setne/seteq, but we can 133306c3fb27SDimitry Andric// check for equality with 0. These ComplexPatterns rewrite the setne/seteq into 133406c3fb27SDimitry Andric// something that can be compared with 0. 133506c3fb27SDimitry Andric// These ComplexPatterns must be used in pairs. 133606c3fb27SDimitry Andricdef riscv_setne : ComplexPattern<XLenVT, 1, "selectSETNE", [setcc]>; 133706c3fb27SDimitry Andricdef riscv_seteq : ComplexPattern<XLenVT, 1, "selectSETEQ", [setcc]>; 133806c3fb27SDimitry Andric 13390b57cec5SDimitry Andric// Define pattern expansions for setcc operations that aren't directly 13400b57cec5SDimitry Andric// handled by a RISC-V instruction. 134106c3fb27SDimitry Andricdef : Pat<(riscv_seteq (XLenVT GPR:$rs1)), (SLTIU GPR:$rs1, 1)>; 134206c3fb27SDimitry Andricdef : Pat<(riscv_setne (XLenVT GPR:$rs1)), (SLTU (XLenVT X0), GPR:$rs1)>; 134306c3fb27SDimitry Andricdef : Pat<(XLenVT (setne (XLenVT GPR:$rs1), -1)), (SLTIU GPR:$rs1, -1)>; 1344fcaf7f86SDimitry Andric 1345349cc55cSDimitry Andricdef IntCCtoRISCVCC : SDNodeXForm<riscv_selectcc, [{ 1346349cc55cSDimitry Andric ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get(); 1347349cc55cSDimitry Andric RISCVCC::CondCode BrCC = getRISCVCCForIntCC(CC); 1348349cc55cSDimitry Andric return CurDAG->getTargetConstant(BrCC, SDLoc(N), Subtarget->getXLenVT()); 1349349cc55cSDimitry Andric}]>; 1350349cc55cSDimitry Andric 1351349cc55cSDimitry Andricdef riscv_selectcc_frag : PatFrag<(ops node:$lhs, node:$rhs, node:$cc, 1352349cc55cSDimitry Andric node:$truev, node:$falsev), 1353349cc55cSDimitry Andric (riscv_selectcc node:$lhs, node:$rhs, 1354349cc55cSDimitry Andric node:$cc, node:$truev, 1355349cc55cSDimitry Andric node:$falsev), [{}], 1356349cc55cSDimitry Andric IntCCtoRISCVCC>; 1357349cc55cSDimitry Andric 1358bdd1243dSDimitry Andriclet Predicates = [HasShortForwardBranchOpt], isSelect = 1, 1359bdd1243dSDimitry Andric Constraints = "$dst = $falsev", isCommutable = 1, Size = 8 in { 1360bdd1243dSDimitry Andric// This instruction moves $truev to $dst when the condition is true. It will 1361bdd1243dSDimitry Andric// be expanded to control flow in RISCVExpandPseudoInsts. 1362bdd1243dSDimitry Andricdef PseudoCCMOVGPR : Pseudo<(outs GPR:$dst), 1363bdd1243dSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 1364bdd1243dSDimitry Andric GPR:$falsev, GPR:$truev), 1365bdd1243dSDimitry Andric [(set GPR:$dst, 136606c3fb27SDimitry Andric (riscv_selectcc_frag:$cc (XLenVT GPR:$lhs), 136706c3fb27SDimitry Andric GPR:$rhs, cond, 136806c3fb27SDimitry Andric (XLenVT GPR:$truev), 1369bdd1243dSDimitry Andric GPR:$falsev))]>, 137006c3fb27SDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, 137106c3fb27SDimitry Andric ReadSFBALU, ReadSFBALU]>; 1372bdd1243dSDimitry Andric} 1373bdd1243dSDimitry Andric 13741db9f3b2SDimitry Andric// This should always expand to a branch+c.mv so the size is 6 or 4 if the 13751db9f3b2SDimitry Andric// branch is compressible. 13761db9f3b2SDimitry Andriclet Predicates = [HasConditionalMoveFusion, NoShortForwardBranchOpt], 13771db9f3b2SDimitry Andric Constraints = "$dst = $falsev", isCommutable = 1, Size = 6 in { 13781db9f3b2SDimitry Andric// This instruction moves $truev to $dst when the condition is true. It will 13791db9f3b2SDimitry Andric// be expanded to control flow in RISCVExpandPseudoInsts. 13801db9f3b2SDimitry Andric// We use GPRNoX0 because c.mv cannot encode X0. 13811db9f3b2SDimitry Andricdef PseudoCCMOVGPRNoX0 : Pseudo<(outs GPRNoX0:$dst), 13821db9f3b2SDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 13831db9f3b2SDimitry Andric GPRNoX0:$falsev, GPRNoX0:$truev), 13841db9f3b2SDimitry Andric [(set GPRNoX0:$dst, 13851db9f3b2SDimitry Andric (riscv_selectcc_frag:$cc (XLenVT GPR:$lhs), 13861db9f3b2SDimitry Andric (XLenVT GPR:$rhs), 13871db9f3b2SDimitry Andric cond, (XLenVT GPRNoX0:$truev), 13881db9f3b2SDimitry Andric (XLenVT GPRNoX0:$falsev)))]>, 13891db9f3b2SDimitry Andric Sched<[]>; 13901db9f3b2SDimitry Andric} 13911db9f3b2SDimitry Andric 1392bdd1243dSDimitry Andric// Conditional binops, that updates update $dst to (op rs1, rs2) when condition 1393bdd1243dSDimitry Andric// is true. Returns $falsev otherwise. Selected by optimizeSelect. 1394bdd1243dSDimitry Andric// TODO: Can we use DefaultOperands on the regular binop to accomplish this more 1395bdd1243dSDimitry Andric// like how ARM does predication? 1396bdd1243dSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, 1397bdd1243dSDimitry Andric Constraints = "$dst = $falsev" in { 1398bdd1243dSDimitry Andricdef PseudoCCADD : Pseudo<(outs GPR:$dst), 1399bdd1243dSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 1400bdd1243dSDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 140106c3fb27SDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, 140206c3fb27SDimitry Andric ReadSFBALU, ReadSFBALU, ReadSFBALU]>; 1403bdd1243dSDimitry Andricdef PseudoCCSUB : Pseudo<(outs GPR:$dst), 1404bdd1243dSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 1405bdd1243dSDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 140606c3fb27SDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, 140706c3fb27SDimitry Andric ReadSFBALU, ReadSFBALU, ReadSFBALU]>; 14085f757f3fSDimitry Andricdef PseudoCCSLL : Pseudo<(outs GPR:$dst), 14095f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 14105f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 14115f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 14125f757f3fSDimitry Andric ReadSFBALU, ReadSFBALU]>; 14135f757f3fSDimitry Andricdef PseudoCCSRL : Pseudo<(outs GPR:$dst), 14145f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 14155f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 14165f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 14175f757f3fSDimitry Andric ReadSFBALU, ReadSFBALU]>; 14185f757f3fSDimitry Andricdef PseudoCCSRA : Pseudo<(outs GPR:$dst), 14195f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 14205f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 14215f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 14225f757f3fSDimitry Andric ReadSFBALU, ReadSFBALU]>; 1423bdd1243dSDimitry Andricdef PseudoCCAND : Pseudo<(outs GPR:$dst), 1424bdd1243dSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 1425bdd1243dSDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 142606c3fb27SDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, 142706c3fb27SDimitry Andric ReadSFBALU, ReadSFBALU, ReadSFBALU]>; 1428bdd1243dSDimitry Andricdef PseudoCCOR : Pseudo<(outs GPR:$dst), 1429bdd1243dSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 1430bdd1243dSDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 143106c3fb27SDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, 143206c3fb27SDimitry Andric ReadSFBALU, ReadSFBALU, ReadSFBALU]>; 1433bdd1243dSDimitry Andricdef PseudoCCXOR : Pseudo<(outs GPR:$dst), 1434bdd1243dSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 1435bdd1243dSDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 143606c3fb27SDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, 143706c3fb27SDimitry Andric ReadSFBALU, ReadSFBALU, ReadSFBALU]>; 1438bdd1243dSDimitry Andric 14395f757f3fSDimitry Andricdef PseudoCCADDI : Pseudo<(outs GPR:$dst), 14405f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 14415f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, simm12:$rs2), []>, 14425f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 14435f757f3fSDimitry Andric ReadSFBALU]>; 14445f757f3fSDimitry Andricdef PseudoCCSLLI : Pseudo<(outs GPR:$dst), 14455f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 14465f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, simm12:$rs2), []>, 14475f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 14485f757f3fSDimitry Andric ReadSFBALU]>; 14495f757f3fSDimitry Andricdef PseudoCCSRLI : Pseudo<(outs GPR:$dst), 14505f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 14515f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, simm12:$rs2), []>, 14525f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 14535f757f3fSDimitry Andric ReadSFBALU]>; 14545f757f3fSDimitry Andricdef PseudoCCSRAI : Pseudo<(outs GPR:$dst), 14555f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 14565f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, simm12:$rs2), []>, 14575f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 14585f757f3fSDimitry Andric ReadSFBALU]>; 14595f757f3fSDimitry Andricdef PseudoCCANDI : Pseudo<(outs GPR:$dst), 14605f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 14615f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, simm12:$rs2), []>, 14625f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 14635f757f3fSDimitry Andric ReadSFBALU]>; 14645f757f3fSDimitry Andricdef PseudoCCORI : Pseudo<(outs GPR:$dst), 14655f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 14665f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, simm12:$rs2), []>, 14675f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 14685f757f3fSDimitry Andric ReadSFBALU]>; 14695f757f3fSDimitry Andricdef PseudoCCXORI : Pseudo<(outs GPR:$dst), 14705f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 14715f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, simm12:$rs2), []>, 14725f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 14735f757f3fSDimitry Andric ReadSFBALU]>; 14745f757f3fSDimitry Andric 1475bdd1243dSDimitry Andric// RV64I instructions 1476bdd1243dSDimitry Andricdef PseudoCCADDW : Pseudo<(outs GPR:$dst), 1477bdd1243dSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 1478bdd1243dSDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 147906c3fb27SDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, 148006c3fb27SDimitry Andric ReadSFBALU, ReadSFBALU, ReadSFBALU]>; 1481bdd1243dSDimitry Andricdef PseudoCCSUBW : Pseudo<(outs GPR:$dst), 1482bdd1243dSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 1483bdd1243dSDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 148406c3fb27SDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, 148506c3fb27SDimitry Andric ReadSFBALU, ReadSFBALU, ReadSFBALU]>; 14865f757f3fSDimitry Andricdef PseudoCCSLLW : Pseudo<(outs GPR:$dst), 14875f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 14885f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 14895f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 14905f757f3fSDimitry Andric ReadSFBALU, ReadSFBALU]>; 14915f757f3fSDimitry Andricdef PseudoCCSRLW : Pseudo<(outs GPR:$dst), 14925f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 14935f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 14945f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 14955f757f3fSDimitry Andric ReadSFBALU, ReadSFBALU]>; 14965f757f3fSDimitry Andricdef PseudoCCSRAW : Pseudo<(outs GPR:$dst), 14975f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 14985f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 14995f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 15005f757f3fSDimitry Andric ReadSFBALU, ReadSFBALU]>; 15015f757f3fSDimitry Andric 15025f757f3fSDimitry Andricdef PseudoCCADDIW : Pseudo<(outs GPR:$dst), 15035f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 15045f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, simm12:$rs2), []>, 15055f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 15065f757f3fSDimitry Andric ReadSFBALU]>; 15075f757f3fSDimitry Andricdef PseudoCCSLLIW : Pseudo<(outs GPR:$dst), 15085f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 15095f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, simm12:$rs2), []>, 15105f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 15115f757f3fSDimitry Andric ReadSFBALU]>; 15125f757f3fSDimitry Andricdef PseudoCCSRLIW : Pseudo<(outs GPR:$dst), 15135f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 15145f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, simm12:$rs2), []>, 15155f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 15165f757f3fSDimitry Andric ReadSFBALU]>; 15175f757f3fSDimitry Andricdef PseudoCCSRAIW : Pseudo<(outs GPR:$dst), 15185f757f3fSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 15195f757f3fSDimitry Andric GPR:$falsev, GPR:$rs1, simm12:$rs2), []>, 15205f757f3fSDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, 15215f757f3fSDimitry Andric ReadSFBALU]>; 15221db9f3b2SDimitry Andric 15231db9f3b2SDimitry Andric// Zbb/Zbkb instructions 15241db9f3b2SDimitry Andricdef PseudoCCANDN : Pseudo<(outs GPR:$dst), 15251db9f3b2SDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 15261db9f3b2SDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 15271db9f3b2SDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, 15281db9f3b2SDimitry Andric ReadSFBALU, ReadSFBALU, ReadSFBALU]>; 15291db9f3b2SDimitry Andricdef PseudoCCORN : Pseudo<(outs GPR:$dst), 15301db9f3b2SDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 15311db9f3b2SDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 15321db9f3b2SDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, 15331db9f3b2SDimitry Andric ReadSFBALU, ReadSFBALU, ReadSFBALU]>; 15341db9f3b2SDimitry Andricdef PseudoCCXNOR : Pseudo<(outs GPR:$dst), 15351db9f3b2SDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 15361db9f3b2SDimitry Andric GPR:$falsev, GPR:$rs1, GPR:$rs2), []>, 15371db9f3b2SDimitry Andric Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, 15381db9f3b2SDimitry Andric ReadSFBALU, ReadSFBALU, ReadSFBALU]>; 1539bdd1243dSDimitry Andric} 1540bdd1243dSDimitry Andric 154106c3fb27SDimitry Andricmulticlass SelectCC_GPR_rrirr<DAGOperand valty, ValueType vt> { 15420b57cec5SDimitry Andric let usesCustomInserter = 1 in 1543bdd1243dSDimitry Andric def _Using_CC_GPR : Pseudo<(outs valty:$dst), 1544bdd1243dSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 15450b57cec5SDimitry Andric valty:$truev, valty:$falsev), 1546349cc55cSDimitry Andric [(set valty:$dst, 154706c3fb27SDimitry Andric (riscv_selectcc_frag:$cc (XLenVT GPR:$lhs), GPR:$rhs, cond, 154806c3fb27SDimitry Andric (vt valty:$truev), valty:$falsev))]>; 1549bdd1243dSDimitry Andric // Explicitly select 0 in the condition to X0. The register coalescer doesn't 1550bdd1243dSDimitry Andric // always do it. 155106c3fb27SDimitry Andric def : Pat<(riscv_selectcc_frag:$cc (XLenVT GPR:$lhs), 0, cond, (vt valty:$truev), 1552bdd1243dSDimitry Andric valty:$falsev), 155306c3fb27SDimitry Andric (!cast<Instruction>(NAME#"_Using_CC_GPR") GPR:$lhs, (XLenVT X0), 1554bdd1243dSDimitry Andric (IntCCtoRISCVCC $cc), valty:$truev, valty:$falsev)>; 1555bdd1243dSDimitry Andric} 15560b57cec5SDimitry Andric 15571db9f3b2SDimitry Andriclet Predicates = [NoConditionalMoveFusion] in 155806c3fb27SDimitry Andricdefm Select_GPR : SelectCC_GPR_rrirr<GPR, XLenVT>; 1559bdd1243dSDimitry Andric 156006c3fb27SDimitry Andricclass SelectCompressOpt<CondCode Cond> 156106c3fb27SDimitry Andric : Pat<(riscv_selectcc_frag:$select (XLenVT GPR:$lhs), simm12_no6:$Constant, Cond, 156206c3fb27SDimitry Andric (XLenVT GPR:$truev), GPR:$falsev), 156306c3fb27SDimitry Andric (Select_GPR_Using_CC_GPR (ADDI GPR:$lhs, (NegImm simm12:$Constant)), (XLenVT X0), 1564bdd1243dSDimitry Andric (IntCCtoRISCVCC $select), GPR:$truev, GPR:$falsev)>; 1565bdd1243dSDimitry Andric 1566bdd1243dSDimitry Andricdef OptForMinSize : Predicate<"MF ? MF->getFunction().hasMinSize() : false">; 1567bdd1243dSDimitry Andric 1568bdd1243dSDimitry Andriclet Predicates = [HasStdExtC, OptForMinSize] in { 1569bdd1243dSDimitry Andric def : SelectCompressOpt<SETEQ>; 1570bdd1243dSDimitry Andric def : SelectCompressOpt<SETNE>; 1571bdd1243dSDimitry Andric} 15720b57cec5SDimitry Andric 15730b57cec5SDimitry Andric/// Branches and jumps 15740b57cec5SDimitry Andric 1575fe6060f1SDimitry Andric// Match `riscv_brcc` and lower to the appropriate RISC-V branch instruction. 1576bdd1243dSDimitry Andricmulticlass BccPat<CondCode Cond, RVInstB Inst> { 157706c3fb27SDimitry Andric def : Pat<(riscv_brcc (XLenVT GPR:$rs1), GPR:$rs2, Cond, bb:$imm12), 15780b57cec5SDimitry Andric (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>; 1579bdd1243dSDimitry Andric // Explicitly select 0 to X0. The register coalescer doesn't always do it. 158006c3fb27SDimitry Andric def : Pat<(riscv_brcc (XLenVT GPR:$rs1), 0, Cond, bb:$imm12), 158106c3fb27SDimitry Andric (Inst GPR:$rs1, (XLenVT X0), simm13_lsb0:$imm12)>; 1582bdd1243dSDimitry Andric} 15830b57cec5SDimitry Andric 158406c3fb27SDimitry Andricclass BrccCompressOpt<CondCode Cond, RVInstB Inst> 158506c3fb27SDimitry Andric : Pat<(riscv_brcc GPR:$lhs, simm12_no6:$Constant, Cond, bb:$place), 158606c3fb27SDimitry Andric (Inst (ADDI GPR:$lhs, (NegImm simm12:$Constant)), (XLenVT X0), bb:$place)>; 1587bdd1243dSDimitry Andric 1588bdd1243dSDimitry Andricdefm : BccPat<SETEQ, BEQ>; 1589bdd1243dSDimitry Andricdefm : BccPat<SETNE, BNE>; 1590bdd1243dSDimitry Andricdefm : BccPat<SETLT, BLT>; 1591bdd1243dSDimitry Andricdefm : BccPat<SETGE, BGE>; 1592bdd1243dSDimitry Andricdefm : BccPat<SETULT, BLTU>; 1593bdd1243dSDimitry Andricdefm : BccPat<SETUGE, BGEU>; 1594bdd1243dSDimitry Andric 1595bdd1243dSDimitry Andriclet Predicates = [HasStdExtC, OptForMinSize] in { 159606c3fb27SDimitry Andric def : BrccCompressOpt<SETEQ, BEQ>; 159706c3fb27SDimitry Andric def : BrccCompressOpt<SETNE, BNE>; 1598bdd1243dSDimitry Andric} 15990b57cec5SDimitry Andric 160006c3fb27SDimitry Andricclass LongBccPseudo : Pseudo<(outs), 160106c3fb27SDimitry Andric (ins GPR:$rs1, GPR:$rs2, simm21_lsb0_jal:$imm20), 160206c3fb27SDimitry Andric []> { 160306c3fb27SDimitry Andric let Size = 8; 160406c3fb27SDimitry Andric let isBarrier = 1; 160506c3fb27SDimitry Andric let isBranch = 1; 160606c3fb27SDimitry Andric let hasSideEffects = 0; 160706c3fb27SDimitry Andric let mayStore = 0; 160806c3fb27SDimitry Andric let mayLoad = 0; 160906c3fb27SDimitry Andric let isAsmParserOnly = 1; 161006c3fb27SDimitry Andric let hasNoSchedulingInfo = 1; 161106c3fb27SDimitry Andric} 161206c3fb27SDimitry Andric 161306c3fb27SDimitry Andricdef PseudoLongBEQ : LongBccPseudo; 161406c3fb27SDimitry Andricdef PseudoLongBNE : LongBccPseudo; 161506c3fb27SDimitry Andricdef PseudoLongBLT : LongBccPseudo; 161606c3fb27SDimitry Andricdef PseudoLongBGE : LongBccPseudo; 161706c3fb27SDimitry Andricdef PseudoLongBLTU : LongBccPseudo; 161806c3fb27SDimitry Andricdef PseudoLongBGEU : LongBccPseudo; 161906c3fb27SDimitry Andric 16200b57cec5SDimitry Andriclet isBarrier = 1, isBranch = 1, isTerminator = 1 in 16210b57cec5SDimitry Andricdef PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>, 16220b57cec5SDimitry Andric PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>; 16230b57cec5SDimitry Andric 16240b57cec5SDimitry Andriclet isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in 1625fe6060f1SDimitry Andricdef PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12:$imm12), []>, 16260b57cec5SDimitry Andric PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; 16270b57cec5SDimitry Andric 1628fe6060f1SDimitry Andricdef : Pat<(brind GPRJALR:$rs1), (PseudoBRIND GPRJALR:$rs1, 0)>; 1629fe6060f1SDimitry Andricdef : Pat<(brind (add GPRJALR:$rs1, simm12:$imm12)), 1630fe6060f1SDimitry Andric (PseudoBRIND GPRJALR:$rs1, simm12:$imm12)>; 16310b57cec5SDimitry Andric 1632480093f4SDimitry Andric// PseudoCALLReg is a generic pseudo instruction for calls which will eventually 16330b57cec5SDimitry Andric// expand to auipc and jalr while encoding, with any given register used as the 16340b57cec5SDimitry Andric// destination. 16350b57cec5SDimitry Andric// Define AsmString to print "call" when compile with -S flag. 16360b57cec5SDimitry Andric// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 16371fd87a68SDimitry Andriclet isCall = 1, isBarrier = 1, isCodeGenOnly = 0, Size = 8, hasSideEffects = 0, 16380b57cec5SDimitry Andric mayStore = 0, mayLoad = 0 in 163906c3fb27SDimitry Andricdef PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), [], 164006c3fb27SDimitry Andric "call", "$rd, $func">, 164106c3fb27SDimitry Andric Sched<[WriteIALU, WriteJalr, ReadJalr]>; 16420b57cec5SDimitry Andric 16430b57cec5SDimitry Andric// PseudoCALL is a pseudo instruction which will eventually expand to auipc 16440b57cec5SDimitry Andric// and jalr while encoding. This is desirable, as an auipc+jalr pair with 16450b57cec5SDimitry Andric// R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker 16460b57cec5SDimitry Andric// if the offset fits in a signed 21-bit immediate. 16470b57cec5SDimitry Andric// Define AsmString to print "call" when compile with -S flag. 16480b57cec5SDimitry Andric// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 16491fd87a68SDimitry Andriclet isCall = 1, Defs = [X1], isCodeGenOnly = 0, Size = 8 in 165006c3fb27SDimitry Andricdef PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), [], 165106c3fb27SDimitry Andric "call", "$func">, 165206c3fb27SDimitry Andric Sched<[WriteIALU, WriteJalr, ReadJalr]>; 16530b57cec5SDimitry Andric 16540b57cec5SDimitry Andricdef : Pat<(riscv_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>; 16550b57cec5SDimitry Andricdef : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>; 16560b57cec5SDimitry Andric 165706c3fb27SDimitry Andricdef : Pat<(riscv_sret_glue), (SRET (XLenVT X0), (XLenVT X0))>; 165806c3fb27SDimitry Andricdef : Pat<(riscv_mret_glue), (MRET (XLenVT X0), (XLenVT X0))>; 16590b57cec5SDimitry Andric 16600b57cec5SDimitry Andriclet isCall = 1, Defs = [X1] in 1661fe6060f1SDimitry Andricdef PseudoCALLIndirect : Pseudo<(outs), (ins GPRJALR:$rs1), 1662fe6060f1SDimitry Andric [(riscv_call GPRJALR:$rs1)]>, 16630b57cec5SDimitry Andric PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>; 16640b57cec5SDimitry Andric 16650b57cec5SDimitry Andriclet isBarrier = 1, isReturn = 1, isTerminator = 1 in 166606c3fb27SDimitry Andricdef PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_glue)]>, 16670b57cec5SDimitry Andric PseudoInstExpansion<(JALR X0, X1, 0)>; 16680b57cec5SDimitry Andric 16690b57cec5SDimitry Andric// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually 16700b57cec5SDimitry Andric// expand to auipc and jalr while encoding. 16710b57cec5SDimitry Andric// Define AsmString to print "tail" when compile with -S flag. 16720b57cec5SDimitry Andriclet isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2], 16731fd87a68SDimitry Andric Size = 8, isCodeGenOnly = 0 in 167406c3fb27SDimitry Andricdef PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), [], 167506c3fb27SDimitry Andric "tail", "$dst">, 167606c3fb27SDimitry Andric Sched<[WriteIALU, WriteJalr, ReadJalr]>; 16770b57cec5SDimitry Andric 16780b57cec5SDimitry Andriclet isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in 16790b57cec5SDimitry Andricdef PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1), 16800b57cec5SDimitry Andric [(riscv_tail GPRTC:$rs1)]>, 16810b57cec5SDimitry Andric PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>; 16820b57cec5SDimitry Andric 16830b57cec5SDimitry Andricdef : Pat<(riscv_tail (iPTR tglobaladdr:$dst)), 168481ad6265SDimitry Andric (PseudoTAIL tglobaladdr:$dst)>; 16850b57cec5SDimitry Andricdef : Pat<(riscv_tail (iPTR texternalsym:$dst)), 16860b57cec5SDimitry Andric (PseudoTAIL texternalsym:$dst)>; 16870b57cec5SDimitry Andric 16881fd87a68SDimitry Andriclet isCall = 0, isBarrier = 1, isBranch = 1, isTerminator = 1, Size = 8, 168975b4d546SDimitry Andric isCodeGenOnly = 0, hasSideEffects = 0, mayStore = 0, mayLoad = 0 in 169006c3fb27SDimitry Andricdef PseudoJump : Pseudo<(outs GPR:$rd), (ins pseudo_jump_symbol:$target), [], 169106c3fb27SDimitry Andric "jump", "$target, $rd">, 169206c3fb27SDimitry Andric Sched<[WriteIALU, WriteJalr, ReadJalr]>; 16935ffd83dbSDimitry Andric 16945f757f3fSDimitry Andric// Pseudo for a rematerializable constant materialization sequence. 16955f757f3fSDimitry Andric// This is an experimental feature enabled by 16965f757f3fSDimitry Andric// -riscv-use-rematerializable-movimm in RISCVISelDAGToDAG.cpp 16975f757f3fSDimitry Andric// It will be expanded after register allocation. 16985f757f3fSDimitry Andric// FIXME: The scheduling information does not reflect the multiple instructions. 16995f757f3fSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 1, 17005f757f3fSDimitry Andric isPseudo = 1, isReMaterializable = 1, IsSignExtendingOpW = 1 in 17015f757f3fSDimitry Andricdef PseudoMovImm : Pseudo<(outs GPR:$dst), (ins i32imm:$imm), []>, 17025f757f3fSDimitry Andric Sched<[WriteIALU]>; 17035f757f3fSDimitry Andric 17041fd87a68SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0, 17050b57cec5SDimitry Andric isAsmParserOnly = 1 in 17060b57cec5SDimitry Andricdef PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 17070b57cec5SDimitry Andric "lla", "$dst, $src">; 17080b57cec5SDimitry Andric 170906c3fb27SDimitry Andric// Refer to comment on PseudoLI for explanation of Size=32 171006c3fb27SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0, 171106c3fb27SDimitry Andric isAsmParserOnly = 1 in 171206c3fb27SDimitry Andricdef PseudoLLAImm : Pseudo<(outs GPR:$dst), (ins ixlenimm_li_restricted:$imm), [], 171306c3fb27SDimitry Andric "lla", "$dst, $imm">; 171481ad6265SDimitry Andricdef : Pat<(riscv_lla tglobaladdr:$in), (PseudoLLA tglobaladdr:$in)>; 171581ad6265SDimitry Andricdef : Pat<(riscv_lla tblockaddress:$in), (PseudoLLA tblockaddress:$in)>; 171681ad6265SDimitry Andricdef : Pat<(riscv_lla tjumptable:$in), (PseudoLLA tjumptable:$in)>; 171781ad6265SDimitry Andricdef : Pat<(riscv_lla tconstpool:$in), (PseudoLLA tconstpool:$in)>; 171881ad6265SDimitry Andric 17191fd87a68SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0, 17200b57cec5SDimitry Andric isAsmParserOnly = 1 in 172106c3fb27SDimitry Andricdef PseudoLGA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 172206c3fb27SDimitry Andric "lga", "$dst, $src">; 172306c3fb27SDimitry Andric 172406c3fb27SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0, 172506c3fb27SDimitry Andric isAsmParserOnly = 1 in 17260b57cec5SDimitry Andricdef PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 17270b57cec5SDimitry Andric "la", "$dst, $src">; 17280b57cec5SDimitry Andric 172906c3fb27SDimitry Andric// Refer to comment on PseudoLI for explanation of Size=32 173006c3fb27SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32, 173106c3fb27SDimitry Andric isCodeGenOnly = 0, isAsmParserOnly = 1 in 173206c3fb27SDimitry Andricdef PseudoLAImm : Pseudo<(outs GPR:$rd), (ins ixlenimm_li_restricted:$imm), [], 173306c3fb27SDimitry Andric "la", "$rd, $imm">; 173481ad6265SDimitry Andric 17351fd87a68SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0, 17360b57cec5SDimitry Andric isAsmParserOnly = 1 in 17370b57cec5SDimitry Andricdef PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 17380b57cec5SDimitry Andric "la.tls.ie", "$dst, $src">; 17390b57cec5SDimitry Andric 174081ad6265SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0, 17410b57cec5SDimitry Andric isAsmParserOnly = 1 in 17420b57cec5SDimitry Andricdef PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 17430b57cec5SDimitry Andric "la.tls.gd", "$dst, $src">; 17440b57cec5SDimitry Andric 17457a6dacacSDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 32, isCodeGenOnly = 0 in 17467a6dacacSDimitry Andricdef PseudoLA_TLSDESC : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 17477a6dacacSDimitry Andric "la.tlsdesc", "$dst, $src">; 17487a6dacacSDimitry Andric 17497a6dacacSDimitry Andricdef TLSDESCCallSymbol : AsmOperandClass { 17507a6dacacSDimitry Andric let Name = "TLSDESCCallSymbol"; 17517a6dacacSDimitry Andric let RenderMethod = "addImmOperands"; 17527a6dacacSDimitry Andric let DiagnosticType = "InvalidTLSDESCCallSymbol"; 17537a6dacacSDimitry Andric let ParserMethod = "parseOperandWithModifier"; 17547a6dacacSDimitry Andric} 17557a6dacacSDimitry Andric 17567a6dacacSDimitry Andric// A bare symbol with the %tlsdesc_call variant. 17577a6dacacSDimitry Andricdef tlsdesc_call_symbol : Operand<XLenVT> { 17587a6dacacSDimitry Andric let ParserMatchClass = TLSDESCCallSymbol; 17597a6dacacSDimitry Andric} 17607a6dacacSDimitry Andric// This is a special case of the JALR instruction used to facilitate the use of a 17617a6dacacSDimitry Andric// fourth operand to emit a relocation on a symbol relating to this instruction. 17627a6dacacSDimitry Andric// The relocation does not affect any bits of the instruction itself but is used 17637a6dacacSDimitry Andric// as a hint to the linker. 17647a6dacacSDimitry Andriclet isCall = 1, isBarrier = 1, isCodeGenOnly = 0, Size = 8, hasSideEffects = 0, 17657a6dacacSDimitry Andric mayStore = 0, mayLoad = 0 in 17667a6dacacSDimitry Andricdef PseudoTLSDESCCall : Pseudo<(outs GPR:$rd), 17677a6dacacSDimitry Andric (ins GPR:$rs1, simm12:$imm12, tlsdesc_call_symbol:$src), [], 17687a6dacacSDimitry Andric "jalr", "$rd, ${imm12}(${rs1}), $src">, 17697a6dacacSDimitry Andric Sched<[WriteJalr, ReadJalr]> { 17707a6dacacSDimitry Andric let Defs = [X10]; 17717a6dacacSDimitry Andric let Uses = [X10]; 17727a6dacacSDimitry Andric} 17737a6dacacSDimitry Andric 1774e8d8bef9SDimitry Andric 1775e8d8bef9SDimitry Andric/// Sign/Zero Extends 1776e8d8bef9SDimitry Andric 1777e8d8bef9SDimitry Andric// There are single-instruction versions of these in Zbb, so disable these 1778e8d8bef9SDimitry Andric// Pseudos if that extension is present. 1779e8d8bef9SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, 1780e8d8bef9SDimitry Andric mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in { 1781e8d8bef9SDimitry Andricdef PseudoSEXT_B : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.b", "$rd, $rs">; 1782e8d8bef9SDimitry Andricdef PseudoSEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.h", "$rd, $rs">; 1783e8d8bef9SDimitry Andric// rv64's sext.w is defined above, using InstAlias<"sext.w ... 1784e8d8bef9SDimitry Andric// zext.b is defined above, using InstAlias<"zext.b ... 1785e8d8bef9SDimitry Andricdef PseudoZEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.h", "$rd, $rs">; 1786e8d8bef9SDimitry Andric} // hasSideEffects = 0, ... 1787e8d8bef9SDimitry Andric 1788e8d8bef9SDimitry Andriclet Predicates = [IsRV64], hasSideEffects = 0, mayLoad = 0, mayStore = 0, 1789e8d8bef9SDimitry Andric isCodeGenOnly = 0, isAsmParserOnly = 1 in { 1790e8d8bef9SDimitry Andricdef PseudoZEXT_W : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.w", "$rd, $rs">; 1791e8d8bef9SDimitry Andric} // Predicates = [IsRV64], ... 1792e8d8bef9SDimitry Andric 17930b57cec5SDimitry Andric/// Loads 17940b57cec5SDimitry Andric 179506c3fb27SDimitry Andricclass LdPat<PatFrag LoadOp, RVInst Inst, ValueType vt = XLenVT> 179606c3fb27SDimitry Andric : Pat<(vt (LoadOp (AddrRegImm (XLenVT GPR:$rs1), simm12:$imm12))), 179781ad6265SDimitry Andric (Inst GPR:$rs1, simm12:$imm12)>; 17980b57cec5SDimitry Andric 179906c3fb27SDimitry Andricdef : LdPat<sextloadi8, LB>; 180006c3fb27SDimitry Andricdef : LdPat<extloadi8, LBU>; // Prefer unsigned due to no c.lb in Zcb. 180106c3fb27SDimitry Andricdef : LdPat<sextloadi16, LH>; 180206c3fb27SDimitry Andricdef : LdPat<extloadi16, LH>; 18035f757f3fSDimitry Andricdef : LdPat<load, LW, i32>; 180406c3fb27SDimitry Andricdef : LdPat<zextloadi8, LBU>; 180506c3fb27SDimitry Andricdef : LdPat<zextloadi16, LHU>; 18060b57cec5SDimitry Andric 18070b57cec5SDimitry Andric/// Stores 18080b57cec5SDimitry Andric 180906c3fb27SDimitry Andricclass StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy, 181006c3fb27SDimitry Andric ValueType vt> 181106c3fb27SDimitry Andric : Pat<(StoreOp (vt StTy:$rs2), (AddrRegImm (XLenVT GPR:$rs1), 181206c3fb27SDimitry Andric simm12:$imm12)), 181381ad6265SDimitry Andric (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>; 18140b57cec5SDimitry Andric 181506c3fb27SDimitry Andricdef : StPat<truncstorei8, SB, GPR, XLenVT>; 181606c3fb27SDimitry Andricdef : StPat<truncstorei16, SH, GPR, XLenVT>; 18175f757f3fSDimitry Andricdef : StPat<store, SW, GPR, i32>; 18180b57cec5SDimitry Andric 18190b57cec5SDimitry Andric/// Fences 18200b57cec5SDimitry Andric 18210b57cec5SDimitry Andric// Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set 18220b57cec5SDimitry Andric// Manual: Volume I. 18230b57cec5SDimitry Andric 18240b57cec5SDimitry Andric// fence acquire -> fence r, rw 1825480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 4), (timm)), (FENCE 0b10, 0b11)>; 18260b57cec5SDimitry Andric// fence release -> fence rw, w 1827480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 5), (timm)), (FENCE 0b11, 0b1)>; 18280b57cec5SDimitry Andric// fence acq_rel -> fence.tso 1829480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 6), (timm)), (FENCE_TSO)>; 18300b57cec5SDimitry Andric// fence seq_cst -> fence rw, rw 1831480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 7), (timm)), (FENCE 0b11, 0b11)>; 18320b57cec5SDimitry Andric 18330b57cec5SDimitry Andric// Lowering for atomic load and store is defined in RISCVInstrInfoA.td. 18340b57cec5SDimitry Andric// Although these are lowered to fence+load/store instructions defined in the 18350b57cec5SDimitry Andric// base RV32I/RV64I ISA, this lowering is only used when the A extension is 18360b57cec5SDimitry Andric// present. This is necessary as it isn't valid to mix __atomic_* libcalls 18370b57cec5SDimitry Andric// with inline atomic operations for the same object. 18380b57cec5SDimitry Andric 1839fe6060f1SDimitry Andric/// Access to system registers 1840fe6060f1SDimitry Andric 1841fe6060f1SDimitry Andric// Helpers for defining specific operations. They are defined for each system 1842fe6060f1SDimitry Andric// register separately. Side effect is not used because dependencies are 1843fe6060f1SDimitry Andric// expressed via use-def properties. 1844fe6060f1SDimitry Andric 1845fe6060f1SDimitry Andricclass ReadSysReg<SysReg SR, list<Register> Regs> 1846fe6060f1SDimitry Andric : Pseudo<(outs GPR:$rd), (ins), 184706c3fb27SDimitry Andric [(set GPR:$rd, (XLenVT (riscv_read_csr (XLenVT SR.Encoding))))]>, 1848fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRS GPR:$rd, SR.Encoding, X0)> { 1849fe6060f1SDimitry Andric let hasSideEffects = 0; 1850fe6060f1SDimitry Andric let Uses = Regs; 1851fe6060f1SDimitry Andric} 1852fe6060f1SDimitry Andric 1853fe6060f1SDimitry Andricclass WriteSysReg<SysReg SR, list<Register> Regs> 1854fe6060f1SDimitry Andric : Pseudo<(outs), (ins GPR:$val), 185506c3fb27SDimitry Andric [(riscv_write_csr (XLenVT SR.Encoding), (XLenVT GPR:$val))]>, 1856fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRW X0, SR.Encoding, GPR:$val)> { 1857fe6060f1SDimitry Andric let hasSideEffects = 0; 1858fe6060f1SDimitry Andric let Defs = Regs; 1859fe6060f1SDimitry Andric} 1860fe6060f1SDimitry Andric 1861fe6060f1SDimitry Andricclass WriteSysRegImm<SysReg SR, list<Register> Regs> 1862fe6060f1SDimitry Andric : Pseudo<(outs), (ins uimm5:$val), 1863fe6060f1SDimitry Andric [(riscv_write_csr (XLenVT SR.Encoding), uimm5:$val)]>, 1864fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRWI X0, SR.Encoding, uimm5:$val)> { 1865fe6060f1SDimitry Andric let hasSideEffects = 0; 1866fe6060f1SDimitry Andric let Defs = Regs; 1867fe6060f1SDimitry Andric} 1868fe6060f1SDimitry Andric 1869fe6060f1SDimitry Andricclass SwapSysReg<SysReg SR, list<Register> Regs> 1870fe6060f1SDimitry Andric : Pseudo<(outs GPR:$rd), (ins GPR:$val), 187106c3fb27SDimitry Andric [(set GPR:$rd, (riscv_swap_csr (XLenVT SR.Encoding), (XLenVT GPR:$val)))]>, 1872fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRW GPR:$rd, SR.Encoding, GPR:$val)> { 1873fe6060f1SDimitry Andric let hasSideEffects = 0; 1874fe6060f1SDimitry Andric let Uses = Regs; 1875fe6060f1SDimitry Andric let Defs = Regs; 1876fe6060f1SDimitry Andric} 1877fe6060f1SDimitry Andric 1878fe6060f1SDimitry Andricclass SwapSysRegImm<SysReg SR, list<Register> Regs> 1879fe6060f1SDimitry Andric : Pseudo<(outs GPR:$rd), (ins uimm5:$val), 188006c3fb27SDimitry Andric [(set GPR:$rd, (XLenVT (riscv_swap_csr (XLenVT SR.Encoding), uimm5:$val)))]>, 1881fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRWI GPR:$rd, SR.Encoding, uimm5:$val)> { 1882fe6060f1SDimitry Andric let hasSideEffects = 0; 1883fe6060f1SDimitry Andric let Uses = Regs; 1884fe6060f1SDimitry Andric let Defs = Regs; 1885fe6060f1SDimitry Andric} 1886fe6060f1SDimitry Andric 1887fe6060f1SDimitry Andricdef ReadFRM : ReadSysReg<SysRegFRM, [FRM]>; 1888fe6060f1SDimitry Andricdef WriteFRM : WriteSysReg<SysRegFRM, [FRM]>; 1889fe6060f1SDimitry Andricdef WriteFRMImm : WriteSysRegImm<SysRegFRM, [FRM]>; 1890bdd1243dSDimitry Andricdef SwapFRMImm : SwapSysRegImm<SysRegFRM, [FRM]>; 1891fe6060f1SDimitry Andric 189206c3fb27SDimitry Andricdef WriteVXRMImm : WriteSysRegImm<SysRegVXRM, [VXRM]>; 189306c3fb27SDimitry Andric 189404eeddc0SDimitry Andriclet hasSideEffects = true in { 189504eeddc0SDimitry Andricdef ReadFFLAGS : ReadSysReg<SysRegFFLAGS, [FFLAGS]>; 189604eeddc0SDimitry Andricdef WriteFFLAGS : WriteSysReg<SysRegFFLAGS, [FFLAGS]>; 189704eeddc0SDimitry Andric} 18980b57cec5SDimitry Andric/// Other pseudo-instructions 18990b57cec5SDimitry Andric 19000b57cec5SDimitry Andric// Pessimistically assume the stack pointer will be clobbered 19010b57cec5SDimitry Andriclet Defs = [X2], Uses = [X2] in { 19020b57cec5SDimitry Andricdef ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 19030b57cec5SDimitry Andric [(callseq_start timm:$amt1, timm:$amt2)]>; 19040b57cec5SDimitry Andricdef ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 19050b57cec5SDimitry Andric [(callseq_end timm:$amt1, timm:$amt2)]>; 19060b57cec5SDimitry Andric} // Defs = [X2], Uses = [X2] 19070b57cec5SDimitry Andric 19080b57cec5SDimitry Andric/// RV64 patterns 19090b57cec5SDimitry Andric 1910e8d8bef9SDimitry Andriclet Predicates = [IsRV64, NotHasStdExtZba] in { 1911fe6060f1SDimitry Andricdef : Pat<(i64 (and GPR:$rs1, 0xffffffff)), (SRLI (SLLI GPR:$rs1, 32), 32)>; 1912e8d8bef9SDimitry Andric 1913e8d8bef9SDimitry Andric// If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2 1914e8d8bef9SDimitry Andric// shifts instead of 3. This can occur when unsigned is used to index an array. 1915fe6060f1SDimitry Andricdef : Pat<(i64 (shl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)), 1916e8d8bef9SDimitry Andric (SRLI (SLLI GPR:$rs1, 32), (ImmSubFrom32 uimm5:$shamt))>; 1917e8d8bef9SDimitry Andric} 1918e8d8bef9SDimitry Andric 19195f757f3fSDimitry Andricclass binop_allhusers<SDPatternOperator operator> 19205f757f3fSDimitry Andric : PatFrag<(ops node:$lhs, node:$rhs), 19215f757f3fSDimitry Andric (XLenVT (operator node:$lhs, node:$rhs)), [{ 19225f757f3fSDimitry Andric return hasAllHUsers(Node); 19235f757f3fSDimitry Andric}]>; 19245f757f3fSDimitry Andric 1925349cc55cSDimitry Andric// PatFrag to allow ADDW/SUBW/MULW/SLLW to be selected from i64 add/sub/mul/shl 1926349cc55cSDimitry Andric// if only the lower 32 bits of their result is used. 1927349cc55cSDimitry Andricclass binop_allwusers<SDPatternOperator operator> 1928349cc55cSDimitry Andric : PatFrag<(ops node:$lhs, node:$rhs), 192981ad6265SDimitry Andric (i64 (operator node:$lhs, node:$rhs)), [{ 1930349cc55cSDimitry Andric return hasAllWUsers(Node); 1931349cc55cSDimitry Andric}]>; 1932349cc55cSDimitry Andric 1933349cc55cSDimitry Andricdef sexti32_allwusers : PatFrag<(ops node:$src), 1934349cc55cSDimitry Andric (sext_inreg node:$src, i32), [{ 1935349cc55cSDimitry Andric return hasAllWUsers(Node); 1936349cc55cSDimitry Andric}]>; 1937349cc55cSDimitry Andric 1938bdd1243dSDimitry Andricdef ImmSExt32 : SDNodeXForm<imm, [{ 1939bdd1243dSDimitry Andric return CurDAG->getTargetConstant(SignExtend64<32>(N->getSExtValue()), 1940bdd1243dSDimitry Andric SDLoc(N), N->getValueType(0)); 1941bdd1243dSDimitry Andric}]>; 1942bdd1243dSDimitry Andric// Look for constants where the upper 32 bits are 0, but sign extending bit 31 1943bdd1243dSDimitry Andric// would be an simm12. 1944bdd1243dSDimitry Andricdef u32simm12 : ImmLeaf<XLenVT, [{ 1945bdd1243dSDimitry Andric return isUInt<32>(Imm) && isInt<12>(SignExtend64<32>(Imm)); 1946bdd1243dSDimitry Andric}], ImmSExt32>; 1947bdd1243dSDimitry Andric 19480b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 19490b57cec5SDimitry Andric 1950bdd1243dSDimitry Andricdef : Pat<(i64 (and GPR:$rs, LeadingOnesWMask:$mask)), 1951bdd1243dSDimitry Andric (SLLI (SRLIW $rs, LeadingOnesWMask:$mask), LeadingOnesWMask:$mask)>; 1952bdd1243dSDimitry Andric 19530b57cec5SDimitry Andric/// sext and zext 19540b57cec5SDimitry Andric 1955349cc55cSDimitry Andric// Sign extend is not needed if all users are W instructions. 1956349cc55cSDimitry Andricdef : Pat<(sexti32_allwusers GPR:$rs1), (XLenVT GPR:$rs1)>; 1957349cc55cSDimitry Andric 19580b57cec5SDimitry Andricdef : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>; 19590b57cec5SDimitry Andric 19600b57cec5SDimitry Andric/// ALU operations 19610b57cec5SDimitry Andric 1962fe6060f1SDimitry Andricdef : Pat<(i64 (srl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)), 1963e8d8bef9SDimitry Andric (SRLIW GPR:$rs1, uimm5:$shamt)>; 1964fe6060f1SDimitry Andricdef : Pat<(i64 (srl (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)), 1965e8d8bef9SDimitry Andric (SRLIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>; 19660b57cec5SDimitry Andricdef : Pat<(sra (sext_inreg GPR:$rs1, i32), uimm5:$shamt), 19670b57cec5SDimitry Andric (SRAIW GPR:$rs1, uimm5:$shamt)>; 1968fe6060f1SDimitry Andricdef : Pat<(i64 (sra (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)), 1969e8d8bef9SDimitry Andric (SRAIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>; 19700b57cec5SDimitry Andric 1971e8d8bef9SDimitry Andricdef : PatGprGpr<shiftopw<riscv_sllw>, SLLW>; 1972e8d8bef9SDimitry Andricdef : PatGprGpr<shiftopw<riscv_srlw>, SRLW>; 1973e8d8bef9SDimitry Andricdef : PatGprGpr<shiftopw<riscv_sraw>, SRAW>; 19740b57cec5SDimitry Andric 1975349cc55cSDimitry Andric// Select W instructions if only the lower 32 bits of the result are used. 1976349cc55cSDimitry Andricdef : PatGprGpr<binop_allwusers<add>, ADDW>; 1977349cc55cSDimitry Andricdef : PatGprSimm12<binop_allwusers<add>, ADDIW>; 1978349cc55cSDimitry Andricdef : PatGprGpr<binop_allwusers<sub>, SUBW>; 1979349cc55cSDimitry Andricdef : PatGprImm<binop_allwusers<shl>, SLLIW, uimm5>; 1980349cc55cSDimitry Andric 1981349cc55cSDimitry Andric// If this is a shr of a value sign extended from i32, and all the users only 1982349cc55cSDimitry Andric// use the lower 32 bits, we can use an sraiw to remove the sext_inreg. This 1983349cc55cSDimitry Andric// occurs because SimplifyDemandedBits prefers srl over sra. 1984349cc55cSDimitry Andricdef : Pat<(binop_allwusers<srl> (sext_inreg GPR:$rs1, i32), uimm5:$shamt), 1985349cc55cSDimitry Andric (SRAIW GPR:$rs1, uimm5:$shamt)>; 1986349cc55cSDimitry Andric 1987bdd1243dSDimitry Andric// Use binop_allwusers to recover immediates that may have been broken by 1988bdd1243dSDimitry Andric// SimplifyDemandedBits. 1989bdd1243dSDimitry Andricdef : Pat<(binop_allwusers<and> GPR:$rs1, u32simm12:$imm), 1990bdd1243dSDimitry Andric (ANDI GPR:$rs1, u32simm12:$imm)>; 1991bdd1243dSDimitry Andric 1992bdd1243dSDimitry Andricdef : Pat<(binop_allwusers<or> GPR:$rs1, u32simm12:$imm), 1993bdd1243dSDimitry Andric (ORI GPR:$rs1, u32simm12:$imm)>; 1994bdd1243dSDimitry Andric 1995bdd1243dSDimitry Andricdef : Pat<(binop_allwusers<xor> GPR:$rs1, u32simm12:$imm), 1996bdd1243dSDimitry Andric (XORI GPR:$rs1, u32simm12:$imm)>; 19970b57cec5SDimitry Andric/// Loads 19980b57cec5SDimitry Andric 199906c3fb27SDimitry Andricdef : LdPat<sextloadi32, LW, i64>; 200006c3fb27SDimitry Andricdef : LdPat<extloadi32, LW, i64>; 200106c3fb27SDimitry Andricdef : LdPat<zextloadi32, LWU, i64>; 200206c3fb27SDimitry Andricdef : LdPat<load, LD, i64>; 20030b57cec5SDimitry Andric 20040b57cec5SDimitry Andric/// Stores 20050b57cec5SDimitry Andric 200606c3fb27SDimitry Andricdef : StPat<truncstorei32, SW, GPR, i64>; 200706c3fb27SDimitry Andricdef : StPat<store, SD, GPR, i64>; 20080b57cec5SDimitry Andric} // Predicates = [IsRV64] 20090b57cec5SDimitry Andric 20100b57cec5SDimitry Andric/// readcyclecounter 20110b57cec5SDimitry Andric// On RV64, we can directly read the 64-bit "cycle" CSR. 20120b57cec5SDimitry Andriclet Predicates = [IsRV64] in 201306c3fb27SDimitry Andricdef : Pat<(i64 (readcyclecounter)), (CSRRS CYCLE.Encoding, (XLenVT X0))>; 20140b57cec5SDimitry Andric// On RV32, ReadCycleWide will be expanded to the suggested loop reading both 20150b57cec5SDimitry Andric// halves of the 64-bit "cycle" CSR. 2016e8d8bef9SDimitry Andriclet Predicates = [IsRV32], usesCustomInserter = 1, hasNoSchedulingInfo = 1 in 2017e8d8bef9SDimitry Andricdef ReadCycleWide : Pseudo<(outs GPR:$lo, GPR:$hi), (ins), 2018e8d8bef9SDimitry Andric [(set GPR:$lo, GPR:$hi, (riscv_read_cycle_wide))], 2019e8d8bef9SDimitry Andric "", "">; 20200b57cec5SDimitry Andric 2021480093f4SDimitry Andric/// traps 2022480093f4SDimitry Andric 2023480093f4SDimitry Andric// We lower `trap` to `unimp`, as this causes a hard exception on nearly all 2024480093f4SDimitry Andric// systems. 2025480093f4SDimitry Andricdef : Pat<(trap), (UNIMP)>; 2026480093f4SDimitry Andric 2027480093f4SDimitry Andric// We lower `debugtrap` to `ebreak`, as this will get the attention of the 2028480093f4SDimitry Andric// debugger if possible. 2029480093f4SDimitry Andricdef : Pat<(debugtrap), (EBREAK)>; 2030480093f4SDimitry Andric 2031bdd1243dSDimitry Andriclet Predicates = [IsRV64], Uses = [X5], 2032bdd1243dSDimitry Andric Defs = [X1, X6, X7, X28, X29, X30, X31] in 2033bdd1243dSDimitry Andricdef HWASAN_CHECK_MEMACCESS_SHORTGRANULES 2034bdd1243dSDimitry Andric : Pseudo<(outs), (ins GPRJALR:$ptr, i32imm:$accessinfo), 20355f757f3fSDimitry Andric [(int_hwasan_check_memaccess_shortgranules (i64 X5), GPRJALR:$ptr, 2036bdd1243dSDimitry Andric (i32 timm:$accessinfo))]>; 2037bdd1243dSDimitry Andric 203806c3fb27SDimitry Andric// This gets lowered into a 20-byte instruction sequence (at most) 203906c3fb27SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, 204006c3fb27SDimitry Andric Defs = [ X6, X7, X28, X29, X30, X31 ], Size = 20 in { 204106c3fb27SDimitry Andricdef KCFI_CHECK 204206c3fb27SDimitry Andric : Pseudo<(outs), (ins GPRJALR:$ptr, i32imm:$type), []>, Sched<[]>; 204306c3fb27SDimitry Andric} 204406c3fb27SDimitry Andric 2045fe6060f1SDimitry Andric/// Simple optimization 204606c3fb27SDimitry Andricdef : Pat<(XLenVT (add GPR:$rs1, (AddiPair:$rs2))), 204781ad6265SDimitry Andric (ADDI (ADDI GPR:$rs1, (AddiPairImmLarge AddiPair:$rs2)), 204881ad6265SDimitry Andric (AddiPairImmSmall GPR:$rs2))>; 2049fe6060f1SDimitry Andric 2050fe6060f1SDimitry Andriclet Predicates = [IsRV64] in { 2051349cc55cSDimitry Andric// Select W instructions if only the lower 32-bits of the result are used. 2052349cc55cSDimitry Andricdef : Pat<(binop_allwusers<add> GPR:$rs1, (AddiPair:$rs2)), 205381ad6265SDimitry Andric (ADDIW (ADDIW GPR:$rs1, (AddiPairImmLarge AddiPair:$rs2)), 205481ad6265SDimitry Andric (AddiPairImmSmall AddiPair:$rs2))>; 2055fe6060f1SDimitry Andric} 2056fe6060f1SDimitry Andric 20575f757f3fSDimitry Andriclet Predicates = [HasShortForwardBranchOpt] in 20585f757f3fSDimitry Andricdef : Pat<(XLenVT (abs GPR:$rs1)), 20595f757f3fSDimitry Andric (PseudoCCSUB (XLenVT GPR:$rs1), (XLenVT X0), /* COND_LT */ 2, 20605f757f3fSDimitry Andric (XLenVT GPR:$rs1), (XLenVT X0), (XLenVT GPR:$rs1))>; 20615f757f3fSDimitry Andriclet Predicates = [HasShortForwardBranchOpt, IsRV64] in 20625f757f3fSDimitry Andricdef : Pat<(sext_inreg (abs 33signbits_node:$rs1), i32), 20635f757f3fSDimitry Andric (PseudoCCSUBW (i64 GPR:$rs1), (i64 X0), /* COND_LT */ 2, 20645f757f3fSDimitry Andric (i64 GPR:$rs1), (i64 X0), (i64 GPR:$rs1))>; 20655f757f3fSDimitry Andric 20665f757f3fSDimitry Andric//===----------------------------------------------------------------------===// 20675f757f3fSDimitry Andric// Experimental RV64 i32 legalization patterns. 20685f757f3fSDimitry Andric//===----------------------------------------------------------------------===// 20695f757f3fSDimitry Andric 20705f757f3fSDimitry Andricdef simm12i32 : ImmLeaf<i32, [{return isInt<12>(Imm);}]>; 20715f757f3fSDimitry Andric 20725f757f3fSDimitry Andric// Convert from i32 immediate to i64 target immediate to make SelectionDAG type 20735f757f3fSDimitry Andric// checking happy so we can use ADDIW which expects an XLen immediate. 20745f757f3fSDimitry Andricdef as_i64imm : SDNodeXForm<imm, [{ 20755f757f3fSDimitry Andric return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i64); 20765f757f3fSDimitry Andric}]>; 20775f757f3fSDimitry Andric 20785f757f3fSDimitry Andricdef zext_is_sext : PatFrag<(ops node:$src), (zext node:$src), [{ 20795f757f3fSDimitry Andric KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0), 0); 20805f757f3fSDimitry Andric return Known.isNonNegative(); 20815f757f3fSDimitry Andric}]>; 20825f757f3fSDimitry Andric 20835f757f3fSDimitry Andriclet Predicates = [IsRV64] in { 20845f757f3fSDimitry Andricdef : LdPat<sextloadi8, LB, i32>; 20855f757f3fSDimitry Andricdef : LdPat<extloadi8, LBU, i32>; // Prefer unsigned due to no c.lb in Zcb. 20865f757f3fSDimitry Andricdef : LdPat<sextloadi16, LH, i32>; 20875f757f3fSDimitry Andricdef : LdPat<extloadi16, LH, i32>; 20885f757f3fSDimitry Andricdef : LdPat<zextloadi8, LBU, i32>; 20895f757f3fSDimitry Andricdef : LdPat<zextloadi16, LHU, i32>; 20905f757f3fSDimitry Andric 20915f757f3fSDimitry Andricdef : StPat<truncstorei8, SB, GPR, i32>; 20925f757f3fSDimitry Andricdef : StPat<truncstorei16, SH, GPR, i32>; 20935f757f3fSDimitry Andric 20945f757f3fSDimitry Andricdef : Pat<(anyext GPR:$src), (COPY GPR:$src)>; 20955f757f3fSDimitry Andricdef : Pat<(sext GPR:$src), (ADDIW GPR:$src, 0)>; 20965f757f3fSDimitry Andricdef : Pat<(trunc GPR:$src), (COPY GPR:$src)>; 20975f757f3fSDimitry Andric 20985f757f3fSDimitry Andricdef : PatGprGpr<add, ADDW, i32, i32>; 20995f757f3fSDimitry Andricdef : PatGprGpr<sub, SUBW, i32, i32>; 21005f757f3fSDimitry Andricdef : PatGprGpr<and, AND, i32, i32>; 21015f757f3fSDimitry Andricdef : PatGprGpr<or, OR, i32, i32>; 21025f757f3fSDimitry Andricdef : PatGprGpr<xor, XOR, i32, i32>; 21035f757f3fSDimitry Andricdef : PatGprGpr<shiftopw<shl>, SLLW, i32, i64>; 21045f757f3fSDimitry Andricdef : PatGprGpr<shiftopw<srl>, SRLW, i32, i64>; 21055f757f3fSDimitry Andricdef : PatGprGpr<shiftopw<sra>, SRAW, i32, i64>; 21065f757f3fSDimitry Andric 21075f757f3fSDimitry Andricdef : Pat<(i32 (add GPR:$rs1, simm12i32:$imm)), 21085f757f3fSDimitry Andric (ADDIW GPR:$rs1, (i64 (as_i64imm $imm)))>; 21095f757f3fSDimitry Andricdef : Pat<(i32 (and GPR:$rs1, simm12i32:$imm)), 21105f757f3fSDimitry Andric (ANDI GPR:$rs1, (i64 (as_i64imm $imm)))>; 21115f757f3fSDimitry Andricdef : Pat<(i32 (or GPR:$rs1, simm12i32:$imm)), 21125f757f3fSDimitry Andric (ORI GPR:$rs1, (i64 (as_i64imm $imm)))>; 21135f757f3fSDimitry Andricdef : Pat<(i32 (xor GPR:$rs1, simm12i32:$imm)), 21145f757f3fSDimitry Andric (XORI GPR:$rs1, (i64 (as_i64imm $imm)))>; 21155f757f3fSDimitry Andric 21165f757f3fSDimitry Andricdef : PatGprImm<shl, SLLIW, uimm5, i32>; 21175f757f3fSDimitry Andricdef : PatGprImm<srl, SRLIW, uimm5, i32>; 21185f757f3fSDimitry Andricdef : PatGprImm<sra, SRAIW, uimm5, i32>; 21195f757f3fSDimitry Andric 21205f757f3fSDimitry Andricdef : Pat<(i32 (and GPR:$rs, TrailingOnesMask:$mask)), 21215f757f3fSDimitry Andric (SRLI (SLLI $rs, (i64 (XLenSubTrailingOnes $mask))), 21225f757f3fSDimitry Andric (i64 (XLenSubTrailingOnes $mask)))>; 21235f757f3fSDimitry Andric 21245f757f3fSDimitry Andric// Use sext if the sign bit of the input is 0. 21255f757f3fSDimitry Andricdef : Pat<(zext_is_sext GPR:$src), (ADDIW GPR:$src, 0)>; 21265f757f3fSDimitry Andric} 21275f757f3fSDimitry Andric 21285f757f3fSDimitry Andriclet Predicates = [IsRV64, NotHasStdExtZba] in { 21295f757f3fSDimitry Andricdef : Pat<(zext GPR:$src), (SRLI (SLLI GPR:$src, 32), 32)>; 21305f757f3fSDimitry Andric 21315f757f3fSDimitry Andric// If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2 21325f757f3fSDimitry Andric// shifts instead of 3. This can occur when unsigned is used to index an array. 21335f757f3fSDimitry Andricdef : Pat<(shl (zext GPR:$rs), uimm5:$shamt), 21345f757f3fSDimitry Andric (SRLI (SLLI GPR:$rs, 32), (ImmSubFrom32 uimm5:$shamt))>; 21355f757f3fSDimitry Andric} 21365f757f3fSDimitry Andric 21370b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 21380b57cec5SDimitry Andric// Standard extensions 21390b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 21400b57cec5SDimitry Andric 214106c3fb27SDimitry Andric// Multiply and Division 21420b57cec5SDimitry Andricinclude "RISCVInstrInfoM.td" 214306c3fb27SDimitry Andric 214406c3fb27SDimitry Andric// Atomic 21450b57cec5SDimitry Andricinclude "RISCVInstrInfoA.td" 21461db9f3b2SDimitry Andricinclude "RISCVInstrInfoZa.td" 214706c3fb27SDimitry Andric 214806c3fb27SDimitry Andric// Scalar FP 21490b57cec5SDimitry Andricinclude "RISCVInstrInfoF.td" 21500b57cec5SDimitry Andricinclude "RISCVInstrInfoD.td" 215106c3fb27SDimitry Andricinclude "RISCVInstrInfoZfh.td" 215206c3fb27SDimitry Andricinclude "RISCVInstrInfoZfbfmin.td" 215306c3fb27SDimitry Andricinclude "RISCVInstrInfoZfa.td" 215406c3fb27SDimitry Andric 215506c3fb27SDimitry Andric// Scalar bitmanip and cryptography 2156349cc55cSDimitry Andricinclude "RISCVInstrInfoZb.td" 215704eeddc0SDimitry Andricinclude "RISCVInstrInfoZk.td" 215806c3fb27SDimitry Andric 215906c3fb27SDimitry Andric// Vector 21605ffd83dbSDimitry Andricinclude "RISCVInstrInfoV.td" 216106c3fb27SDimitry Andricinclude "RISCVInstrInfoZvk.td" 216206c3fb27SDimitry Andric 216306c3fb27SDimitry Andric// Compressed 216406c3fb27SDimitry Andricinclude "RISCVInstrInfoC.td" 216506c3fb27SDimitry Andricinclude "RISCVInstrInfoZc.td" 2166647cbc5dSDimitry Andricinclude "RISCVInstrInfoZcmop.td" 2167647cbc5dSDimitry Andric 2168647cbc5dSDimitry Andric// Integer 2169647cbc5dSDimitry Andricinclude "RISCVInstrInfoZimop.td" 2170647cbc5dSDimitry Andricinclude "RISCVInstrInfoZicbo.td" 2171647cbc5dSDimitry Andricinclude "RISCVInstrInfoZicond.td" 2172647cbc5dSDimitry Andricinclude "RISCVInstrInfoZicfiss.td" 2173bdd1243dSDimitry Andric 2174bdd1243dSDimitry Andric//===----------------------------------------------------------------------===// 2175bdd1243dSDimitry Andric// Vendor extensions 2176bdd1243dSDimitry Andric//===----------------------------------------------------------------------===// 2177bdd1243dSDimitry Andric 2178bdd1243dSDimitry Andricinclude "RISCVInstrInfoXVentana.td" 2179bdd1243dSDimitry Andricinclude "RISCVInstrInfoXTHead.td" 218006c3fb27SDimitry Andricinclude "RISCVInstrInfoXSf.td" 218106c3fb27SDimitry Andricinclude "RISCVInstrInfoXCV.td" 21825f757f3fSDimitry Andric 21835f757f3fSDimitry Andric//===----------------------------------------------------------------------===// 21845f757f3fSDimitry Andric// Global ISel 21855f757f3fSDimitry Andric//===----------------------------------------------------------------------===// 21865f757f3fSDimitry Andric 21875f757f3fSDimitry Andricinclude "RISCVInstrGISel.td" 2188