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>]>; 36*0fca6ea1SDimitry Andricdef SDT_RISCVReadCounterWide : SDTypeProfile<2, 2, [SDTCisVT<0, i32>, 37*0fca6ea1SDimitry Andric SDTCisVT<1, i32>, 38*0fca6ea1SDimitry Andric SDTCisInt<2>, 39*0fca6ea1SDimitry Andric SDTCisInt<3>]>; 40fe6060f1SDimitry Andricdef SDT_RISCVIntUnaryOpW : SDTypeProfile<1, 1, [ 41fe6060f1SDimitry Andric SDTCisSameAs<0, 1>, SDTCisVT<0, i64> 42fe6060f1SDimitry Andric]>; 43fe6060f1SDimitry Andricdef SDT_RISCVIntBinOpW : SDTypeProfile<1, 2, [ 44fe6060f1SDimitry Andric SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64> 45fe6060f1SDimitry Andric]>; 46fe6060f1SDimitry Andricdef SDT_RISCVIntShiftDOpW : SDTypeProfile<1, 3, [ 47fe6060f1SDimitry Andric SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64>, SDTCisVT<3, i64> 48fe6060f1SDimitry Andric]>; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric// Target-independent nodes, but with target-specific formats. 510b57cec5SDimitry Andricdef callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart, 520b57cec5SDimitry Andric [SDNPHasChain, SDNPOutGlue]>; 530b57cec5SDimitry Andricdef callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd, 540b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric// Target-dependent nodes. 570b57cec5SDimitry Andricdef riscv_call : SDNode<"RISCVISD::CALL", SDT_RISCVCall, 580b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 590b57cec5SDimitry Andric SDNPVariadic]>; 6006c3fb27SDimitry Andricdef riscv_ret_glue : SDNode<"RISCVISD::RET_GLUE", SDTNone, 610b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; 6206c3fb27SDimitry Andricdef riscv_sret_glue : SDNode<"RISCVISD::SRET_GLUE", SDTNone, 630b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue]>; 6406c3fb27SDimitry Andricdef riscv_mret_glue : SDNode<"RISCVISD::MRET_GLUE", SDTNone, 650b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue]>; 66e8d8bef9SDimitry Andricdef riscv_selectcc : SDNode<"RISCVISD::SELECT_CC", SDT_RISCVSelectCC>; 67fe6060f1SDimitry Andricdef riscv_brcc : SDNode<"RISCVISD::BR_CC", SDT_RISCVBrCC, 68fe6060f1SDimitry Andric [SDNPHasChain]>; 690b57cec5SDimitry Andricdef riscv_tail : SDNode<"RISCVISD::TAIL", SDT_RISCVCall, 700b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 710b57cec5SDimitry Andric SDNPVariadic]>; 72*0fca6ea1SDimitry Andricdef riscv_sw_guarded_brind : SDNode<"RISCVISD::SW_GUARDED_BRIND", 73*0fca6ea1SDimitry Andric SDTBrind, [SDNPHasChain]>; 74fe6060f1SDimitry Andricdef riscv_sllw : SDNode<"RISCVISD::SLLW", SDT_RISCVIntBinOpW>; 75fe6060f1SDimitry Andricdef riscv_sraw : SDNode<"RISCVISD::SRAW", SDT_RISCVIntBinOpW>; 76fe6060f1SDimitry Andricdef riscv_srlw : SDNode<"RISCVISD::SRLW", SDT_RISCVIntBinOpW>; 77fe6060f1SDimitry Andricdef riscv_read_csr : SDNode<"RISCVISD::READ_CSR", SDT_RISCVReadCSR, 78fe6060f1SDimitry Andric [SDNPHasChain]>; 79fe6060f1SDimitry Andricdef riscv_write_csr : SDNode<"RISCVISD::WRITE_CSR", SDT_RISCVWriteCSR, 80fe6060f1SDimitry Andric [SDNPHasChain]>; 81fe6060f1SDimitry Andricdef riscv_swap_csr : SDNode<"RISCVISD::SWAP_CSR", SDT_RISCVSwapCSR, 82fe6060f1SDimitry Andric [SDNPHasChain]>; 830b57cec5SDimitry Andric 84*0fca6ea1SDimitry Andricdef riscv_read_counter_wide : SDNode<"RISCVISD::READ_COUNTER_WIDE", 85*0fca6ea1SDimitry Andric SDT_RISCVReadCounterWide, 86e8d8bef9SDimitry Andric [SDNPHasChain, SDNPSideEffect]>; 87e8d8bef9SDimitry Andric 8881ad6265SDimitry Andricdef riscv_add_lo : SDNode<"RISCVISD::ADD_LO", SDTIntBinOp>; 8981ad6265SDimitry Andricdef riscv_hi : SDNode<"RISCVISD::HI", SDTIntUnaryOp>; 9081ad6265SDimitry Andricdef riscv_lla : SDNode<"RISCVISD::LLA", SDTIntUnaryOp>; 9181ad6265SDimitry Andricdef riscv_add_tprel : SDNode<"RISCVISD::ADD_TPREL", 9281ad6265SDimitry Andric SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, 9381ad6265SDimitry Andric SDTCisSameAs<0, 2>, 9481ad6265SDimitry Andric SDTCisSameAs<0, 3>, 9581ad6265SDimitry Andric SDTCisInt<0>]>>; 9681ad6265SDimitry Andric 970b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 980b57cec5SDimitry Andric// Operand and SDNode transformation definitions. 990b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andricclass ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass { 1020b57cec5SDimitry Andric let Name = prefix # "ImmXLen" # suffix; 1030b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 1040b57cec5SDimitry Andric let DiagnosticType = !strconcat("Invalid", Name); 1050b57cec5SDimitry Andric} 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andricclass ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass { 1080b57cec5SDimitry Andric let Name = prefix # "Imm" # width # suffix; 1090b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 1100b57cec5SDimitry Andric let DiagnosticType = !strconcat("Invalid", Name); 1110b57cec5SDimitry Andric} 1120b57cec5SDimitry Andric 1138bcb0991SDimitry Andricdef ImmZeroAsmOperand : AsmOperandClass { 1148bcb0991SDimitry Andric let Name = "ImmZero"; 1158bcb0991SDimitry Andric let RenderMethod = "addImmOperands"; 1168bcb0991SDimitry Andric let DiagnosticType = !strconcat("Invalid", Name); 1178bcb0991SDimitry Andric} 1188bcb0991SDimitry Andric 11981ad6265SDimitry Andric// A parse method for (${gpr}) or 0(${gpr}), where the 0 is be silently ignored. 12081ad6265SDimitry Andricdef ZeroOffsetMemOpOperand : AsmOperandClass { 12181ad6265SDimitry Andric let Name = "ZeroOffsetMemOpOperand"; 12281ad6265SDimitry Andric let RenderMethod = "addRegOperands"; 12381ad6265SDimitry Andric let PredicateMethod = "isGPR"; 12481ad6265SDimitry Andric let ParserMethod = "parseZeroOffsetMemOp"; 12581ad6265SDimitry Andric} 12681ad6265SDimitry Andric 127bdd1243dSDimitry Andricclass MemOperand<RegisterClass regClass> : RegisterOperand<regClass>{ 128bdd1243dSDimitry Andric let OperandType = "OPERAND_MEMORY"; 129bdd1243dSDimitry Andric} 130bdd1243dSDimitry Andric 131bdd1243dSDimitry Andricdef GPRMemZeroOffset : MemOperand<GPR> { 13281ad6265SDimitry Andric let ParserMatchClass = ZeroOffsetMemOpOperand; 13381ad6265SDimitry Andric let PrintMethod = "printZeroOffsetMemOp"; 13481ad6265SDimitry Andric} 13581ad6265SDimitry Andric 136bdd1243dSDimitry Andricdef GPRMem : MemOperand<GPR>; 137bdd1243dSDimitry Andric 138bdd1243dSDimitry Andricdef SPMem : MemOperand<SP>; 139bdd1243dSDimitry Andric 140bdd1243dSDimitry Andricdef GPRCMem : MemOperand<GPRC>; 141bdd1243dSDimitry Andric 1420b57cec5SDimitry Andricclass SImmAsmOperand<int width, string suffix = ""> 1430b57cec5SDimitry Andric : ImmAsmOperand<"S", width, suffix> { 1440b57cec5SDimitry Andric} 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andricclass UImmAsmOperand<int width, string suffix = ""> 1470b57cec5SDimitry Andric : ImmAsmOperand<"U", width, suffix> { 1480b57cec5SDimitry Andric} 1490b57cec5SDimitry Andric 1505f757f3fSDimitry Andricclass RISCVOp<ValueType vt = XLenVT> : Operand<vt> { 1515f757f3fSDimitry Andric let OperandNamespace = "RISCVOp"; 1525f757f3fSDimitry Andric} 1535f757f3fSDimitry Andric 1545f757f3fSDimitry Andricclass RISCVUImmOp<int bitsNum> : RISCVOp { 1555f757f3fSDimitry Andric let ParserMatchClass = UImmAsmOperand<bitsNum>; 1565f757f3fSDimitry Andric let DecoderMethod = "decodeUImmOperand<" # bitsNum # ">"; 1575f757f3fSDimitry Andric let OperandType = "OPERAND_UIMM" # bitsNum; 1585f757f3fSDimitry Andric} 1595f757f3fSDimitry Andric 1605f757f3fSDimitry Andricclass RISCVUImmLeafOp<int bitsNum> : 1615f757f3fSDimitry Andric RISCVUImmOp<bitsNum>, ImmLeaf<XLenVT, "return isUInt<" # bitsNum # ">(Imm);">; 1625f757f3fSDimitry Andric 1635f757f3fSDimitry Andricclass RISCVSImmOp<int bitsNum> : RISCVOp { 1645f757f3fSDimitry Andric let ParserMatchClass = SImmAsmOperand<bitsNum>; 1655f757f3fSDimitry Andric let EncoderMethod = "getImmOpValue"; 1665f757f3fSDimitry Andric let DecoderMethod = "decodeSImmOperand<" # bitsNum # ">"; 1675f757f3fSDimitry Andric let OperandType = "OPERAND_SIMM" # bitsNum; 1685f757f3fSDimitry Andric} 1695f757f3fSDimitry Andric 1705f757f3fSDimitry Andricclass RISCVSImmLeafOp<int bitsNum> : 1715f757f3fSDimitry Andric RISCVSImmOp<bitsNum>, ImmLeaf<XLenVT, "return isInt<" # bitsNum # ">(Imm);">; 1725f757f3fSDimitry Andric 1730b57cec5SDimitry Andricdef FenceArg : AsmOperandClass { 1740b57cec5SDimitry Andric let Name = "FenceArg"; 1750b57cec5SDimitry Andric let RenderMethod = "addFenceArgOperands"; 17606c3fb27SDimitry Andric let ParserMethod = "parseFenceArg"; 1770b57cec5SDimitry Andric} 1780b57cec5SDimitry Andric 1795f757f3fSDimitry Andricdef fencearg : RISCVOp { 1800b57cec5SDimitry Andric let ParserMatchClass = FenceArg; 1810b57cec5SDimitry Andric let PrintMethod = "printFenceArg"; 1820b57cec5SDimitry Andric let DecoderMethod = "decodeUImmOperand<4>"; 1838bcb0991SDimitry Andric let OperandType = "OPERAND_UIMM4"; 1840b57cec5SDimitry Andric} 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andricdef UImmLog2XLenAsmOperand : AsmOperandClass { 1870b57cec5SDimitry Andric let Name = "UImmLog2XLen"; 1880b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 1890b57cec5SDimitry Andric let DiagnosticType = "InvalidUImmLog2XLen"; 1900b57cec5SDimitry Andric} 1910b57cec5SDimitry Andric 1925f757f3fSDimitry Andricdef uimmlog2xlen : RISCVOp, ImmLeaf<XLenVT, [{ 1930b57cec5SDimitry Andric if (Subtarget->is64Bit()) 1940b57cec5SDimitry Andric return isUInt<6>(Imm); 1950b57cec5SDimitry Andric return isUInt<5>(Imm); 1960b57cec5SDimitry Andric}]> { 1970b57cec5SDimitry Andric let ParserMatchClass = UImmLog2XLenAsmOperand; 1980b57cec5SDimitry Andric // TODO: should ensure invalid shamt is rejected when decoding. 1990b57cec5SDimitry Andric let DecoderMethod = "decodeUImmOperand<6>"; 2000b57cec5SDimitry Andric let MCOperandPredicate = [{ 2010b57cec5SDimitry Andric int64_t Imm; 2020b57cec5SDimitry Andric if (!MCOp.evaluateAsConstantImm(Imm)) 2030b57cec5SDimitry Andric return false; 2040b57cec5SDimitry Andric if (STI.getTargetTriple().isArch64Bit()) 2050b57cec5SDimitry Andric return isUInt<6>(Imm); 2060b57cec5SDimitry Andric return isUInt<5>(Imm); 2070b57cec5SDimitry Andric }]; 2088bcb0991SDimitry Andric let OperandType = "OPERAND_UIMMLOG2XLEN"; 2090b57cec5SDimitry Andric} 2100b57cec5SDimitry Andric 2110eae32dcSDimitry Andricdef InsnDirectiveOpcode : AsmOperandClass { 2120eae32dcSDimitry Andric let Name = "InsnDirectiveOpcode"; 2130eae32dcSDimitry Andric let ParserMethod = "parseInsnDirectiveOpcode"; 2140eae32dcSDimitry Andric let RenderMethod = "addImmOperands"; 2150eae32dcSDimitry Andric let PredicateMethod = "isImm"; 2160eae32dcSDimitry Andric} 2170eae32dcSDimitry Andric 2185f757f3fSDimitry Andricdef uimm1 : RISCVUImmLeafOp<1>; 2195f757f3fSDimitry Andricdef uimm2 : RISCVUImmLeafOp<2> { 2205f757f3fSDimitry Andric let MCOperandPredicate = [{ 2215f757f3fSDimitry Andric int64_t Imm; 2225f757f3fSDimitry Andric if (!MCOp.evaluateAsConstantImm(Imm)) 2235f757f3fSDimitry Andric return false; 2245f757f3fSDimitry Andric return isUInt<2>(Imm); 2255f757f3fSDimitry Andric }]; 22606c3fb27SDimitry Andric} 2275f757f3fSDimitry Andricdef uimm3 : RISCVUImmOp<3>; 2285f757f3fSDimitry Andricdef uimm4 : RISCVUImmOp<4>; 2295f757f3fSDimitry Andricdef uimm5 : RISCVUImmLeafOp<5>; 2305f757f3fSDimitry Andricdef uimm6 : RISCVUImmLeafOp<6>; 2315f757f3fSDimitry Andricdef uimm7_opcode : RISCVUImmOp<7> { 2320eae32dcSDimitry Andric let ParserMatchClass = InsnDirectiveOpcode; 2330eae32dcSDimitry Andric} 2345f757f3fSDimitry Andricdef uimm7 : RISCVUImmOp<7>; 2355f757f3fSDimitry Andricdef uimm8 : RISCVUImmOp<8>; 236*0fca6ea1SDimitry Andricdef uimm16 : RISCVUImmOp<16>; 237*0fca6ea1SDimitry Andricdef uimm32 : RISCVUImmOp<32>; 2385f757f3fSDimitry Andricdef simm12 : RISCVSImmLeafOp<12> { 2390b57cec5SDimitry Andric let MCOperandPredicate = [{ 2400b57cec5SDimitry Andric int64_t Imm; 2410b57cec5SDimitry Andric if (MCOp.evaluateAsConstantImm(Imm)) 2420b57cec5SDimitry Andric return isInt<12>(Imm); 2430b57cec5SDimitry Andric return MCOp.isBareSymbolRef(); 2440b57cec5SDimitry Andric }]; 2450b57cec5SDimitry Andric} 2460b57cec5SDimitry Andric 247bdd1243dSDimitry Andric// A 12-bit signed immediate which cannot fit in 6-bit signed immediate, 248bdd1243dSDimitry Andric// but even negative value fit in 12-bit. 249bdd1243dSDimitry Andricdef simm12_no6 : ImmLeaf<XLenVT, [{ 250bdd1243dSDimitry Andric return isInt<12>(Imm) && !isInt<6>(Imm) && isInt<12>(-Imm);}]>; 251bdd1243dSDimitry Andric 2520b57cec5SDimitry Andric// A 13-bit signed immediate where the least significant bit is zero. 2530b57cec5SDimitry Andricdef simm13_lsb0 : Operand<OtherVT> { 2540b57cec5SDimitry Andric let ParserMatchClass = SImmAsmOperand<13, "Lsb0">; 255e8d8bef9SDimitry Andric let PrintMethod = "printBranchOperand"; 2560b57cec5SDimitry Andric let EncoderMethod = "getImmOpValueAsr1"; 2570b57cec5SDimitry Andric let DecoderMethod = "decodeSImmOperandAndLsl1<13>"; 2580b57cec5SDimitry Andric let MCOperandPredicate = [{ 2590b57cec5SDimitry Andric int64_t Imm; 2600b57cec5SDimitry Andric if (MCOp.evaluateAsConstantImm(Imm)) 2610b57cec5SDimitry Andric return isShiftedInt<12, 1>(Imm); 2620b57cec5SDimitry Andric return MCOp.isBareSymbolRef(); 2630b57cec5SDimitry Andric }]; 264e8d8bef9SDimitry Andric let OperandType = "OPERAND_PCREL"; 2650b57cec5SDimitry Andric} 2660b57cec5SDimitry Andric 2675f757f3fSDimitry Andricclass UImm20Operand : RISCVOp { 2680b57cec5SDimitry Andric let EncoderMethod = "getImmOpValue"; 2690b57cec5SDimitry Andric let DecoderMethod = "decodeUImmOperand<20>"; 2705f757f3fSDimitry Andric let OperandType = "OPERAND_UIMM20"; 2715f757f3fSDimitry Andric} 2725f757f3fSDimitry Andric 2735f757f3fSDimitry Andricclass UImm20OperandMaybeSym : UImm20Operand { 2740b57cec5SDimitry Andric let MCOperandPredicate = [{ 2750b57cec5SDimitry Andric int64_t Imm; 2760b57cec5SDimitry Andric if (MCOp.evaluateAsConstantImm(Imm)) 2770b57cec5SDimitry Andric return isUInt<20>(Imm); 2780b57cec5SDimitry Andric return MCOp.isBareSymbolRef(); 2790b57cec5SDimitry Andric }]; 2800b57cec5SDimitry Andric} 2810b57cec5SDimitry Andric 2825f757f3fSDimitry Andricdef uimm20_lui : UImm20OperandMaybeSym { 2830b57cec5SDimitry Andric let ParserMatchClass = UImmAsmOperand<20, "LUI">; 2840b57cec5SDimitry Andric} 2855f757f3fSDimitry Andricdef uimm20_auipc : UImm20OperandMaybeSym { 2860b57cec5SDimitry Andric let ParserMatchClass = UImmAsmOperand<20, "AUIPC">; 2870b57cec5SDimitry Andric} 2880b57cec5SDimitry Andric 2895f757f3fSDimitry Andricdef uimm20 : UImm20Operand { 2905f757f3fSDimitry Andric let ParserMatchClass = UImmAsmOperand<20>; 2915f757f3fSDimitry Andric let MCOperandPredicate = [{ 2925f757f3fSDimitry Andric int64_t Imm; 2935f757f3fSDimitry Andric if (!MCOp.evaluateAsConstantImm(Imm)) 2945f757f3fSDimitry Andric return false; 2955f757f3fSDimitry Andric return isUInt<20>(Imm); 2965f757f3fSDimitry Andric }]; 2975f757f3fSDimitry Andric} 2985f757f3fSDimitry Andric 2990b57cec5SDimitry Andricdef Simm21Lsb0JALAsmOperand : SImmAsmOperand<21, "Lsb0JAL"> { 3000b57cec5SDimitry Andric let ParserMethod = "parseJALOffset"; 3010b57cec5SDimitry Andric} 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric// A 21-bit signed immediate where the least significant bit is zero. 3040b57cec5SDimitry Andricdef simm21_lsb0_jal : Operand<OtherVT> { 3050b57cec5SDimitry Andric let ParserMatchClass = Simm21Lsb0JALAsmOperand; 306e8d8bef9SDimitry Andric let PrintMethod = "printBranchOperand"; 3070b57cec5SDimitry Andric let EncoderMethod = "getImmOpValueAsr1"; 3080b57cec5SDimitry Andric let DecoderMethod = "decodeSImmOperandAndLsl1<21>"; 3090b57cec5SDimitry Andric let MCOperandPredicate = [{ 3100b57cec5SDimitry Andric int64_t Imm; 3110b57cec5SDimitry Andric if (MCOp.evaluateAsConstantImm(Imm)) 3120b57cec5SDimitry Andric return isShiftedInt<20, 1>(Imm); 3130b57cec5SDimitry Andric return MCOp.isBareSymbolRef(); 3140b57cec5SDimitry Andric }]; 315e8d8bef9SDimitry Andric let OperandType = "OPERAND_PCREL"; 3160b57cec5SDimitry Andric} 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andricdef BareSymbol : AsmOperandClass { 3190b57cec5SDimitry Andric let Name = "BareSymbol"; 3200b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 3210b57cec5SDimitry Andric let DiagnosticType = "InvalidBareSymbol"; 3220b57cec5SDimitry Andric let ParserMethod = "parseBareSymbol"; 3230b57cec5SDimitry Andric} 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric// A bare symbol. 3260b57cec5SDimitry Andricdef bare_symbol : Operand<XLenVT> { 3270b57cec5SDimitry Andric let ParserMatchClass = BareSymbol; 3280b57cec5SDimitry Andric} 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andricdef CallSymbol : AsmOperandClass { 3310b57cec5SDimitry Andric let Name = "CallSymbol"; 3320b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 3330b57cec5SDimitry Andric let DiagnosticType = "InvalidCallSymbol"; 3340b57cec5SDimitry Andric let ParserMethod = "parseCallSymbol"; 3350b57cec5SDimitry Andric} 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric// A bare symbol used in call/tail only. 3380b57cec5SDimitry Andricdef call_symbol : Operand<XLenVT> { 3390b57cec5SDimitry Andric let ParserMatchClass = CallSymbol; 3400b57cec5SDimitry Andric} 3410b57cec5SDimitry Andric 3425ffd83dbSDimitry Andricdef PseudoJumpSymbol : AsmOperandClass { 3435ffd83dbSDimitry Andric let Name = "PseudoJumpSymbol"; 3445ffd83dbSDimitry Andric let RenderMethod = "addImmOperands"; 3455ffd83dbSDimitry Andric let DiagnosticType = "InvalidPseudoJumpSymbol"; 3465ffd83dbSDimitry Andric let ParserMethod = "parsePseudoJumpSymbol"; 3475ffd83dbSDimitry Andric} 3485ffd83dbSDimitry Andric 3495ffd83dbSDimitry Andric// A bare symbol used for pseudo jumps only. 3505ffd83dbSDimitry Andricdef pseudo_jump_symbol : Operand<XLenVT> { 3515ffd83dbSDimitry Andric let ParserMatchClass = PseudoJumpSymbol; 3525ffd83dbSDimitry Andric} 3535ffd83dbSDimitry Andric 3540b57cec5SDimitry Andricdef TPRelAddSymbol : AsmOperandClass { 3550b57cec5SDimitry Andric let Name = "TPRelAddSymbol"; 3560b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 3570b57cec5SDimitry Andric let DiagnosticType = "InvalidTPRelAddSymbol"; 3580b57cec5SDimitry Andric let ParserMethod = "parseOperandWithModifier"; 3590b57cec5SDimitry Andric} 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric// A bare symbol with the %tprel_add variant. 3620b57cec5SDimitry Andricdef tprel_add_symbol : Operand<XLenVT> { 3630b57cec5SDimitry Andric let ParserMatchClass = TPRelAddSymbol; 3640b57cec5SDimitry Andric} 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andricdef CSRSystemRegister : AsmOperandClass { 3670b57cec5SDimitry Andric let Name = "CSRSystemRegister"; 3680b57cec5SDimitry Andric let ParserMethod = "parseCSRSystemRegister"; 3690b57cec5SDimitry Andric let DiagnosticType = "InvalidCSRSystemRegister"; 3700b57cec5SDimitry Andric} 3710b57cec5SDimitry Andric 372*0fca6ea1SDimitry Andricdef csr_sysreg : RISCVOp, TImmLeaf<XLenVT, "return isUInt<12>(Imm);"> { 3730b57cec5SDimitry Andric let ParserMatchClass = CSRSystemRegister; 3740b57cec5SDimitry Andric let PrintMethod = "printCSRSystemRegister"; 3750b57cec5SDimitry Andric let DecoderMethod = "decodeUImmOperand<12>"; 3768bcb0991SDimitry Andric let OperandType = "OPERAND_UIMM12"; 3770b57cec5SDimitry Andric} 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric// A parameterized register class alternative to i32imm/i64imm from Target.td. 3800b57cec5SDimitry Andricdef ixlenimm : Operand<XLenVT>; 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andricdef ixlenimm_li : Operand<XLenVT> { 3830b57cec5SDimitry Andric let ParserMatchClass = ImmXLenAsmOperand<"", "LI">; 3840b57cec5SDimitry Andric} 3850b57cec5SDimitry Andric 38606c3fb27SDimitry Andric// Accepts subset of LI operands, used by LAImm and LLAImm 38706c3fb27SDimitry Andricdef ixlenimm_li_restricted : Operand<XLenVT> { 38806c3fb27SDimitry Andric let ParserMatchClass = ImmXLenAsmOperand<"", "LI_Restricted">; 38906c3fb27SDimitry Andric} 390fe6060f1SDimitry Andric 39106c3fb27SDimitry Andric// Standalone (codegen-only) immleaf patterns. 3920b57cec5SDimitry Andric 393e8d8bef9SDimitry Andric// A 6-bit constant greater than 32. 394e8d8bef9SDimitry Andricdef uimm6gt32 : ImmLeaf<XLenVT, [{ 395e8d8bef9SDimitry Andric return isUInt<6>(Imm) && Imm > 32; 396e8d8bef9SDimitry Andric}]>; 397e8d8bef9SDimitry Andric 3980b57cec5SDimitry Andric// Addressing modes. 3990b57cec5SDimitry Andric// Necessary because a frameindex can't be matched directly in a pattern. 40081ad6265SDimitry Andricdef FrameAddrRegImm : ComplexPattern<iPTR, 2, "SelectFrameAddrRegImm", 40181ad6265SDimitry Andric [frameindex, or, add]>; 40281ad6265SDimitry Andricdef AddrRegImm : ComplexPattern<iPTR, 2, "SelectAddrRegImm">; 4030b57cec5SDimitry Andric 4045ffd83dbSDimitry Andric// Return the negation of an immediate value. 4055ffd83dbSDimitry Andricdef NegImm : SDNodeXForm<imm, [{ 4065ffd83dbSDimitry Andric return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N), 4075ffd83dbSDimitry Andric N->getValueType(0)); 4085ffd83dbSDimitry Andric}]>; 4095ffd83dbSDimitry Andric 410e8d8bef9SDimitry Andric// Return an immediate value minus 32. 411e8d8bef9SDimitry Andricdef ImmSub32 : SDNodeXForm<imm, [{ 412e8d8bef9SDimitry Andric return CurDAG->getTargetConstant(N->getSExtValue() - 32, SDLoc(N), 413e8d8bef9SDimitry Andric N->getValueType(0)); 414e8d8bef9SDimitry Andric}]>; 415e8d8bef9SDimitry Andric 416e8d8bef9SDimitry Andric// Return an immediate subtracted from XLen. 417e8d8bef9SDimitry Andricdef ImmSubFromXLen : SDNodeXForm<imm, [{ 418e8d8bef9SDimitry Andric uint64_t XLen = Subtarget->getXLen(); 419e8d8bef9SDimitry Andric return CurDAG->getTargetConstant(XLen - N->getZExtValue(), SDLoc(N), 420e8d8bef9SDimitry Andric N->getValueType(0)); 421e8d8bef9SDimitry Andric}]>; 422e8d8bef9SDimitry Andric 423e8d8bef9SDimitry Andric// Return an immediate subtracted from 32. 424e8d8bef9SDimitry Andricdef ImmSubFrom32 : SDNodeXForm<imm, [{ 425e8d8bef9SDimitry Andric return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N), 426e8d8bef9SDimitry Andric N->getValueType(0)); 427e8d8bef9SDimitry Andric}]>; 428e8d8bef9SDimitry Andric 429fe6060f1SDimitry Andric// Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1), 43081ad6265SDimitry Andric// in which imm = imm0 + imm1 and both imm0 and imm1 are simm12. We make imm0 43181ad6265SDimitry Andric// as large as possible and imm1 as small as possible so that we might be able 43281ad6265SDimitry Andric// to use c.addi for the small immediate. 433fe6060f1SDimitry Andricdef AddiPair : PatLeaf<(imm), [{ 434fe6060f1SDimitry Andric if (!N->hasOneUse()) 435fe6060f1SDimitry Andric return false; 436fe6060f1SDimitry Andric // The immediate operand must be in range [-4096,-2049] or [2048,4094]. 437fe6060f1SDimitry Andric int64_t Imm = N->getSExtValue(); 438fe6060f1SDimitry Andric return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094); 439fe6060f1SDimitry Andric}]>; 440fe6060f1SDimitry Andric 44181ad6265SDimitry Andric// Return imm - (imm < 0 ? -2048 : 2047). 44281ad6265SDimitry Andricdef AddiPairImmSmall : SDNodeXForm<imm, [{ 44381ad6265SDimitry Andric int64_t Imm = N->getSExtValue(); 44481ad6265SDimitry Andric int64_t Adj = N->getSExtValue() < 0 ? -2048 : 2047; 44581ad6265SDimitry Andric return CurDAG->getTargetConstant(Imm - Adj, SDLoc(N), 446fe6060f1SDimitry Andric N->getValueType(0)); 447fe6060f1SDimitry Andric}]>; 448fe6060f1SDimitry Andric 44981ad6265SDimitry Andric// Return -2048 if immediate is negative or 2047 if positive. These are the 45081ad6265SDimitry Andric// largest simm12 values. 45181ad6265SDimitry Andricdef AddiPairImmLarge : SDNodeXForm<imm, [{ 45281ad6265SDimitry Andric int64_t Imm = N->getSExtValue() < 0 ? -2048 : 2047; 45381ad6265SDimitry Andric return CurDAG->getTargetConstant(Imm, SDLoc(N), 454fe6060f1SDimitry Andric N->getValueType(0)); 455fe6060f1SDimitry Andric}]>; 456fe6060f1SDimitry Andric 45781ad6265SDimitry Andricdef TrailingZeros : SDNodeXForm<imm, [{ 45806c3fb27SDimitry Andric return CurDAG->getTargetConstant(llvm::countr_zero(N->getZExtValue()), 45981ad6265SDimitry Andric SDLoc(N), N->getValueType(0)); 46081ad6265SDimitry Andric}]>; 46181ad6265SDimitry Andric 46204eeddc0SDimitry Andricdef XLenSubTrailingOnes : SDNodeXForm<imm, [{ 46304eeddc0SDimitry Andric uint64_t XLen = Subtarget->getXLen(); 46406c3fb27SDimitry Andric uint64_t TrailingOnes = llvm::countr_one(N->getZExtValue()); 46504eeddc0SDimitry Andric return CurDAG->getTargetConstant(XLen - TrailingOnes, SDLoc(N), 46604eeddc0SDimitry Andric N->getValueType(0)); 46704eeddc0SDimitry Andric}]>; 46804eeddc0SDimitry Andric 46904eeddc0SDimitry Andric// Checks if this mask is a non-empty sequence of ones starting at the 47081ad6265SDimitry Andric// most/least significant bit with the remainder zero and exceeds simm32/simm12. 47181ad6265SDimitry Andricdef LeadingOnesMask : PatLeaf<(imm), [{ 47281ad6265SDimitry Andric if (!N->hasOneUse()) 47381ad6265SDimitry Andric return false; 47481ad6265SDimitry Andric return !isInt<32>(N->getSExtValue()) && isMask_64(~N->getSExtValue()); 47581ad6265SDimitry Andric}], TrailingZeros>; 47681ad6265SDimitry Andric 47704eeddc0SDimitry Andricdef TrailingOnesMask : PatLeaf<(imm), [{ 47804eeddc0SDimitry Andric if (!N->hasOneUse()) 47904eeddc0SDimitry Andric return false; 48004eeddc0SDimitry Andric return !isInt<12>(N->getSExtValue()) && isMask_64(N->getZExtValue()); 48104eeddc0SDimitry Andric}], XLenSubTrailingOnes>; 48204eeddc0SDimitry Andric 483bdd1243dSDimitry Andric// Similar to LeadingOnesMask, but only consider leading ones in the lower 32 484bdd1243dSDimitry Andric// bits. 485bdd1243dSDimitry Andricdef LeadingOnesWMask : PatLeaf<(imm), [{ 486bdd1243dSDimitry Andric if (!N->hasOneUse()) 487bdd1243dSDimitry Andric return false; 488bdd1243dSDimitry Andric // If the value is a uint32 but not an int32, it must have bit 31 set and 489bdd1243dSDimitry Andric // bits 63:32 cleared. After that we're looking for a shifted mask but not 490bdd1243dSDimitry Andric // an all ones mask. 491bdd1243dSDimitry Andric int64_t Imm = N->getSExtValue(); 492bdd1243dSDimitry Andric return !isInt<32>(Imm) && isUInt<32>(Imm) && isShiftedMask_64(Imm) && 493bdd1243dSDimitry Andric Imm != UINT64_C(0xffffffff); 494bdd1243dSDimitry Andric}], TrailingZeros>; 495bdd1243dSDimitry Andric 4960b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 4970b57cec5SDimitry Andric// Instruction Formats 4980b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andricinclude "RISCVInstrFormats.td" 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 5030b57cec5SDimitry Andric// Instruction Class Templates 5040b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 5070b57cec5SDimitry Andricclass BranchCC_rri<bits<3> funct3, string opcodestr> 5080b57cec5SDimitry Andric : RVInstB<funct3, OPC_BRANCH, (outs), 5090b57cec5SDimitry Andric (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12), 51013138422SDimitry Andric opcodestr, "$rs1, $rs2, $imm12">, 5115ffd83dbSDimitry Andric Sched<[WriteJmp, ReadJmp, ReadJmp]> { 5120b57cec5SDimitry Andric let isBranch = 1; 5130b57cec5SDimitry Andric let isTerminator = 1; 5140b57cec5SDimitry Andric} 5150b57cec5SDimitry Andric 51681ad6265SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { 5170b57cec5SDimitry Andricclass Load_ri<bits<3> funct3, string opcodestr> 518bdd1243dSDimitry Andric : RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPRMem:$rs1, simm12:$imm12), 5190b57cec5SDimitry Andric opcodestr, "$rd, ${imm12}(${rs1})">; 5200b57cec5SDimitry Andric 52181ad6265SDimitry Andricclass HLoad_r<bits<7> funct7, bits<5> funct5, string opcodestr> 52281ad6265SDimitry Andric : RVInstR<funct7, 0b100, OPC_SYSTEM, (outs GPR:$rd), 52381ad6265SDimitry Andric (ins GPRMemZeroOffset:$rs1), opcodestr, "$rd, $rs1"> { 52481ad6265SDimitry Andric let rs2 = funct5; 52581ad6265SDimitry Andric} 52681ad6265SDimitry Andric} 52781ad6265SDimitry Andric 5280b57cec5SDimitry Andric// Operands for stores are in the order srcreg, base, offset rather than 5290b57cec5SDimitry Andric// reflecting the order these fields are specified in the instruction 5300b57cec5SDimitry Andric// encoding. 53181ad6265SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 1 in { 5320b57cec5SDimitry Andricclass Store_rri<bits<3> funct3, string opcodestr> 5330b57cec5SDimitry Andric : RVInstS<funct3, OPC_STORE, (outs), 534bdd1243dSDimitry Andric (ins GPR:$rs2, GPRMem:$rs1, simm12:$imm12), 5350b57cec5SDimitry Andric opcodestr, "$rs2, ${imm12}(${rs1})">; 5360b57cec5SDimitry Andric 53781ad6265SDimitry Andricclass HStore_rr<bits<7> funct7, string opcodestr> 53881ad6265SDimitry Andric : RVInstR<funct7, 0b100, OPC_SYSTEM, (outs), 53981ad6265SDimitry Andric (ins GPR:$rs2, GPRMemZeroOffset:$rs1), 54081ad6265SDimitry Andric opcodestr, "$rs2, $rs1"> { 54181ad6265SDimitry Andric let rd = 0; 54281ad6265SDimitry Andric} 54381ad6265SDimitry Andric} 54481ad6265SDimitry Andric 5450b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 5460b57cec5SDimitry Andricclass ALU_ri<bits<3> funct3, string opcodestr> 5470b57cec5SDimitry Andric : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), 54813138422SDimitry Andric opcodestr, "$rd, $rs1, $imm12">, 54913138422SDimitry Andric Sched<[WriteIALU, ReadIALU]>; 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 552fe6060f1SDimitry Andricclass Shift_ri<bits<5> imm11_7, bits<3> funct3, string opcodestr> 553fe6060f1SDimitry Andric : RVInstIShift<imm11_7, funct3, OPC_OP_IMM, (outs GPR:$rd), 5540b57cec5SDimitry Andric (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr, 55513138422SDimitry Andric "$rd, $rs1, $shamt">, 556fe6060f1SDimitry Andric Sched<[WriteShiftImm, ReadShiftImm]>; 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 55981ad6265SDimitry Andricclass ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr, 56081ad6265SDimitry Andric bit Commutable = 0> 5610b57cec5SDimitry Andric : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), 56281ad6265SDimitry Andric opcodestr, "$rd, $rs1, $rs2"> { 56381ad6265SDimitry Andric let isCommutable = Commutable; 56481ad6265SDimitry Andric} 5650b57cec5SDimitry Andric 566e8d8bef9SDimitry Andriclet hasNoSchedulingInfo = 1, 567e8d8bef9SDimitry Andric hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 5680b57cec5SDimitry Andricclass CSR_ir<bits<3> funct3, string opcodestr> 5690b57cec5SDimitry Andric : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins csr_sysreg:$imm12, GPR:$rs1), 57013138422SDimitry Andric opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR, ReadCSR]>; 5710b57cec5SDimitry Andric 572e8d8bef9SDimitry Andriclet hasNoSchedulingInfo = 1, 573e8d8bef9SDimitry Andric hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 5740b57cec5SDimitry Andricclass CSR_ii<bits<3> funct3, string opcodestr> 5750b57cec5SDimitry Andric : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), 5760b57cec5SDimitry Andric (ins csr_sysreg:$imm12, uimm5:$rs1), 57713138422SDimitry Andric opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR]>; 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 580fe6060f1SDimitry Andricclass ShiftW_ri<bits<7> imm11_5, bits<3> funct3, string opcodestr> 581fe6060f1SDimitry Andric : RVInstIShiftW<imm11_5, funct3, OPC_OP_IMM_32, (outs GPR:$rd), 5820b57cec5SDimitry Andric (ins GPR:$rs1, uimm5:$shamt), opcodestr, 58313138422SDimitry Andric "$rd, $rs1, $shamt">, 584fe6060f1SDimitry Andric Sched<[WriteShiftImm32, ReadShiftImm32]>; 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 58781ad6265SDimitry Andricclass ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr, 58881ad6265SDimitry Andric bit Commutable = 0> 5890b57cec5SDimitry Andric : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd), 59081ad6265SDimitry Andric (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2"> { 59181ad6265SDimitry Andric let isCommutable = Commutable; 59281ad6265SDimitry Andric} 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andriclet hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 5950b57cec5SDimitry Andricclass Priv<string opcodestr, bits<7> funct7> 5960b57cec5SDimitry Andric : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2), 5970b57cec5SDimitry Andric opcodestr, "">; 5980b57cec5SDimitry Andric 59981ad6265SDimitry Andriclet hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 60081ad6265SDimitry Andricclass Priv_rr<string opcodestr, bits<7> funct7> 60181ad6265SDimitry Andric : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2), 60281ad6265SDimitry Andric opcodestr, "$rs1, $rs2"> { 60381ad6265SDimitry Andric let rd = 0; 60481ad6265SDimitry Andric} 60581ad6265SDimitry Andric 6060b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 6070b57cec5SDimitry Andric// Instructions 6080b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { 611bdd1243dSDimitry Andriclet isReMaterializable = 1, isAsCheapAsAMove = 1, 612bdd1243dSDimitry Andric IsSignExtendingOpW = 1 in 6130b57cec5SDimitry Andricdef LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20_lui:$imm20), 61413138422SDimitry Andric "lui", "$rd, $imm20">, Sched<[WriteIALU]>; 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andricdef AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20_auipc:$imm20), 61713138422SDimitry Andric "auipc", "$rd, $imm20">, Sched<[WriteIALU]>; 6180b57cec5SDimitry Andric 6190b57cec5SDimitry Andricdef JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20), 62013138422SDimitry Andric "jal", "$rd, $imm20">, Sched<[WriteJal]>; 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andricdef JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd), 6230b57cec5SDimitry Andric (ins GPR:$rs1, simm12:$imm12), 62413138422SDimitry Andric "jalr", "$rd, ${imm12}(${rs1})">, 62513138422SDimitry Andric Sched<[WriteJalr, ReadJalr]>; 6260b57cec5SDimitry Andric} // hasSideEffects = 0, mayLoad = 0, mayStore = 0 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andricdef BEQ : BranchCC_rri<0b000, "beq">; 6290b57cec5SDimitry Andricdef BNE : BranchCC_rri<0b001, "bne">; 6300b57cec5SDimitry Andricdef BLT : BranchCC_rri<0b100, "blt">; 6310b57cec5SDimitry Andricdef BGE : BranchCC_rri<0b101, "bge">; 6320b57cec5SDimitry Andricdef BLTU : BranchCC_rri<0b110, "bltu">; 6330b57cec5SDimitry Andricdef BGEU : BranchCC_rri<0b111, "bgeu">; 6340b57cec5SDimitry Andric 635bdd1243dSDimitry Andriclet IsSignExtendingOpW = 1 in { 63613138422SDimitry Andricdef LB : Load_ri<0b000, "lb">, Sched<[WriteLDB, ReadMemBase]>; 63713138422SDimitry Andricdef LH : Load_ri<0b001, "lh">, Sched<[WriteLDH, ReadMemBase]>; 63813138422SDimitry Andricdef LW : Load_ri<0b010, "lw">, Sched<[WriteLDW, ReadMemBase]>; 63913138422SDimitry Andricdef LBU : Load_ri<0b100, "lbu">, Sched<[WriteLDB, ReadMemBase]>; 64013138422SDimitry Andricdef LHU : Load_ri<0b101, "lhu">, Sched<[WriteLDH, ReadMemBase]>; 641bdd1243dSDimitry Andric} 6420b57cec5SDimitry Andric 64313138422SDimitry Andricdef SB : Store_rri<0b000, "sb">, Sched<[WriteSTB, ReadStoreData, ReadMemBase]>; 64413138422SDimitry Andricdef SH : Store_rri<0b001, "sh">, Sched<[WriteSTH, ReadStoreData, ReadMemBase]>; 64513138422SDimitry Andricdef SW : Store_rri<0b010, "sw">, Sched<[WriteSTW, ReadStoreData, ReadMemBase]>; 6460b57cec5SDimitry Andric 6470b57cec5SDimitry Andric// ADDI isn't always rematerializable, but isReMaterializable will be used as 6480b57cec5SDimitry Andric// a hint which is verified in isReallyTriviallyReMaterializable. 6490b57cec5SDimitry Andriclet isReMaterializable = 1, isAsCheapAsAMove = 1 in 6500b57cec5SDimitry Andricdef ADDI : ALU_ri<0b000, "addi">; 6510b57cec5SDimitry Andric 652bdd1243dSDimitry Andriclet IsSignExtendingOpW = 1 in { 6530b57cec5SDimitry Andricdef SLTI : ALU_ri<0b010, "slti">; 6540b57cec5SDimitry Andricdef SLTIU : ALU_ri<0b011, "sltiu">; 655bdd1243dSDimitry Andric} 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andriclet isReMaterializable = 1, isAsCheapAsAMove = 1 in { 6580b57cec5SDimitry Andricdef XORI : ALU_ri<0b100, "xori">; 6590b57cec5SDimitry Andricdef ORI : ALU_ri<0b110, "ori">; 6600b57cec5SDimitry Andric} 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andricdef ANDI : ALU_ri<0b111, "andi">; 6630b57cec5SDimitry Andric 664fe6060f1SDimitry Andricdef SLLI : Shift_ri<0b00000, 0b001, "slli">; 665fe6060f1SDimitry Andricdef SRLI : Shift_ri<0b00000, 0b101, "srli">; 666fe6060f1SDimitry Andricdef SRAI : Shift_ri<0b01000, 0b101, "srai">; 6670b57cec5SDimitry Andric 66806c3fb27SDimitry Andricdef ADD : ALU_rr<0b0000000, 0b000, "add", Commutable=1>, 66981ad6265SDimitry Andric Sched<[WriteIALU, ReadIALU, ReadIALU]>; 67081ad6265SDimitry Andricdef SUB : ALU_rr<0b0100000, 0b000, "sub">, 67181ad6265SDimitry Andric Sched<[WriteIALU, ReadIALU, ReadIALU]>; 67281ad6265SDimitry Andricdef SLL : ALU_rr<0b0000000, 0b001, "sll">, 67381ad6265SDimitry Andric Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 674bdd1243dSDimitry Andriclet IsSignExtendingOpW = 1 in { 67581ad6265SDimitry Andricdef SLT : ALU_rr<0b0000000, 0b010, "slt">, 67681ad6265SDimitry Andric Sched<[WriteIALU, ReadIALU, ReadIALU]>; 67781ad6265SDimitry Andricdef SLTU : ALU_rr<0b0000000, 0b011, "sltu">, 67881ad6265SDimitry Andric Sched<[WriteIALU, ReadIALU, ReadIALU]>; 679bdd1243dSDimitry Andric} 68006c3fb27SDimitry Andricdef XOR : ALU_rr<0b0000000, 0b100, "xor", Commutable=1>, 68181ad6265SDimitry Andric Sched<[WriteIALU, ReadIALU, ReadIALU]>; 68281ad6265SDimitry Andricdef SRL : ALU_rr<0b0000000, 0b101, "srl">, 68381ad6265SDimitry Andric Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 68481ad6265SDimitry Andricdef SRA : ALU_rr<0b0100000, 0b101, "sra">, 68581ad6265SDimitry Andric Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 68606c3fb27SDimitry Andricdef OR : ALU_rr<0b0000000, 0b110, "or", Commutable=1>, 68781ad6265SDimitry Andric Sched<[WriteIALU, ReadIALU, ReadIALU]>; 68806c3fb27SDimitry Andricdef AND : ALU_rr<0b0000000, 0b111, "and", Commutable=1>, 68981ad6265SDimitry Andric Sched<[WriteIALU, ReadIALU, ReadIALU]>; 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andriclet hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { 6920b57cec5SDimitry Andricdef FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs), 6930b57cec5SDimitry Andric (ins fencearg:$pred, fencearg:$succ), 69413138422SDimitry Andric "fence", "$pred, $succ">, Sched<[]> { 6950b57cec5SDimitry Andric bits<4> pred; 6960b57cec5SDimitry Andric bits<4> succ; 6970b57cec5SDimitry Andric 6980b57cec5SDimitry Andric let rs1 = 0; 6990b57cec5SDimitry Andric let rd = 0; 7000b57cec5SDimitry Andric let imm12 = {0b0000,pred,succ}; 7010b57cec5SDimitry Andric} 7020b57cec5SDimitry Andric 70313138422SDimitry Andricdef FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", "">, Sched<[]> { 7040b57cec5SDimitry Andric let rs1 = 0; 7050b57cec5SDimitry Andric let rd = 0; 7060b57cec5SDimitry Andric let imm12 = {0b1000,0b0011,0b0011}; 7070b57cec5SDimitry Andric} 7080b57cec5SDimitry Andric 70913138422SDimitry Andricdef FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", "">, Sched<[]> { 7100b57cec5SDimitry Andric let rs1 = 0; 7110b57cec5SDimitry Andric let rd = 0; 7120b57cec5SDimitry Andric let imm12 = 0; 7130b57cec5SDimitry Andric} 7140b57cec5SDimitry Andric 71513138422SDimitry Andricdef ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", "">, Sched<[WriteJmp]> { 7160b57cec5SDimitry Andric let rs1 = 0; 7170b57cec5SDimitry Andric let rd = 0; 7180b57cec5SDimitry Andric let imm12 = 0; 7190b57cec5SDimitry Andric} 7200b57cec5SDimitry Andric 72113138422SDimitry Andricdef EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", "">, 72213138422SDimitry Andric Sched<[]> { 7230b57cec5SDimitry Andric let rs1 = 0; 7240b57cec5SDimitry Andric let rd = 0; 7250b57cec5SDimitry Andric let imm12 = 1; 7260b57cec5SDimitry Andric} 7270b57cec5SDimitry Andric 7280b57cec5SDimitry Andric// This is a de facto standard (as set by GNU binutils) 32-bit unimplemented 7290b57cec5SDimitry Andric// instruction (i.e., it should always trap, if your implementation has invalid 7300b57cec5SDimitry Andric// instruction traps). 73113138422SDimitry Andricdef UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", "">, 73213138422SDimitry Andric Sched<[]> { 7330b57cec5SDimitry Andric let rs1 = 0; 7340b57cec5SDimitry Andric let rd = 0; 7350b57cec5SDimitry Andric let imm12 = 0b110000000000; 7360b57cec5SDimitry Andric} 737bdd1243dSDimitry Andric 7380b57cec5SDimitry Andric} // hasSideEffects = 1, mayLoad = 0, mayStore = 0 7390b57cec5SDimitry Andric 7400b57cec5SDimitry Andricdef CSRRW : CSR_ir<0b001, "csrrw">; 7410b57cec5SDimitry Andricdef CSRRS : CSR_ir<0b010, "csrrs">; 7420b57cec5SDimitry Andricdef CSRRC : CSR_ir<0b011, "csrrc">; 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andricdef CSRRWI : CSR_ii<0b101, "csrrwi">; 7450b57cec5SDimitry Andricdef CSRRSI : CSR_ii<0b110, "csrrsi">; 7460b57cec5SDimitry Andricdef CSRRCI : CSR_ii<0b111, "csrrci">; 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric/// RV64I instructions 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 751bdd1243dSDimitry Andricdef LWU : Load_ri<0b110, "lwu">, Sched<[WriteLDW, ReadMemBase]>; 75213138422SDimitry Andricdef LD : Load_ri<0b011, "ld">, Sched<[WriteLDD, ReadMemBase]>; 75313138422SDimitry Andricdef SD : Store_rri<0b011, "sd">, Sched<[WriteSTD, ReadStoreData, ReadMemBase]>; 7540b57cec5SDimitry Andric 755bdd1243dSDimitry Andriclet IsSignExtendingOpW = 1 in { 7560b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 7570b57cec5SDimitry Andricdef ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd), 7580b57cec5SDimitry Andric (ins GPR:$rs1, simm12:$imm12), 75913138422SDimitry Andric "addiw", "$rd, $rs1, $imm12">, 76013138422SDimitry Andric Sched<[WriteIALU32, ReadIALU32]>; 7610b57cec5SDimitry Andric 762fe6060f1SDimitry Andricdef SLLIW : ShiftW_ri<0b0000000, 0b001, "slliw">; 763fe6060f1SDimitry Andricdef SRLIW : ShiftW_ri<0b0000000, 0b101, "srliw">; 764fe6060f1SDimitry Andricdef SRAIW : ShiftW_ri<0b0100000, 0b101, "sraiw">; 7650b57cec5SDimitry Andric 76606c3fb27SDimitry Andricdef ADDW : ALUW_rr<0b0000000, 0b000, "addw", Commutable=1>, 76713138422SDimitry Andric Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 76813138422SDimitry Andricdef SUBW : ALUW_rr<0b0100000, 0b000, "subw">, 76913138422SDimitry Andric Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 77013138422SDimitry Andricdef SLLW : ALUW_rr<0b0000000, 0b001, "sllw">, 771fe6060f1SDimitry Andric Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 77213138422SDimitry Andricdef SRLW : ALUW_rr<0b0000000, 0b101, "srlw">, 773fe6060f1SDimitry Andric Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 77413138422SDimitry Andricdef SRAW : ALUW_rr<0b0100000, 0b101, "sraw">, 775fe6060f1SDimitry Andric Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 776bdd1243dSDimitry Andric} // IsSignExtendingOpW = 1 7770b57cec5SDimitry Andric} // Predicates = [IsRV64] 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 7800b57cec5SDimitry Andric// Privileged instructions 7810b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 7820b57cec5SDimitry Andric 7830b57cec5SDimitry Andriclet isBarrier = 1, isReturn = 1, isTerminator = 1 in { 78413138422SDimitry Andricdef SRET : Priv<"sret", 0b0001000>, Sched<[]> { 7850b57cec5SDimitry Andric let rd = 0; 7860b57cec5SDimitry Andric let rs1 = 0; 7870b57cec5SDimitry Andric let rs2 = 0b00010; 7880b57cec5SDimitry Andric} 7890b57cec5SDimitry Andric 79013138422SDimitry Andricdef MRET : Priv<"mret", 0b0011000>, Sched<[]> { 7910b57cec5SDimitry Andric let rd = 0; 7920b57cec5SDimitry Andric let rs1 = 0; 7930b57cec5SDimitry Andric let rs2 = 0b00010; 7940b57cec5SDimitry Andric} 7950b57cec5SDimitry Andric} // isBarrier = 1, isReturn = 1, isTerminator = 1 7960b57cec5SDimitry Andric 79713138422SDimitry Andricdef WFI : Priv<"wfi", 0b0001000>, Sched<[]> { 7980b57cec5SDimitry Andric let rd = 0; 7990b57cec5SDimitry Andric let rs1 = 0; 8000b57cec5SDimitry Andric let rs2 = 0b00101; 8010b57cec5SDimitry Andric} 8020b57cec5SDimitry Andric 803bdd1243dSDimitry Andriclet Predicates = [HasStdExtSvinval] in { 80481ad6265SDimitry Andricdef SFENCE_W_INVAL : Priv<"sfence.w.inval", 0b0001100>, Sched<[]> { 8050b57cec5SDimitry Andric let rd = 0; 80681ad6265SDimitry Andric let rs1 = 0; 80781ad6265SDimitry Andric let rs2 = 0; 80881ad6265SDimitry Andric} 80981ad6265SDimitry Andric 81081ad6265SDimitry Andricdef SFENCE_INVAL_IR : Priv<"sfence.inval.ir", 0b0001100>, Sched<[]> { 81181ad6265SDimitry Andric let rd = 0; 81281ad6265SDimitry Andric let rs1 = 0; 81381ad6265SDimitry Andric let rs2 = 0b00001; 81481ad6265SDimitry Andric} 81581ad6265SDimitry Andricdef SINVAL_VMA : Priv_rr<"sinval.vma", 0b0001011>, Sched<[]>; 81681ad6265SDimitry Andricdef HINVAL_VVMA : Priv_rr<"hinval.vvma", 0b0010011>, Sched<[]>; 81781ad6265SDimitry Andricdef HINVAL_GVMA : Priv_rr<"hinval.gvma", 0b0110011>, Sched<[]>; 818bdd1243dSDimitry Andric} // Predicates = [HasStdExtSvinval] 819bdd1243dSDimitry Andric 820bdd1243dSDimitry Andricdef SFENCE_VMA : Priv_rr<"sfence.vma", 0b0001001>, Sched<[]>; 821bdd1243dSDimitry Andric 822bdd1243dSDimitry Andriclet Predicates = [HasStdExtH] in { 823bdd1243dSDimitry Andricdef HFENCE_VVMA : Priv_rr<"hfence.vvma", 0b0010001>, Sched<[]>; 824bdd1243dSDimitry Andricdef HFENCE_GVMA : Priv_rr<"hfence.gvma", 0b0110001>, Sched<[]>; 82581ad6265SDimitry Andric 82681ad6265SDimitry Andricdef HLV_B : HLoad_r<0b0110000, 0b00000, "hlv.b">, Sched<[]>; 82781ad6265SDimitry Andricdef HLV_BU : HLoad_r<0b0110000, 0b00001, "hlv.bu">, Sched<[]>; 82881ad6265SDimitry Andricdef HLV_H : HLoad_r<0b0110010, 0b00000, "hlv.h">, Sched<[]>; 82981ad6265SDimitry Andricdef HLV_HU : HLoad_r<0b0110010, 0b00001, "hlv.hu">, Sched<[]>; 83081ad6265SDimitry Andricdef HLVX_HU : HLoad_r<0b0110010, 0b00011, "hlvx.hu">, Sched<[]>; 83181ad6265SDimitry Andricdef HLV_W : HLoad_r<0b0110100, 0b00000, "hlv.w">, Sched<[]>; 83281ad6265SDimitry Andricdef HLVX_WU : HLoad_r<0b0110100, 0b00011, "hlvx.wu">, Sched<[]>; 83381ad6265SDimitry Andricdef HSV_B : HStore_rr<0b0110001, "hsv.b">, Sched<[]>; 83481ad6265SDimitry Andricdef HSV_H : HStore_rr<0b0110011, "hsv.h">, Sched<[]>; 83581ad6265SDimitry Andricdef HSV_W : HStore_rr<0b0110101, "hsv.w">, Sched<[]>; 836bdd1243dSDimitry Andric} 837bdd1243dSDimitry Andriclet Predicates = [IsRV64, HasStdExtH] in { 83881ad6265SDimitry Andricdef HLV_WU : HLoad_r<0b0110100, 0b00001, "hlv.wu">, Sched<[]>; 83981ad6265SDimitry Andricdef HLV_D : HLoad_r<0b0110110, 0b00000, "hlv.d">, Sched<[]>; 84081ad6265SDimitry Andricdef HSV_D : HStore_rr<0b0110111, "hsv.d">, Sched<[]>; 8410b57cec5SDimitry Andric} 8420b57cec5SDimitry Andric 8430b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 8445ffd83dbSDimitry Andric// Debug instructions 8455ffd83dbSDimitry Andric//===----------------------------------------------------------------------===// 8465ffd83dbSDimitry Andric 8475ffd83dbSDimitry Andriclet isBarrier = 1, isReturn = 1, isTerminator = 1 in { 8485ffd83dbSDimitry Andricdef DRET : Priv<"dret", 0b0111101>, Sched<[]> { 8495ffd83dbSDimitry Andric let rd = 0; 8505ffd83dbSDimitry Andric let rs1 = 0; 8515ffd83dbSDimitry Andric let rs2 = 0b10010; 8525ffd83dbSDimitry Andric} 8535ffd83dbSDimitry Andric} // isBarrier = 1, isReturn = 1, isTerminator = 1 8545ffd83dbSDimitry Andric 8555ffd83dbSDimitry Andric//===----------------------------------------------------------------------===// 8560b57cec5SDimitry Andric// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) 8570b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 8580b57cec5SDimitry Andric 8590b57cec5SDimitry Andricdef : InstAlias<"nop", (ADDI X0, X0, 0)>; 8600b57cec5SDimitry Andric 8610b57cec5SDimitry Andric// Note that the size is 32 because up to 8 32-bit instructions are needed to 8620b57cec5SDimitry Andric// generate an arbitrary 64-bit immediate. However, the size does not really 8630b57cec5SDimitry Andric// matter since PseudoLI is currently only used in the AsmParser where it gets 8640b57cec5SDimitry Andric// expanded to real instructions immediately. 8650b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32, 8660b57cec5SDimitry Andric isCodeGenOnly = 0, isAsmParserOnly = 1 in 8670b57cec5SDimitry Andricdef PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [], 8680b57cec5SDimitry Andric "li", "$rd, $imm">; 8690b57cec5SDimitry Andric 8700b57cec5SDimitry Andricdef PseudoLB : PseudoLoad<"lb">; 8710b57cec5SDimitry Andricdef PseudoLBU : PseudoLoad<"lbu">; 8720b57cec5SDimitry Andricdef PseudoLH : PseudoLoad<"lh">; 8730b57cec5SDimitry Andricdef PseudoLHU : PseudoLoad<"lhu">; 8740b57cec5SDimitry Andricdef PseudoLW : PseudoLoad<"lw">; 8750b57cec5SDimitry Andric 8760b57cec5SDimitry Andricdef PseudoSB : PseudoStore<"sb">; 8770b57cec5SDimitry Andricdef PseudoSH : PseudoStore<"sh">; 8780b57cec5SDimitry Andricdef PseudoSW : PseudoStore<"sw">; 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 8810b57cec5SDimitry Andricdef PseudoLWU : PseudoLoad<"lwu">; 8820b57cec5SDimitry Andricdef PseudoLD : PseudoLoad<"ld">; 8830b57cec5SDimitry Andricdef PseudoSD : PseudoStore<"sd">; 8840b57cec5SDimitry Andric} // Predicates = [IsRV64] 8850b57cec5SDimitry Andric 8864824e7fdSDimitry Andricdef : InstAlias<"li $rd, $imm", (ADDI GPR:$rd, X0, simm12:$imm)>; 8870b57cec5SDimitry Andricdef : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>; 8880b57cec5SDimitry Andricdef : InstAlias<"not $rd, $rs", (XORI GPR:$rd, GPR:$rs, -1)>; 8890b57cec5SDimitry Andricdef : InstAlias<"neg $rd, $rs", (SUB GPR:$rd, X0, GPR:$rs)>; 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 8920b57cec5SDimitry Andricdef : InstAlias<"negw $rd, $rs", (SUBW GPR:$rd, X0, GPR:$rs)>; 8930b57cec5SDimitry Andricdef : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs, 0)>; 8940b57cec5SDimitry Andric} // Predicates = [IsRV64] 8950b57cec5SDimitry Andric 8960b57cec5SDimitry Andricdef : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs, 1)>; 8970b57cec5SDimitry Andricdef : InstAlias<"snez $rd, $rs", (SLTU GPR:$rd, X0, GPR:$rs)>; 8980b57cec5SDimitry Andricdef : InstAlias<"sltz $rd, $rs", (SLT GPR:$rd, GPR:$rs, X0)>; 8990b57cec5SDimitry Andricdef : InstAlias<"sgtz $rd, $rs", (SLT GPR:$rd, X0, GPR:$rs)>; 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric// sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu 9020b57cec5SDimitry Andric// form will always be printed. Therefore, set a zero weight. 9030b57cec5SDimitry Andricdef : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>; 9040b57cec5SDimitry Andricdef : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>; 9050b57cec5SDimitry Andric 9060b57cec5SDimitry Andricdef : InstAlias<"beqz $rs, $offset", 9070b57cec5SDimitry Andric (BEQ GPR:$rs, X0, simm13_lsb0:$offset)>; 9080b57cec5SDimitry Andricdef : InstAlias<"bnez $rs, $offset", 9090b57cec5SDimitry Andric (BNE GPR:$rs, X0, simm13_lsb0:$offset)>; 9100b57cec5SDimitry Andricdef : InstAlias<"blez $rs, $offset", 9110b57cec5SDimitry Andric (BGE X0, GPR:$rs, simm13_lsb0:$offset)>; 9120b57cec5SDimitry Andricdef : InstAlias<"bgez $rs, $offset", 9130b57cec5SDimitry Andric (BGE GPR:$rs, X0, simm13_lsb0:$offset)>; 9140b57cec5SDimitry Andricdef : InstAlias<"bltz $rs, $offset", 9150b57cec5SDimitry Andric (BLT GPR:$rs, X0, simm13_lsb0:$offset)>; 9160b57cec5SDimitry Andricdef : InstAlias<"bgtz $rs, $offset", 9170b57cec5SDimitry Andric (BLT X0, GPR:$rs, simm13_lsb0:$offset)>; 9180b57cec5SDimitry Andric 9190b57cec5SDimitry Andric// Always output the canonical mnemonic for the pseudo branch instructions. 9200b57cec5SDimitry Andric// The GNU tools emit the canonical mnemonic for the branch pseudo instructions 9210b57cec5SDimitry Andric// as well (e.g. "bgt" will be recognised by the assembler but never printed by 9220b57cec5SDimitry Andric// objdump). Match this behaviour by setting a zero weight. 9230b57cec5SDimitry Andricdef : InstAlias<"bgt $rs, $rt, $offset", 9240b57cec5SDimitry Andric (BLT GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 9250b57cec5SDimitry Andricdef : InstAlias<"ble $rs, $rt, $offset", 9260b57cec5SDimitry Andric (BGE GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 9270b57cec5SDimitry Andricdef : InstAlias<"bgtu $rs, $rt, $offset", 9280b57cec5SDimitry Andric (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 9290b57cec5SDimitry Andricdef : InstAlias<"bleu $rs, $rt, $offset", 9300b57cec5SDimitry Andric (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andricdef : InstAlias<"j $offset", (JAL X0, simm21_lsb0_jal:$offset)>; 9330b57cec5SDimitry Andricdef : InstAlias<"jal $offset", (JAL X1, simm21_lsb0_jal:$offset)>; 9340b57cec5SDimitry Andric 9350b57cec5SDimitry Andric// Non-zero offset aliases of "jalr" are the lowest weight, followed by the 9360b57cec5SDimitry Andric// two-register form, then the one-register forms and finally "ret". 9370b57cec5SDimitry Andricdef : InstAlias<"jr $rs", (JALR X0, GPR:$rs, 0), 3>; 9380b57cec5SDimitry Andricdef : InstAlias<"jr ${offset}(${rs})", (JALR X0, GPR:$rs, simm12:$offset)>; 9390b57cec5SDimitry Andricdef : InstAlias<"jalr $rs", (JALR X1, GPR:$rs, 0), 3>; 9400b57cec5SDimitry Andricdef : InstAlias<"jalr ${offset}(${rs})", (JALR X1, GPR:$rs, simm12:$offset)>; 9410b57cec5SDimitry Andricdef : InstAlias<"jalr $rd, $rs", (JALR GPR:$rd, GPR:$rs, 0), 2>; 9420b57cec5SDimitry Andricdef : InstAlias<"ret", (JALR X0, X1, 0), 4>; 9430b57cec5SDimitry Andric 9440b57cec5SDimitry Andric// Non-canonical forms for jump targets also accepted by the assembler. 9450b57cec5SDimitry Andricdef : InstAlias<"jr $rs, $offset", (JALR X0, GPR:$rs, simm12:$offset), 0>; 9460b57cec5SDimitry Andricdef : InstAlias<"jalr $rs, $offset", (JALR X1, GPR:$rs, simm12:$offset), 0>; 9470b57cec5SDimitry Andricdef : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12:$offset), 0>; 948*0fca6ea1SDimitry Andricdef : InstAlias<"jr (${rs})", (JALR X0, GPR:$rs, 0), 0>; 949*0fca6ea1SDimitry Andricdef : InstAlias<"jalr (${rs})", (JALR X1, GPR:$rs, 0), 0>; 950*0fca6ea1SDimitry Andricdef : InstAlias<"jalr $rd, (${rs})", (JALR GPR:$rd, GPR:$rs, 0), 0>; 9510b57cec5SDimitry Andric 9520b57cec5SDimitry Andricdef : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw 9530b57cec5SDimitry Andric 95481ad6265SDimitry Andriclet Predicates = [HasStdExtZihintpause] in 95581ad6265SDimitry Andricdef : InstAlias<"pause", (FENCE 0x1, 0x0)>; // 0x1 == w 95681ad6265SDimitry Andric 9570b57cec5SDimitry Andricdef : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>; 9580b57cec5SDimitry Andricdef : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, CYCLE.Encoding, X0)>; 9590b57cec5SDimitry Andricdef : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, TIME.Encoding, X0)>; 9600b57cec5SDimitry Andric 9610b57cec5SDimitry Andriclet Predicates = [IsRV32] in { 9620b57cec5SDimitry Andricdef : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, INSTRETH.Encoding, X0)>; 9630b57cec5SDimitry Andricdef : InstAlias<"rdcycleh $rd", (CSRRS GPR:$rd, CYCLEH.Encoding, X0)>; 9640b57cec5SDimitry Andricdef : InstAlias<"rdtimeh $rd", (CSRRS GPR:$rd, TIMEH.Encoding, X0)>; 9650b57cec5SDimitry Andric} // Predicates = [IsRV32] 9660b57cec5SDimitry Andric 9670b57cec5SDimitry Andricdef : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, csr_sysreg:$csr, X0)>; 9680b57cec5SDimitry Andricdef : InstAlias<"csrw $csr, $rs", (CSRRW X0, csr_sysreg:$csr, GPR:$rs)>; 9690b57cec5SDimitry Andricdef : InstAlias<"csrs $csr, $rs", (CSRRS X0, csr_sysreg:$csr, GPR:$rs)>; 9700b57cec5SDimitry Andricdef : InstAlias<"csrc $csr, $rs", (CSRRC X0, csr_sysreg:$csr, GPR:$rs)>; 9710b57cec5SDimitry Andric 9720b57cec5SDimitry Andricdef : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>; 9730b57cec5SDimitry Andricdef : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>; 9740b57cec5SDimitry Andricdef : InstAlias<"csrci $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>; 9750b57cec5SDimitry Andric 9760b57cec5SDimitry Andriclet EmitPriority = 0 in { 9770b57cec5SDimitry Andricdef : InstAlias<"csrw $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>; 9780b57cec5SDimitry Andricdef : InstAlias<"csrs $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>; 9790b57cec5SDimitry Andricdef : InstAlias<"csrc $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>; 9800b57cec5SDimitry Andric 9810b57cec5SDimitry Andricdef : InstAlias<"csrrw $rd, $csr, $imm", (CSRRWI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 9820b57cec5SDimitry Andricdef : InstAlias<"csrrs $rd, $csr, $imm", (CSRRSI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 9830b57cec5SDimitry Andricdef : InstAlias<"csrrc $rd, $csr, $imm", (CSRRCI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 9840b57cec5SDimitry Andric} 9850b57cec5SDimitry Andric 9860b57cec5SDimitry Andricdef : InstAlias<"sfence.vma", (SFENCE_VMA X0, X0)>; 9870b57cec5SDimitry Andricdef : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>; 9880b57cec5SDimitry Andric 98981ad6265SDimitry Andricdef : InstAlias<"hfence.gvma", (HFENCE_GVMA X0, X0)>; 99081ad6265SDimitry Andricdef : InstAlias<"hfence.gvma $rs", (HFENCE_GVMA GPR:$rs, X0)>; 99181ad6265SDimitry Andric 99281ad6265SDimitry Andricdef : InstAlias<"hfence.vvma", (HFENCE_VVMA X0, X0)>; 99381ad6265SDimitry Andricdef : InstAlias<"hfence.vvma $rs", (HFENCE_VVMA GPR:$rs, X0)>; 99481ad6265SDimitry Andric 995bdd1243dSDimitry Andriclet Predicates = [HasStdExtZihintntl] in { 996bdd1243dSDimitry Andric def : InstAlias<"ntl.p1", (ADD X0, X0, X2)>; 997bdd1243dSDimitry Andric def : InstAlias<"ntl.pall", (ADD X0, X0, X3)>; 998bdd1243dSDimitry Andric def : InstAlias<"ntl.s1", (ADD X0, X0, X4)>; 999bdd1243dSDimitry Andric def : InstAlias<"ntl.all", (ADD X0, X0, X5)>; 1000bdd1243dSDimitry Andric} // Predicates = [HasStdExtZihintntl] 1001bdd1243dSDimitry Andric 10020b57cec5SDimitry Andriclet EmitPriority = 0 in { 10030b57cec5SDimitry Andricdef : InstAlias<"lb $rd, (${rs1})", 10040b57cec5SDimitry Andric (LB GPR:$rd, GPR:$rs1, 0)>; 10050b57cec5SDimitry Andricdef : InstAlias<"lh $rd, (${rs1})", 10060b57cec5SDimitry Andric (LH GPR:$rd, GPR:$rs1, 0)>; 10070b57cec5SDimitry Andricdef : InstAlias<"lw $rd, (${rs1})", 10080b57cec5SDimitry Andric (LW GPR:$rd, GPR:$rs1, 0)>; 10090b57cec5SDimitry Andricdef : InstAlias<"lbu $rd, (${rs1})", 10100b57cec5SDimitry Andric (LBU GPR:$rd, GPR:$rs1, 0)>; 10110b57cec5SDimitry Andricdef : InstAlias<"lhu $rd, (${rs1})", 10120b57cec5SDimitry Andric (LHU GPR:$rd, GPR:$rs1, 0)>; 10130b57cec5SDimitry Andric 10140b57cec5SDimitry Andricdef : InstAlias<"sb $rs2, (${rs1})", 10150b57cec5SDimitry Andric (SB GPR:$rs2, GPR:$rs1, 0)>; 10160b57cec5SDimitry Andricdef : InstAlias<"sh $rs2, (${rs1})", 10170b57cec5SDimitry Andric (SH GPR:$rs2, GPR:$rs1, 0)>; 10180b57cec5SDimitry Andricdef : InstAlias<"sw $rs2, (${rs1})", 10190b57cec5SDimitry Andric (SW GPR:$rs2, GPR:$rs1, 0)>; 10200b57cec5SDimitry Andric 10210b57cec5SDimitry Andricdef : InstAlias<"add $rd, $rs1, $imm12", 10220b57cec5SDimitry Andric (ADDI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 10230b57cec5SDimitry Andricdef : InstAlias<"and $rd, $rs1, $imm12", 10240b57cec5SDimitry Andric (ANDI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 10250b57cec5SDimitry Andricdef : InstAlias<"xor $rd, $rs1, $imm12", 10260b57cec5SDimitry Andric (XORI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 10270b57cec5SDimitry Andricdef : InstAlias<"or $rd, $rs1, $imm12", 10280b57cec5SDimitry Andric (ORI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 10290b57cec5SDimitry Andricdef : InstAlias<"sll $rd, $rs1, $shamt", 10300b57cec5SDimitry Andric (SLLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 10310b57cec5SDimitry Andricdef : InstAlias<"srl $rd, $rs1, $shamt", 10320b57cec5SDimitry Andric (SRLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 10330b57cec5SDimitry Andricdef : InstAlias<"sra $rd, $rs1, $shamt", 10340b57cec5SDimitry Andric (SRAI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 10350b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 10360b57cec5SDimitry Andricdef : InstAlias<"lwu $rd, (${rs1})", 10370b57cec5SDimitry Andric (LWU GPR:$rd, GPR:$rs1, 0)>; 10380b57cec5SDimitry Andricdef : InstAlias<"ld $rd, (${rs1})", 10390b57cec5SDimitry Andric (LD GPR:$rd, GPR:$rs1, 0)>; 10400b57cec5SDimitry Andricdef : InstAlias<"sd $rs2, (${rs1})", 10410b57cec5SDimitry Andric (SD GPR:$rs2, GPR:$rs1, 0)>; 10420b57cec5SDimitry Andric 10430b57cec5SDimitry Andricdef : InstAlias<"addw $rd, $rs1, $imm12", 10440b57cec5SDimitry Andric (ADDIW GPR:$rd, GPR:$rs1, simm12:$imm12)>; 10450b57cec5SDimitry Andricdef : InstAlias<"sllw $rd, $rs1, $shamt", 10460b57cec5SDimitry Andric (SLLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 10470b57cec5SDimitry Andricdef : InstAlias<"srlw $rd, $rs1, $shamt", 10480b57cec5SDimitry Andric (SRLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 10490b57cec5SDimitry Andricdef : InstAlias<"sraw $rd, $rs1, $shamt", 10500b57cec5SDimitry Andric (SRAIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 10510b57cec5SDimitry Andric} // Predicates = [IsRV64] 10520b57cec5SDimitry Andricdef : InstAlias<"slt $rd, $rs1, $imm12", 10530b57cec5SDimitry Andric (SLTI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 10540b57cec5SDimitry Andricdef : InstAlias<"sltu $rd, $rs1, $imm12", 10550b57cec5SDimitry Andric (SLTIU GPR:$rd, GPR:$rs1, simm12:$imm12)>; 10560b57cec5SDimitry Andric} 10570b57cec5SDimitry Andric 10580b57cec5SDimitry Andricdef : MnemonicAlias<"move", "mv">; 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric// The SCALL and SBREAK instructions wererenamed to ECALL and EBREAK in 10610b57cec5SDimitry Andric// version 2.1 of the user-level ISA. Like the GNU toolchain, we still accept 10620b57cec5SDimitry Andric// the old name for backwards compatibility. 10630b57cec5SDimitry Andricdef : MnemonicAlias<"scall", "ecall">; 10640b57cec5SDimitry Andricdef : MnemonicAlias<"sbreak", "ebreak">; 10650b57cec5SDimitry Andric 1066e8d8bef9SDimitry Andric// This alias was added to the spec in December 2020. Don't print it by default 1067e8d8bef9SDimitry Andric// to allow assembly we print to be compatible with versions of GNU assembler 1068e8d8bef9SDimitry Andric// that don't support this alias. 1069e8d8bef9SDimitry Andricdef : InstAlias<"zext.b $rd, $rs", (ANDI GPR:$rd, GPR:$rs, 0xFF), 0>; 1070e8d8bef9SDimitry Andric 10715f757f3fSDimitry Andriclet Predicates = [HasStdExtZicfilp] in { 10725f757f3fSDimitry Andricdef : InstAlias<"lpad $imm20", (AUIPC X0, uimm20:$imm20)>; 10735f757f3fSDimitry Andric} 10745f757f3fSDimitry Andric 10750b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 1076349cc55cSDimitry Andric// .insn directive instructions 1077349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 1078349cc55cSDimitry Andric 107906c3fb27SDimitry Andricdef AnyRegOperand : AsmOperandClass { 108006c3fb27SDimitry Andric let Name = "AnyRegOperand"; 108106c3fb27SDimitry Andric let RenderMethod = "addRegOperands"; 108206c3fb27SDimitry Andric let PredicateMethod = "isAnyReg"; 108306c3fb27SDimitry Andric} 108406c3fb27SDimitry Andric 108506c3fb27SDimitry Andricdef AnyReg : Operand<XLenVT> { 108606c3fb27SDimitry Andric let OperandType = "OPERAND_REGISTER"; 108706c3fb27SDimitry Andric let ParserMatchClass = AnyRegOperand; 108806c3fb27SDimitry Andric} 108906c3fb27SDimitry Andric 1090349cc55cSDimitry Andric// isCodeGenOnly = 1 to hide them from the tablegened assembly parser. 1091349cc55cSDimitry Andriclet isCodeGenOnly = 1, hasSideEffects = 1, mayLoad = 1, mayStore = 1, 1092349cc55cSDimitry Andric hasNoSchedulingInfo = 1 in { 10930eae32dcSDimitry Andricdef InsnR : DirectiveInsnR<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1094349cc55cSDimitry Andric uimm7:$funct7, AnyReg:$rs1, 1095349cc55cSDimitry Andric AnyReg:$rs2), 1096349cc55cSDimitry Andric "$opcode, $funct3, $funct7, $rd, $rs1, $rs2">; 10970eae32dcSDimitry Andricdef InsnR4 : DirectiveInsnR4<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1098349cc55cSDimitry Andric uimm3:$funct3, 1099349cc55cSDimitry Andric uimm2:$funct2, 1100349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2, 1101349cc55cSDimitry Andric AnyReg:$rs3), 1102349cc55cSDimitry Andric "$opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3">; 11030eae32dcSDimitry Andricdef InsnI : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1104349cc55cSDimitry Andric AnyReg:$rs1, simm12:$imm12), 1105349cc55cSDimitry Andric "$opcode, $funct3, $rd, $rs1, $imm12">; 11060eae32dcSDimitry Andricdef InsnI_Mem : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1107349cc55cSDimitry Andric uimm3:$funct3, 1108349cc55cSDimitry Andric AnyReg:$rs1, 1109349cc55cSDimitry Andric simm12:$imm12), 1110349cc55cSDimitry Andric "$opcode, $funct3, $rd, ${imm12}(${rs1})">; 11110eae32dcSDimitry Andricdef InsnB : DirectiveInsnB<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1112349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2, 1113349cc55cSDimitry Andric simm13_lsb0:$imm12), 1114349cc55cSDimitry Andric "$opcode, $funct3, $rs1, $rs2, $imm12">; 11150eae32dcSDimitry Andricdef InsnU : DirectiveInsnU<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1116349cc55cSDimitry Andric uimm20_lui:$imm20), 1117349cc55cSDimitry Andric "$opcode, $rd, $imm20">; 11180eae32dcSDimitry Andricdef InsnJ : DirectiveInsnJ<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1119349cc55cSDimitry Andric simm21_lsb0_jal:$imm20), 1120349cc55cSDimitry Andric "$opcode, $rd, $imm20">; 11210eae32dcSDimitry Andricdef InsnS : DirectiveInsnS<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1122349cc55cSDimitry Andric AnyReg:$rs2, AnyReg:$rs1, 1123349cc55cSDimitry Andric simm12:$imm12), 1124349cc55cSDimitry Andric "$opcode, $funct3, $rs2, ${imm12}(${rs1})">; 1125*0fca6ea1SDimitry Andricdef Insn32 : RVInst<(outs), (ins uimm32:$value), "", "", [], InstFormatOther> { 1126*0fca6ea1SDimitry Andric bits<32> value; 1127*0fca6ea1SDimitry Andric 1128*0fca6ea1SDimitry Andric let Inst{31-0} = value; 1129*0fca6ea1SDimitry Andric let AsmString = ".insn 0x4, $value"; 1130*0fca6ea1SDimitry Andric} 1131349cc55cSDimitry Andric} 1132349cc55cSDimitry Andric 1133349cc55cSDimitry Andric// Use InstAliases to match these so that we can combine the insn and format 1134349cc55cSDimitry Andric// into a mnemonic to use as the key for the tablegened asm matcher table. The 1135349cc55cSDimitry Andric// parser will take care of creating these fake mnemonics and will only do it 1136349cc55cSDimitry Andric// for known formats. 1137349cc55cSDimitry Andriclet EmitPriority = 0 in { 1138349cc55cSDimitry Andricdef : InstAlias<".insn_r $opcode, $funct3, $funct7, $rd, $rs1, $rs2", 11390eae32dcSDimitry Andric (InsnR AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm7:$funct7, 1140349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2)>; 1141349cc55cSDimitry Andric// Accept 4 register form of ".insn r" as alias for ".insn r4". 1142349cc55cSDimitry Andricdef : InstAlias<".insn_r $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3", 11430eae32dcSDimitry Andric (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2, 1144349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>; 1145349cc55cSDimitry Andricdef : InstAlias<".insn_r4 $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3", 11460eae32dcSDimitry Andric (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2, 1147349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>; 1148349cc55cSDimitry Andricdef : InstAlias<".insn_i $opcode, $funct3, $rd, $rs1, $imm12", 11490eae32dcSDimitry Andric (InsnI AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 1150349cc55cSDimitry Andric simm12:$imm12)>; 1151349cc55cSDimitry Andricdef : InstAlias<".insn_i $opcode, $funct3, $rd, ${imm12}(${rs1})", 11520eae32dcSDimitry Andric (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, 1153349cc55cSDimitry Andric AnyReg:$rs1, simm12:$imm12)>; 1154*0fca6ea1SDimitry Andricdef : InstAlias<".insn_i $opcode, $funct3, $rd, (${rs1})", 1155*0fca6ea1SDimitry Andric (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, 1156*0fca6ea1SDimitry Andric AnyReg:$rs1, 0)>; 1157349cc55cSDimitry Andricdef : InstAlias<".insn_b $opcode, $funct3, $rs1, $rs2, $imm12", 11580eae32dcSDimitry Andric (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 1159349cc55cSDimitry Andric AnyReg:$rs2, simm13_lsb0:$imm12)>; 1160349cc55cSDimitry Andric// Accept sb as an alias for b. 1161349cc55cSDimitry Andricdef : InstAlias<".insn_sb $opcode, $funct3, $rs1, $rs2, $imm12", 11620eae32dcSDimitry Andric (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 1163349cc55cSDimitry Andric AnyReg:$rs2, simm13_lsb0:$imm12)>; 1164349cc55cSDimitry Andricdef : InstAlias<".insn_u $opcode, $rd, $imm20", 11650eae32dcSDimitry Andric (InsnU AnyReg:$rd, uimm7_opcode:$opcode, uimm20_lui:$imm20)>; 1166349cc55cSDimitry Andricdef : InstAlias<".insn_j $opcode, $rd, $imm20", 11670eae32dcSDimitry Andric (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>; 1168349cc55cSDimitry Andric// Accept uj as an alias for j. 1169349cc55cSDimitry Andricdef : InstAlias<".insn_uj $opcode, $rd, $imm20", 11700eae32dcSDimitry Andric (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>; 1171349cc55cSDimitry Andricdef : InstAlias<".insn_s $opcode, $funct3, $rs2, ${imm12}(${rs1})", 11720eae32dcSDimitry Andric (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2, 1173349cc55cSDimitry Andric AnyReg:$rs1, simm12:$imm12)>; 1174*0fca6ea1SDimitry Andricdef : InstAlias<".insn_s $opcode, $funct3, $rs2, (${rs1})", 1175*0fca6ea1SDimitry Andric (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2, 1176*0fca6ea1SDimitry Andric AnyReg:$rs1, 0)>; 1177349cc55cSDimitry Andric} 1178349cc55cSDimitry Andric 1179349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 11800b57cec5SDimitry Andric// Pseudo-instructions and codegen patterns 11810b57cec5SDimitry Andric// 11820b57cec5SDimitry Andric// Naming convention: For 'generic' pattern classes, we use the naming 11830b57cec5SDimitry Andric// convention PatTy1Ty2. For pattern classes which offer a more complex 11845ffd83dbSDimitry Andric// expansion, prefix the class name, e.g. BccPat. 11850b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric/// Generic pattern classes 11880b57cec5SDimitry Andric 118906c3fb27SDimitry Andricclass PatGpr<SDPatternOperator OpNode, RVInst Inst, ValueType vt = XLenVT> 119006c3fb27SDimitry Andric : Pat<(vt (OpNode (vt GPR:$rs1))), (Inst GPR:$rs1)>; 11915f757f3fSDimitry Andricclass PatGprGpr<SDPatternOperator OpNode, RVInst Inst, ValueType vt1 = XLenVT, 11925f757f3fSDimitry Andric ValueType vt2 = XLenVT> 11935f757f3fSDimitry Andric : Pat<(vt1 (OpNode (vt1 GPR:$rs1), (vt2 GPR:$rs2))), (Inst GPR:$rs1, GPR:$rs2)>; 1194fe6060f1SDimitry Andric 11955f757f3fSDimitry Andricclass PatGprImm<SDPatternOperator OpNode, RVInst Inst, ImmLeaf ImmType, 11965f757f3fSDimitry Andric ValueType vt = XLenVT> 11975f757f3fSDimitry Andric : Pat<(vt (OpNode (vt GPR:$rs1), ImmType:$imm)), 1198fe6060f1SDimitry Andric (Inst GPR:$rs1, ImmType:$imm)>; 11990b57cec5SDimitry Andricclass PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst> 1200fe6060f1SDimitry Andric : PatGprImm<OpNode, Inst, simm12>; 12010b57cec5SDimitry Andricclass PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst> 1202fe6060f1SDimitry Andric : PatGprImm<OpNode, Inst, uimmlog2xlen>; 12030b57cec5SDimitry Andric 12040b57cec5SDimitry Andric/// Predicates 12050b57cec5SDimitry Andric 12060b57cec5SDimitry Andricdef assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{ 1207e8d8bef9SDimitry Andric return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32); 12080b57cec5SDimitry Andric}]>; 120906c3fb27SDimitry Andricdef sexti16 : ComplexPattern<XLenVT, 1, "selectSExtBits<16>">; 1210*0fca6ea1SDimitry Andricdef sexti16i32 : ComplexPattern<i32, 1, "selectSExtBits<16>">; 121106c3fb27SDimitry Andricdef sexti32 : ComplexPattern<i64, 1, "selectSExtBits<32>">; 12120b57cec5SDimitry Andricdef assertzexti32 : PatFrag<(ops node:$src), (assertzext node:$src), [{ 1213e8d8bef9SDimitry Andric return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32); 12140b57cec5SDimitry Andric}]>; 1215bdd1243dSDimitry Andricdef zexti32 : ComplexPattern<i64, 1, "selectZExtBits<32>">; 1216bdd1243dSDimitry Andricdef zexti16 : ComplexPattern<XLenVT, 1, "selectZExtBits<16>">; 12175f757f3fSDimitry Andricdef zexti16i32 : ComplexPattern<i32, 1, "selectZExtBits<16>">; 1218bdd1243dSDimitry Andricdef zexti8 : ComplexPattern<XLenVT, 1, "selectZExtBits<8>">; 12195f757f3fSDimitry Andricdef zexti8i32 : ComplexPattern<i32, 1, "selectZExtBits<8>">; 12200b57cec5SDimitry Andric 122106c3fb27SDimitry Andricdef ext : PatFrags<(ops node:$A), [(sext node:$A), (zext node:$A)]>; 122206c3fb27SDimitry Andric 122381ad6265SDimitry Andricclass binop_oneuse<SDPatternOperator operator> 122481ad6265SDimitry Andric : PatFrag<(ops node:$A, node:$B), 122581ad6265SDimitry Andric (operator node:$A, node:$B), [{ 1226fe6060f1SDimitry Andric return N->hasOneUse(); 1227e8d8bef9SDimitry Andric}]>; 1228e8d8bef9SDimitry Andric 1229bdd1243dSDimitry Andricdef and_oneuse : binop_oneuse<and>; 123081ad6265SDimitry Andricdef mul_oneuse : binop_oneuse<mul>; 1231e8d8bef9SDimitry Andric 1232349cc55cSDimitry Andricdef mul_const_oneuse : PatFrag<(ops node:$A, node:$B), 1233349cc55cSDimitry Andric (mul node:$A, node:$B), [{ 1234349cc55cSDimitry Andric if (auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1))) 123506c3fb27SDimitry Andric return N1C->hasOneUse(); 1236349cc55cSDimitry Andric return false; 1237349cc55cSDimitry Andric}]>; 1238349cc55cSDimitry Andric 123981ad6265SDimitry Andricclass unop_oneuse<SDPatternOperator operator> 124081ad6265SDimitry Andric : PatFrag<(ops node:$A), 124181ad6265SDimitry Andric (operator node:$A), [{ 124204eeddc0SDimitry Andric return N->hasOneUse(); 124304eeddc0SDimitry Andric}]>; 124404eeddc0SDimitry Andric 124581ad6265SDimitry Andricdef sext_oneuse : unop_oneuse<sext>; 124681ad6265SDimitry Andricdef zext_oneuse : unop_oneuse<zext>; 124781ad6265SDimitry Andricdef anyext_oneuse : unop_oneuse<anyext>; 124806c3fb27SDimitry Andricdef ext_oneuse : unop_oneuse<ext>; 124981ad6265SDimitry Andricdef fpext_oneuse : unop_oneuse<any_fpextend>; 125004eeddc0SDimitry Andric 12515f757f3fSDimitry Andricdef 33signbits_node : PatLeaf<(i64 GPR:$src), [{ 12525f757f3fSDimitry Andric return CurDAG->ComputeNumSignBits(SDValue(N, 0)) > 32; 12535f757f3fSDimitry Andric}]>; 12545f757f3fSDimitry Andric 12550b57cec5SDimitry Andric/// Simple arithmetic operations 12560b57cec5SDimitry Andric 12570b57cec5SDimitry Andricdef : PatGprGpr<add, ADD>; 12580b57cec5SDimitry Andricdef : PatGprSimm12<add, ADDI>; 12590b57cec5SDimitry Andricdef : PatGprGpr<sub, SUB>; 12600b57cec5SDimitry Andricdef : PatGprGpr<or, OR>; 12610b57cec5SDimitry Andricdef : PatGprSimm12<or, ORI>; 12620b57cec5SDimitry Andricdef : PatGprGpr<and, AND>; 12630b57cec5SDimitry Andricdef : PatGprSimm12<and, ANDI>; 12640b57cec5SDimitry Andricdef : PatGprGpr<xor, XOR>; 12650b57cec5SDimitry Andricdef : PatGprSimm12<xor, XORI>; 12660b57cec5SDimitry Andricdef : PatGprUimmLog2XLen<shl, SLLI>; 12670b57cec5SDimitry Andricdef : PatGprUimmLog2XLen<srl, SRLI>; 12680b57cec5SDimitry Andricdef : PatGprUimmLog2XLen<sra, SRAI>; 12690b57cec5SDimitry Andric 1270bdd1243dSDimitry Andric// Select 'or' as ADDI if the immediate bits are known to be 0 in $rs1. This 1271bdd1243dSDimitry Andric// can improve compressibility. 1272bdd1243dSDimitry Andricdef or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{ 1273*0fca6ea1SDimitry Andric if (N->getFlags().hasDisjoint()) 1274*0fca6ea1SDimitry Andric return true; 1275bdd1243dSDimitry Andric KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0); 1276bdd1243dSDimitry Andric KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0); 1277bdd1243dSDimitry Andric return KnownBits::haveNoCommonBitsSet(Known0, Known1); 1278bdd1243dSDimitry Andric}]>; 1279bdd1243dSDimitry Andricdef : PatGprSimm12<or_is_add, ADDI>; 1280bdd1243dSDimitry Andric 1281*0fca6ea1SDimitry Andricdef add_like : PatFrags<(ops node:$lhs, node:$rhs), 1282*0fca6ea1SDimitry Andric [(or_is_add node:$lhs, node:$rhs), 1283*0fca6ea1SDimitry Andric (add node:$lhs, node:$rhs)]>; 1284*0fca6ea1SDimitry Andric 1285bdd1243dSDimitry Andric// negate of low bit can be done via two (compressible) shifts. The negate 1286bdd1243dSDimitry Andric// is never compressible since rs1 and rd can't be the same register. 1287bdd1243dSDimitry Andricdef : Pat<(XLenVT (sub 0, (and_oneuse GPR:$rs, 1))), 1288*0fca6ea1SDimitry Andric (SRAI (XLenVT (SLLI $rs, (ImmSubFromXLen (XLenVT 1)))), 1289bdd1243dSDimitry Andric (ImmSubFromXLen (XLenVT 1)))>; 1290bdd1243dSDimitry Andric 129181ad6265SDimitry Andric// AND with leading/trailing ones mask exceeding simm32/simm12. 129281ad6265SDimitry Andricdef : Pat<(i64 (and GPR:$rs, LeadingOnesMask:$mask)), 1293*0fca6ea1SDimitry Andric (SLLI (i64 (SRLI $rs, LeadingOnesMask:$mask)), LeadingOnesMask:$mask)>; 129404eeddc0SDimitry Andricdef : Pat<(XLenVT (and GPR:$rs, TrailingOnesMask:$mask)), 1295*0fca6ea1SDimitry Andric (SRLI (XLenVT (SLLI $rs, TrailingOnesMask:$mask)), TrailingOnesMask:$mask)>; 129604eeddc0SDimitry Andric 12970b57cec5SDimitry Andric// Match both a plain shift and one where the shift amount is masked (this is 12980b57cec5SDimitry Andric// typically introduced when the legalizer promotes the shift amount and 12990b57cec5SDimitry Andric// zero-extends it). For RISC-V, the mask is unnecessary as shifts in the base 13000b57cec5SDimitry Andric// ISA only read the least significant 5 bits (RV32I) or 6 bits (RV64I). 1301fe6060f1SDimitry Andricdef shiftMaskXLen : ComplexPattern<XLenVT, 1, "selectShiftMaskXLen", [], [], 0>; 1302fe6060f1SDimitry Andricdef shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>; 1303fe6060f1SDimitry Andric 13040b57cec5SDimitry Andricclass shiftop<SDPatternOperator operator> 1305fe6060f1SDimitry Andric : PatFrag<(ops node:$val, node:$count), 1306fe6060f1SDimitry Andric (operator node:$val, (XLenVT (shiftMaskXLen node:$count)))>; 1307e8d8bef9SDimitry Andricclass shiftopw<SDPatternOperator operator> 1308fe6060f1SDimitry Andric : PatFrag<(ops node:$val, node:$count), 1309fe6060f1SDimitry Andric (operator node:$val, (i64 (shiftMask32 node:$count)))>; 13100b57cec5SDimitry Andric 13110b57cec5SDimitry Andricdef : PatGprGpr<shiftop<shl>, SLL>; 13120b57cec5SDimitry Andricdef : PatGprGpr<shiftop<srl>, SRL>; 13130b57cec5SDimitry Andricdef : PatGprGpr<shiftop<sra>, SRA>; 13140b57cec5SDimitry Andric 13150b57cec5SDimitry Andric// This is a special case of the ADD instruction used to facilitate the use of a 13160b57cec5SDimitry Andric// fourth operand to emit a relocation on a symbol relating to this instruction. 13170b57cec5SDimitry Andric// The relocation does not affect any bits of the instruction itself but is used 13180b57cec5SDimitry Andric// as a hint to the linker. 13190b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in 13200b57cec5SDimitry Andricdef PseudoAddTPRel : Pseudo<(outs GPR:$rd), 13210b57cec5SDimitry Andric (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [], 13220b57cec5SDimitry Andric "add", "$rd, $rs1, $rs2, $src">; 13230b57cec5SDimitry Andric 13240b57cec5SDimitry Andric/// FrameIndex calculations 13250b57cec5SDimitry Andric 132606c3fb27SDimitry Andricdef : Pat<(FrameAddrRegImm (iPTR GPR:$rs1), simm12:$imm12), 132781ad6265SDimitry Andric (ADDI GPR:$rs1, simm12:$imm12)>; 132881ad6265SDimitry Andric 132981ad6265SDimitry Andric/// HI and ADD_LO address nodes. 133081ad6265SDimitry Andric 1331*0fca6ea1SDimitry Andric// Pseudo for a rematerializable LUI+ADDI sequence for loading an address. 1332*0fca6ea1SDimitry Andric// It will be expanded after register allocation. 1333*0fca6ea1SDimitry Andric// FIXME: The scheduling information does not reflect the multiple instructions. 1334*0fca6ea1SDimitry Andriclet Size = 8, isReMaterializable = 1 in 1335*0fca6ea1SDimitry Andricdef PseudoMovAddr : Pseudo<(outs GPR:$dst), (ins uimm20_lui:$hi, simm12:$lo), []>, 1336*0fca6ea1SDimitry Andric Sched<[WriteIALU]>; 1337*0fca6ea1SDimitry Andric 1338*0fca6ea1SDimitry Andricdef riscv_hi_oneuse : unop_oneuse<riscv_hi>; 1339*0fca6ea1SDimitry Andricdef addr_hi_lo : PatFrag<(ops node:$hi, node:$lo), 1340*0fca6ea1SDimitry Andric (riscv_add_lo (riscv_hi_oneuse node:$hi), node:$lo)>; 1341*0fca6ea1SDimitry Andric 1342*0fca6ea1SDimitry Andricdef : Pat<(addr_hi_lo tglobaladdr:$hi, tglobaladdr:$lo), 1343*0fca6ea1SDimitry Andric (PseudoMovAddr tglobaladdr:$hi, tglobaladdr:$lo)>; 1344*0fca6ea1SDimitry Andricdef : Pat<(addr_hi_lo tblockaddress:$hi, tblockaddress:$lo), 1345*0fca6ea1SDimitry Andric (PseudoMovAddr tblockaddress:$hi, tblockaddress:$lo)>; 1346*0fca6ea1SDimitry Andricdef : Pat<(addr_hi_lo tjumptable:$hi, tjumptable:$lo), 1347*0fca6ea1SDimitry Andric (PseudoMovAddr tjumptable:$hi, tjumptable:$lo)>; 1348*0fca6ea1SDimitry Andricdef : Pat<(addr_hi_lo tconstpool:$hi, tconstpool:$lo), 1349*0fca6ea1SDimitry Andric (PseudoMovAddr tconstpool:$hi, tconstpool:$lo)>; 1350*0fca6ea1SDimitry Andric 135181ad6265SDimitry Andricdef : Pat<(riscv_hi tglobaladdr:$in), (LUI tglobaladdr:$in)>; 135281ad6265SDimitry Andricdef : Pat<(riscv_hi tblockaddress:$in), (LUI tblockaddress:$in)>; 135381ad6265SDimitry Andricdef : Pat<(riscv_hi tjumptable:$in), (LUI tjumptable:$in)>; 135481ad6265SDimitry Andricdef : Pat<(riscv_hi tconstpool:$in), (LUI tconstpool:$in)>; 135581ad6265SDimitry Andric 135681ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$hi, tglobaladdr:$lo), 135781ad6265SDimitry Andric (ADDI GPR:$hi, tglobaladdr:$lo)>; 135881ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$hi, tblockaddress:$lo), 135981ad6265SDimitry Andric (ADDI GPR:$hi, tblockaddress:$lo)>; 136081ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$hi, tjumptable:$lo), 136181ad6265SDimitry Andric (ADDI GPR:$hi, tjumptable:$lo)>; 136281ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$hi, tconstpool:$lo), 136381ad6265SDimitry Andric (ADDI GPR:$hi, tconstpool:$lo)>; 136481ad6265SDimitry Andric 136581ad6265SDimitry Andric/// TLS address nodes. 136681ad6265SDimitry Andric 136781ad6265SDimitry Andricdef : Pat<(riscv_hi tglobaltlsaddr:$in), (LUI tglobaltlsaddr:$in)>; 136881ad6265SDimitry Andricdef : Pat<(riscv_add_tprel GPR:$rs1, GPR:$rs2, tglobaltlsaddr:$src), 136981ad6265SDimitry Andric (PseudoAddTPRel GPR:$rs1, GPR:$rs2, tglobaltlsaddr:$src)>; 137081ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$src, tglobaltlsaddr:$lo), 137181ad6265SDimitry Andric (ADDI GPR:$src, tglobaltlsaddr:$lo)>; 13720b57cec5SDimitry Andric 13730b57cec5SDimitry Andric/// Setcc 13740b57cec5SDimitry Andric 13750b57cec5SDimitry Andricdef : PatGprGpr<setlt, SLT>; 13760b57cec5SDimitry Andricdef : PatGprSimm12<setlt, SLTI>; 13770b57cec5SDimitry Andricdef : PatGprGpr<setult, SLTU>; 13780b57cec5SDimitry Andricdef : PatGprSimm12<setult, SLTIU>; 13790b57cec5SDimitry Andric 138006c3fb27SDimitry Andric// RISC-V doesn't have general instructions for integer setne/seteq, but we can 138106c3fb27SDimitry Andric// check for equality with 0. These ComplexPatterns rewrite the setne/seteq into 138206c3fb27SDimitry Andric// something that can be compared with 0. 138306c3fb27SDimitry Andric// These ComplexPatterns must be used in pairs. 138406c3fb27SDimitry Andricdef riscv_setne : ComplexPattern<XLenVT, 1, "selectSETNE", [setcc]>; 138506c3fb27SDimitry Andricdef riscv_seteq : ComplexPattern<XLenVT, 1, "selectSETEQ", [setcc]>; 138606c3fb27SDimitry Andric 13870b57cec5SDimitry Andric// Define pattern expansions for setcc operations that aren't directly 13880b57cec5SDimitry Andric// handled by a RISC-V instruction. 138906c3fb27SDimitry Andricdef : Pat<(riscv_seteq (XLenVT GPR:$rs1)), (SLTIU GPR:$rs1, 1)>; 139006c3fb27SDimitry Andricdef : Pat<(riscv_setne (XLenVT GPR:$rs1)), (SLTU (XLenVT X0), GPR:$rs1)>; 139106c3fb27SDimitry Andricdef : Pat<(XLenVT (setne (XLenVT GPR:$rs1), -1)), (SLTIU GPR:$rs1, -1)>; 1392fcaf7f86SDimitry Andric 1393349cc55cSDimitry Andricdef IntCCtoRISCVCC : SDNodeXForm<riscv_selectcc, [{ 1394349cc55cSDimitry Andric ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get(); 1395349cc55cSDimitry Andric RISCVCC::CondCode BrCC = getRISCVCCForIntCC(CC); 1396349cc55cSDimitry Andric return CurDAG->getTargetConstant(BrCC, SDLoc(N), Subtarget->getXLenVT()); 1397349cc55cSDimitry Andric}]>; 1398349cc55cSDimitry Andric 1399349cc55cSDimitry Andricdef riscv_selectcc_frag : PatFrag<(ops node:$lhs, node:$rhs, node:$cc, 1400349cc55cSDimitry Andric node:$truev, node:$falsev), 1401349cc55cSDimitry Andric (riscv_selectcc node:$lhs, node:$rhs, 1402349cc55cSDimitry Andric node:$cc, node:$truev, 1403349cc55cSDimitry Andric node:$falsev), [{}], 1404349cc55cSDimitry Andric IntCCtoRISCVCC>; 1405349cc55cSDimitry Andric 140606c3fb27SDimitry Andricmulticlass SelectCC_GPR_rrirr<DAGOperand valty, ValueType vt> { 14070b57cec5SDimitry Andric let usesCustomInserter = 1 in 1408bdd1243dSDimitry Andric def _Using_CC_GPR : Pseudo<(outs valty:$dst), 1409bdd1243dSDimitry Andric (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 14100b57cec5SDimitry Andric valty:$truev, valty:$falsev), 1411349cc55cSDimitry Andric [(set valty:$dst, 141206c3fb27SDimitry Andric (riscv_selectcc_frag:$cc (XLenVT GPR:$lhs), GPR:$rhs, cond, 141306c3fb27SDimitry Andric (vt valty:$truev), valty:$falsev))]>; 1414bdd1243dSDimitry Andric // Explicitly select 0 in the condition to X0. The register coalescer doesn't 1415bdd1243dSDimitry Andric // always do it. 141606c3fb27SDimitry Andric def : Pat<(riscv_selectcc_frag:$cc (XLenVT GPR:$lhs), 0, cond, (vt valty:$truev), 1417bdd1243dSDimitry Andric valty:$falsev), 141806c3fb27SDimitry Andric (!cast<Instruction>(NAME#"_Using_CC_GPR") GPR:$lhs, (XLenVT X0), 1419bdd1243dSDimitry Andric (IntCCtoRISCVCC $cc), valty:$truev, valty:$falsev)>; 1420bdd1243dSDimitry Andric} 14210b57cec5SDimitry Andric 14221db9f3b2SDimitry Andriclet Predicates = [NoConditionalMoveFusion] in 142306c3fb27SDimitry Andricdefm Select_GPR : SelectCC_GPR_rrirr<GPR, XLenVT>; 1424bdd1243dSDimitry Andric 142506c3fb27SDimitry Andricclass SelectCompressOpt<CondCode Cond> 142606c3fb27SDimitry Andric : Pat<(riscv_selectcc_frag:$select (XLenVT GPR:$lhs), simm12_no6:$Constant, Cond, 142706c3fb27SDimitry Andric (XLenVT GPR:$truev), GPR:$falsev), 1428*0fca6ea1SDimitry Andric (Select_GPR_Using_CC_GPR (XLenVT (ADDI GPR:$lhs, (NegImm simm12:$Constant))), (XLenVT X0), 1429bdd1243dSDimitry Andric (IntCCtoRISCVCC $select), GPR:$truev, GPR:$falsev)>; 1430bdd1243dSDimitry Andric 1431bdd1243dSDimitry Andricdef OptForMinSize : Predicate<"MF ? MF->getFunction().hasMinSize() : false">; 1432bdd1243dSDimitry Andric 1433bdd1243dSDimitry Andriclet Predicates = [HasStdExtC, OptForMinSize] in { 1434bdd1243dSDimitry Andric def : SelectCompressOpt<SETEQ>; 1435bdd1243dSDimitry Andric def : SelectCompressOpt<SETNE>; 1436bdd1243dSDimitry Andric} 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric/// Branches and jumps 14390b57cec5SDimitry Andric 1440fe6060f1SDimitry Andric// Match `riscv_brcc` and lower to the appropriate RISC-V branch instruction. 1441bdd1243dSDimitry Andricmulticlass BccPat<CondCode Cond, RVInstB Inst> { 144206c3fb27SDimitry Andric def : Pat<(riscv_brcc (XLenVT GPR:$rs1), GPR:$rs2, Cond, bb:$imm12), 14430b57cec5SDimitry Andric (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>; 1444bdd1243dSDimitry Andric // Explicitly select 0 to X0. The register coalescer doesn't always do it. 144506c3fb27SDimitry Andric def : Pat<(riscv_brcc (XLenVT GPR:$rs1), 0, Cond, bb:$imm12), 144606c3fb27SDimitry Andric (Inst GPR:$rs1, (XLenVT X0), simm13_lsb0:$imm12)>; 1447bdd1243dSDimitry Andric} 14480b57cec5SDimitry Andric 144906c3fb27SDimitry Andricclass BrccCompressOpt<CondCode Cond, RVInstB Inst> 145006c3fb27SDimitry Andric : Pat<(riscv_brcc GPR:$lhs, simm12_no6:$Constant, Cond, bb:$place), 1451*0fca6ea1SDimitry Andric (Inst (XLenVT (ADDI GPR:$lhs, (NegImm simm12:$Constant))), 1452*0fca6ea1SDimitry Andric (XLenVT X0), bb:$place)>; 1453bdd1243dSDimitry Andric 1454bdd1243dSDimitry Andricdefm : BccPat<SETEQ, BEQ>; 1455bdd1243dSDimitry Andricdefm : BccPat<SETNE, BNE>; 1456bdd1243dSDimitry Andricdefm : BccPat<SETLT, BLT>; 1457bdd1243dSDimitry Andricdefm : BccPat<SETGE, BGE>; 1458bdd1243dSDimitry Andricdefm : BccPat<SETULT, BLTU>; 1459bdd1243dSDimitry Andricdefm : BccPat<SETUGE, BGEU>; 1460bdd1243dSDimitry Andric 1461*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtCOrZca, OptForMinSize] in { 146206c3fb27SDimitry Andric def : BrccCompressOpt<SETEQ, BEQ>; 146306c3fb27SDimitry Andric def : BrccCompressOpt<SETNE, BNE>; 1464bdd1243dSDimitry Andric} 14650b57cec5SDimitry Andric 146606c3fb27SDimitry Andricclass LongBccPseudo : Pseudo<(outs), 146706c3fb27SDimitry Andric (ins GPR:$rs1, GPR:$rs2, simm21_lsb0_jal:$imm20), 146806c3fb27SDimitry Andric []> { 146906c3fb27SDimitry Andric let Size = 8; 147006c3fb27SDimitry Andric let isBarrier = 1; 147106c3fb27SDimitry Andric let isBranch = 1; 147206c3fb27SDimitry Andric let hasSideEffects = 0; 147306c3fb27SDimitry Andric let mayStore = 0; 147406c3fb27SDimitry Andric let mayLoad = 0; 147506c3fb27SDimitry Andric let isAsmParserOnly = 1; 147606c3fb27SDimitry Andric let hasNoSchedulingInfo = 1; 147706c3fb27SDimitry Andric} 147806c3fb27SDimitry Andric 147906c3fb27SDimitry Andricdef PseudoLongBEQ : LongBccPseudo; 148006c3fb27SDimitry Andricdef PseudoLongBNE : LongBccPseudo; 148106c3fb27SDimitry Andricdef PseudoLongBLT : LongBccPseudo; 148206c3fb27SDimitry Andricdef PseudoLongBGE : LongBccPseudo; 148306c3fb27SDimitry Andricdef PseudoLongBLTU : LongBccPseudo; 148406c3fb27SDimitry Andricdef PseudoLongBGEU : LongBccPseudo; 148506c3fb27SDimitry Andric 14860b57cec5SDimitry Andriclet isBarrier = 1, isBranch = 1, isTerminator = 1 in 14870b57cec5SDimitry Andricdef PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>, 14880b57cec5SDimitry Andric PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>; 14890b57cec5SDimitry Andric 1490*0fca6ea1SDimitry Andriclet Predicates = [NoStdExtZicfilp], 1491*0fca6ea1SDimitry Andric isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in 1492fe6060f1SDimitry Andricdef PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12:$imm12), []>, 14930b57cec5SDimitry Andric PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; 14940b57cec5SDimitry Andric 1495*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZicfilp], 1496*0fca6ea1SDimitry Andric isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in { 1497*0fca6ea1SDimitry Andricdef PseudoBRINDNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1, simm12:$imm12), []>, 1498*0fca6ea1SDimitry Andric PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; 1499*0fca6ea1SDimitry Andricdef PseudoBRINDX7 : Pseudo<(outs), (ins GPRX7:$rs1, simm12:$imm12), []>, 1500*0fca6ea1SDimitry Andric PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; 1501*0fca6ea1SDimitry Andric} 1502*0fca6ea1SDimitry Andric 1503*0fca6ea1SDimitry Andric// For Zicfilp, need to avoid using X7/T2 for indirect branches which need 1504*0fca6ea1SDimitry Andric// landing pad. 1505*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZicfilp] in { 1506*0fca6ea1SDimitry Andricdef : Pat<(brind GPRJALRNonX7:$rs1), (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, 0)>; 1507*0fca6ea1SDimitry Andricdef : Pat<(brind (add GPRJALRNonX7:$rs1, simm12:$imm12)), 1508*0fca6ea1SDimitry Andric (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, simm12:$imm12)>; 1509*0fca6ea1SDimitry Andric 1510*0fca6ea1SDimitry Andricdef : Pat<(riscv_sw_guarded_brind GPRX7:$rs1), (PseudoBRINDX7 GPRX7:$rs1, 0)>; 1511*0fca6ea1SDimitry Andricdef : Pat<(riscv_sw_guarded_brind (add GPRX7:$rs1, simm12:$imm12)), 1512*0fca6ea1SDimitry Andric (PseudoBRINDX7 GPRX7:$rs1, simm12:$imm12)>; 1513*0fca6ea1SDimitry Andric} 1514*0fca6ea1SDimitry Andric 1515*0fca6ea1SDimitry Andriclet Predicates = [NoStdExtZicfilp] in { 1516fe6060f1SDimitry Andricdef : Pat<(brind GPRJALR:$rs1), (PseudoBRIND GPRJALR:$rs1, 0)>; 1517fe6060f1SDimitry Andricdef : Pat<(brind (add GPRJALR:$rs1, simm12:$imm12)), 1518fe6060f1SDimitry Andric (PseudoBRIND GPRJALR:$rs1, simm12:$imm12)>; 1519*0fca6ea1SDimitry Andric} 15200b57cec5SDimitry Andric 1521480093f4SDimitry Andric// PseudoCALLReg is a generic pseudo instruction for calls which will eventually 15220b57cec5SDimitry Andric// expand to auipc and jalr while encoding, with any given register used as the 15230b57cec5SDimitry Andric// destination. 15240b57cec5SDimitry Andric// Define AsmString to print "call" when compile with -S flag. 15250b57cec5SDimitry Andric// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 15261fd87a68SDimitry Andriclet isCall = 1, isBarrier = 1, isCodeGenOnly = 0, Size = 8, hasSideEffects = 0, 15270b57cec5SDimitry Andric mayStore = 0, mayLoad = 0 in 152806c3fb27SDimitry Andricdef PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), [], 152906c3fb27SDimitry Andric "call", "$rd, $func">, 153006c3fb27SDimitry Andric Sched<[WriteIALU, WriteJalr, ReadJalr]>; 15310b57cec5SDimitry Andric 15320b57cec5SDimitry Andric// PseudoCALL is a pseudo instruction which will eventually expand to auipc 15330b57cec5SDimitry Andric// and jalr while encoding. This is desirable, as an auipc+jalr pair with 15340b57cec5SDimitry Andric// R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker 15350b57cec5SDimitry Andric// if the offset fits in a signed 21-bit immediate. 15360b57cec5SDimitry Andric// Define AsmString to print "call" when compile with -S flag. 15370b57cec5SDimitry Andric// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 15381fd87a68SDimitry Andriclet isCall = 1, Defs = [X1], isCodeGenOnly = 0, Size = 8 in 153906c3fb27SDimitry Andricdef PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), [], 154006c3fb27SDimitry Andric "call", "$func">, 154106c3fb27SDimitry Andric Sched<[WriteIALU, WriteJalr, ReadJalr]>; 15420b57cec5SDimitry Andric 15430b57cec5SDimitry Andricdef : Pat<(riscv_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>; 15440b57cec5SDimitry Andricdef : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>; 15450b57cec5SDimitry Andric 154606c3fb27SDimitry Andricdef : Pat<(riscv_sret_glue), (SRET (XLenVT X0), (XLenVT X0))>; 154706c3fb27SDimitry Andricdef : Pat<(riscv_mret_glue), (MRET (XLenVT X0), (XLenVT X0))>; 15480b57cec5SDimitry Andric 1549*0fca6ea1SDimitry Andriclet isCall = 1, Defs = [X1] in { 1550*0fca6ea1SDimitry Andriclet Predicates = [NoStdExtZicfilp] in 1551fe6060f1SDimitry Andricdef PseudoCALLIndirect : Pseudo<(outs), (ins GPRJALR:$rs1), 1552fe6060f1SDimitry Andric [(riscv_call GPRJALR:$rs1)]>, 15530b57cec5SDimitry Andric PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>; 1554*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZicfilp] in 1555*0fca6ea1SDimitry Andricdef PseudoCALLIndirectNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1), 1556*0fca6ea1SDimitry Andric [(riscv_call GPRJALRNonX7:$rs1)]>, 1557*0fca6ea1SDimitry Andric PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>; 1558*0fca6ea1SDimitry Andric} 15590b57cec5SDimitry Andric 15600b57cec5SDimitry Andriclet isBarrier = 1, isReturn = 1, isTerminator = 1 in 156106c3fb27SDimitry Andricdef PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_glue)]>, 15620b57cec5SDimitry Andric PseudoInstExpansion<(JALR X0, X1, 0)>; 15630b57cec5SDimitry Andric 15640b57cec5SDimitry Andric// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually 15650b57cec5SDimitry Andric// expand to auipc and jalr while encoding. 15660b57cec5SDimitry Andric// Define AsmString to print "tail" when compile with -S flag. 15670b57cec5SDimitry Andriclet isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2], 15681fd87a68SDimitry Andric Size = 8, isCodeGenOnly = 0 in 156906c3fb27SDimitry Andricdef PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), [], 157006c3fb27SDimitry Andric "tail", "$dst">, 157106c3fb27SDimitry Andric Sched<[WriteIALU, WriteJalr, ReadJalr]>; 15720b57cec5SDimitry Andric 1573*0fca6ea1SDimitry Andriclet isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in { 1574*0fca6ea1SDimitry Andriclet Predicates = [NoStdExtZicfilp] in 15750b57cec5SDimitry Andricdef PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1), 15760b57cec5SDimitry Andric [(riscv_tail GPRTC:$rs1)]>, 15770b57cec5SDimitry Andric PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>; 1578*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZicfilp] in 1579*0fca6ea1SDimitry Andricdef PseudoTAILIndirectNonX7 : Pseudo<(outs), (ins GPRTCNonX7:$rs1), 1580*0fca6ea1SDimitry Andric [(riscv_tail GPRTCNonX7:$rs1)]>, 1581*0fca6ea1SDimitry Andric PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>; 1582*0fca6ea1SDimitry Andric} 15830b57cec5SDimitry Andric 15840b57cec5SDimitry Andricdef : Pat<(riscv_tail (iPTR tglobaladdr:$dst)), 158581ad6265SDimitry Andric (PseudoTAIL tglobaladdr:$dst)>; 15860b57cec5SDimitry Andricdef : Pat<(riscv_tail (iPTR texternalsym:$dst)), 15870b57cec5SDimitry Andric (PseudoTAIL texternalsym:$dst)>; 15880b57cec5SDimitry Andric 15891fd87a68SDimitry Andriclet isCall = 0, isBarrier = 1, isBranch = 1, isTerminator = 1, Size = 8, 159075b4d546SDimitry Andric isCodeGenOnly = 0, hasSideEffects = 0, mayStore = 0, mayLoad = 0 in 159106c3fb27SDimitry Andricdef PseudoJump : Pseudo<(outs GPR:$rd), (ins pseudo_jump_symbol:$target), [], 159206c3fb27SDimitry Andric "jump", "$target, $rd">, 159306c3fb27SDimitry Andric Sched<[WriteIALU, WriteJalr, ReadJalr]>; 15945ffd83dbSDimitry Andric 15955f757f3fSDimitry Andric// Pseudo for a rematerializable constant materialization sequence. 15965f757f3fSDimitry Andric// This is an experimental feature enabled by 15975f757f3fSDimitry Andric// -riscv-use-rematerializable-movimm in RISCVISelDAGToDAG.cpp 15985f757f3fSDimitry Andric// It will be expanded after register allocation. 15995f757f3fSDimitry Andric// FIXME: The scheduling information does not reflect the multiple instructions. 1600*0fca6ea1SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, 1601*0fca6ea1SDimitry Andric isReMaterializable = 1 in 16025f757f3fSDimitry Andricdef PseudoMovImm : Pseudo<(outs GPR:$dst), (ins i32imm:$imm), []>, 16035f757f3fSDimitry Andric Sched<[WriteIALU]>; 16045f757f3fSDimitry Andric 16051fd87a68SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0, 16060b57cec5SDimitry Andric isAsmParserOnly = 1 in 16070b57cec5SDimitry Andricdef PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 16080b57cec5SDimitry Andric "lla", "$dst, $src">; 16090b57cec5SDimitry Andric 161006c3fb27SDimitry Andric// Refer to comment on PseudoLI for explanation of Size=32 161106c3fb27SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0, 161206c3fb27SDimitry Andric isAsmParserOnly = 1 in 161306c3fb27SDimitry Andricdef PseudoLLAImm : Pseudo<(outs GPR:$dst), (ins ixlenimm_li_restricted:$imm), [], 161406c3fb27SDimitry Andric "lla", "$dst, $imm">; 161581ad6265SDimitry Andricdef : Pat<(riscv_lla tglobaladdr:$in), (PseudoLLA tglobaladdr:$in)>; 161681ad6265SDimitry Andricdef : Pat<(riscv_lla tblockaddress:$in), (PseudoLLA tblockaddress:$in)>; 161781ad6265SDimitry Andricdef : Pat<(riscv_lla tjumptable:$in), (PseudoLLA tjumptable:$in)>; 161881ad6265SDimitry Andricdef : Pat<(riscv_lla tconstpool:$in), (PseudoLLA tconstpool:$in)>; 161981ad6265SDimitry Andric 16201fd87a68SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0, 16210b57cec5SDimitry Andric isAsmParserOnly = 1 in 162206c3fb27SDimitry Andricdef PseudoLGA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 162306c3fb27SDimitry Andric "lga", "$dst, $src">; 162406c3fb27SDimitry Andric 162506c3fb27SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0, 162606c3fb27SDimitry Andric isAsmParserOnly = 1 in 16270b57cec5SDimitry Andricdef PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 16280b57cec5SDimitry Andric "la", "$dst, $src">; 16290b57cec5SDimitry Andric 163006c3fb27SDimitry Andric// Refer to comment on PseudoLI for explanation of Size=32 163106c3fb27SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32, 163206c3fb27SDimitry Andric isCodeGenOnly = 0, isAsmParserOnly = 1 in 163306c3fb27SDimitry Andricdef PseudoLAImm : Pseudo<(outs GPR:$rd), (ins ixlenimm_li_restricted:$imm), [], 163406c3fb27SDimitry Andric "la", "$rd, $imm">; 163581ad6265SDimitry Andric 16361fd87a68SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0, 16370b57cec5SDimitry Andric isAsmParserOnly = 1 in 16380b57cec5SDimitry Andricdef PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 16390b57cec5SDimitry Andric "la.tls.ie", "$dst, $src">; 16400b57cec5SDimitry Andric 164181ad6265SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0, 16420b57cec5SDimitry Andric isAsmParserOnly = 1 in 16430b57cec5SDimitry Andricdef PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 16440b57cec5SDimitry Andric "la.tls.gd", "$dst, $src">; 16450b57cec5SDimitry Andric 16467a6dacacSDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 32, isCodeGenOnly = 0 in 16477a6dacacSDimitry Andricdef PseudoLA_TLSDESC : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 16487a6dacacSDimitry Andric "la.tlsdesc", "$dst, $src">; 16497a6dacacSDimitry Andric 16507a6dacacSDimitry Andricdef TLSDESCCallSymbol : AsmOperandClass { 16517a6dacacSDimitry Andric let Name = "TLSDESCCallSymbol"; 16527a6dacacSDimitry Andric let RenderMethod = "addImmOperands"; 16537a6dacacSDimitry Andric let DiagnosticType = "InvalidTLSDESCCallSymbol"; 16547a6dacacSDimitry Andric let ParserMethod = "parseOperandWithModifier"; 16557a6dacacSDimitry Andric} 16567a6dacacSDimitry Andric 16577a6dacacSDimitry Andric// A bare symbol with the %tlsdesc_call variant. 16587a6dacacSDimitry Andricdef tlsdesc_call_symbol : Operand<XLenVT> { 16597a6dacacSDimitry Andric let ParserMatchClass = TLSDESCCallSymbol; 16607a6dacacSDimitry Andric} 16617a6dacacSDimitry Andric// This is a special case of the JALR instruction used to facilitate the use of a 16627a6dacacSDimitry Andric// fourth operand to emit a relocation on a symbol relating to this instruction. 16637a6dacacSDimitry Andric// The relocation does not affect any bits of the instruction itself but is used 16647a6dacacSDimitry Andric// as a hint to the linker. 16657a6dacacSDimitry Andriclet isCall = 1, isBarrier = 1, isCodeGenOnly = 0, Size = 8, hasSideEffects = 0, 16667a6dacacSDimitry Andric mayStore = 0, mayLoad = 0 in 16677a6dacacSDimitry Andricdef PseudoTLSDESCCall : Pseudo<(outs GPR:$rd), 16687a6dacacSDimitry Andric (ins GPR:$rs1, simm12:$imm12, tlsdesc_call_symbol:$src), [], 16697a6dacacSDimitry Andric "jalr", "$rd, ${imm12}(${rs1}), $src">, 16707a6dacacSDimitry Andric Sched<[WriteJalr, ReadJalr]> { 16717a6dacacSDimitry Andric let Defs = [X10]; 16727a6dacacSDimitry Andric let Uses = [X10]; 16737a6dacacSDimitry Andric} 16747a6dacacSDimitry Andric 1675e8d8bef9SDimitry Andric 1676e8d8bef9SDimitry Andric/// Sign/Zero Extends 1677e8d8bef9SDimitry Andric 1678e8d8bef9SDimitry Andric// There are single-instruction versions of these in Zbb, so disable these 1679e8d8bef9SDimitry Andric// Pseudos if that extension is present. 1680e8d8bef9SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, 1681e8d8bef9SDimitry Andric mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in { 1682e8d8bef9SDimitry Andricdef PseudoSEXT_B : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.b", "$rd, $rs">; 1683e8d8bef9SDimitry Andricdef PseudoSEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.h", "$rd, $rs">; 1684e8d8bef9SDimitry Andric// rv64's sext.w is defined above, using InstAlias<"sext.w ... 1685e8d8bef9SDimitry Andric// zext.b is defined above, using InstAlias<"zext.b ... 1686e8d8bef9SDimitry Andricdef PseudoZEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.h", "$rd, $rs">; 1687e8d8bef9SDimitry Andric} // hasSideEffects = 0, ... 1688e8d8bef9SDimitry Andric 1689e8d8bef9SDimitry Andriclet Predicates = [IsRV64], hasSideEffects = 0, mayLoad = 0, mayStore = 0, 1690e8d8bef9SDimitry Andric isCodeGenOnly = 0, isAsmParserOnly = 1 in { 1691e8d8bef9SDimitry Andricdef PseudoZEXT_W : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.w", "$rd, $rs">; 1692e8d8bef9SDimitry Andric} // Predicates = [IsRV64], ... 1693e8d8bef9SDimitry Andric 16940b57cec5SDimitry Andric/// Loads 16950b57cec5SDimitry Andric 169606c3fb27SDimitry Andricclass LdPat<PatFrag LoadOp, RVInst Inst, ValueType vt = XLenVT> 169706c3fb27SDimitry Andric : Pat<(vt (LoadOp (AddrRegImm (XLenVT GPR:$rs1), simm12:$imm12))), 169881ad6265SDimitry Andric (Inst GPR:$rs1, simm12:$imm12)>; 16990b57cec5SDimitry Andric 170006c3fb27SDimitry Andricdef : LdPat<sextloadi8, LB>; 170106c3fb27SDimitry Andricdef : LdPat<extloadi8, LBU>; // Prefer unsigned due to no c.lb in Zcb. 170206c3fb27SDimitry Andricdef : LdPat<sextloadi16, LH>; 170306c3fb27SDimitry Andricdef : LdPat<extloadi16, LH>; 17045f757f3fSDimitry Andricdef : LdPat<load, LW, i32>; 170506c3fb27SDimitry Andricdef : LdPat<zextloadi8, LBU>; 170606c3fb27SDimitry Andricdef : LdPat<zextloadi16, LHU>; 17070b57cec5SDimitry Andric 17080b57cec5SDimitry Andric/// Stores 17090b57cec5SDimitry Andric 171006c3fb27SDimitry Andricclass StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy, 171106c3fb27SDimitry Andric ValueType vt> 171206c3fb27SDimitry Andric : Pat<(StoreOp (vt StTy:$rs2), (AddrRegImm (XLenVT GPR:$rs1), 171306c3fb27SDimitry Andric simm12:$imm12)), 171481ad6265SDimitry Andric (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>; 17150b57cec5SDimitry Andric 171606c3fb27SDimitry Andricdef : StPat<truncstorei8, SB, GPR, XLenVT>; 171706c3fb27SDimitry Andricdef : StPat<truncstorei16, SH, GPR, XLenVT>; 17185f757f3fSDimitry Andricdef : StPat<store, SW, GPR, i32>; 17190b57cec5SDimitry Andric 17200b57cec5SDimitry Andric/// Fences 17210b57cec5SDimitry Andric 17220b57cec5SDimitry Andric// Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set 17230b57cec5SDimitry Andric// Manual: Volume I. 17240b57cec5SDimitry Andric 17250b57cec5SDimitry Andric// fence acquire -> fence r, rw 1726480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 4), (timm)), (FENCE 0b10, 0b11)>; 17270b57cec5SDimitry Andric// fence release -> fence rw, w 1728480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 5), (timm)), (FENCE 0b11, 0b1)>; 17290b57cec5SDimitry Andric// fence acq_rel -> fence.tso 1730480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 6), (timm)), (FENCE_TSO)>; 17310b57cec5SDimitry Andric// fence seq_cst -> fence rw, rw 1732480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 7), (timm)), (FENCE 0b11, 0b11)>; 17330b57cec5SDimitry Andric 17340b57cec5SDimitry Andric// Lowering for atomic load and store is defined in RISCVInstrInfoA.td. 17350b57cec5SDimitry Andric// Although these are lowered to fence+load/store instructions defined in the 17360b57cec5SDimitry Andric// base RV32I/RV64I ISA, this lowering is only used when the A extension is 17370b57cec5SDimitry Andric// present. This is necessary as it isn't valid to mix __atomic_* libcalls 17380b57cec5SDimitry Andric// with inline atomic operations for the same object. 17390b57cec5SDimitry Andric 1740fe6060f1SDimitry Andric/// Access to system registers 1741fe6060f1SDimitry Andric 1742fe6060f1SDimitry Andric// Helpers for defining specific operations. They are defined for each system 1743fe6060f1SDimitry Andric// register separately. Side effect is not used because dependencies are 1744fe6060f1SDimitry Andric// expressed via use-def properties. 1745fe6060f1SDimitry Andric 1746fe6060f1SDimitry Andricclass ReadSysReg<SysReg SR, list<Register> Regs> 1747fe6060f1SDimitry Andric : Pseudo<(outs GPR:$rd), (ins), 174806c3fb27SDimitry Andric [(set GPR:$rd, (XLenVT (riscv_read_csr (XLenVT SR.Encoding))))]>, 1749fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRS GPR:$rd, SR.Encoding, X0)> { 1750fe6060f1SDimitry Andric let hasSideEffects = 0; 1751fe6060f1SDimitry Andric let Uses = Regs; 1752fe6060f1SDimitry Andric} 1753fe6060f1SDimitry Andric 1754fe6060f1SDimitry Andricclass WriteSysReg<SysReg SR, list<Register> Regs> 1755fe6060f1SDimitry Andric : Pseudo<(outs), (ins GPR:$val), 175606c3fb27SDimitry Andric [(riscv_write_csr (XLenVT SR.Encoding), (XLenVT GPR:$val))]>, 1757fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRW X0, SR.Encoding, GPR:$val)> { 1758fe6060f1SDimitry Andric let hasSideEffects = 0; 1759fe6060f1SDimitry Andric let Defs = Regs; 1760fe6060f1SDimitry Andric} 1761fe6060f1SDimitry Andric 1762fe6060f1SDimitry Andricclass WriteSysRegImm<SysReg SR, list<Register> Regs> 1763fe6060f1SDimitry Andric : Pseudo<(outs), (ins uimm5:$val), 1764fe6060f1SDimitry Andric [(riscv_write_csr (XLenVT SR.Encoding), uimm5:$val)]>, 1765fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRWI X0, SR.Encoding, uimm5:$val)> { 1766fe6060f1SDimitry Andric let hasSideEffects = 0; 1767fe6060f1SDimitry Andric let Defs = Regs; 1768fe6060f1SDimitry Andric} 1769fe6060f1SDimitry Andric 1770fe6060f1SDimitry Andricclass SwapSysReg<SysReg SR, list<Register> Regs> 1771fe6060f1SDimitry Andric : Pseudo<(outs GPR:$rd), (ins GPR:$val), 177206c3fb27SDimitry Andric [(set GPR:$rd, (riscv_swap_csr (XLenVT SR.Encoding), (XLenVT GPR:$val)))]>, 1773fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRW GPR:$rd, SR.Encoding, GPR:$val)> { 1774fe6060f1SDimitry Andric let hasSideEffects = 0; 1775fe6060f1SDimitry Andric let Uses = Regs; 1776fe6060f1SDimitry Andric let Defs = Regs; 1777fe6060f1SDimitry Andric} 1778fe6060f1SDimitry Andric 1779fe6060f1SDimitry Andricclass SwapSysRegImm<SysReg SR, list<Register> Regs> 1780fe6060f1SDimitry Andric : Pseudo<(outs GPR:$rd), (ins uimm5:$val), 178106c3fb27SDimitry Andric [(set GPR:$rd, (XLenVT (riscv_swap_csr (XLenVT SR.Encoding), uimm5:$val)))]>, 1782fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRWI GPR:$rd, SR.Encoding, uimm5:$val)> { 1783fe6060f1SDimitry Andric let hasSideEffects = 0; 1784fe6060f1SDimitry Andric let Uses = Regs; 1785fe6060f1SDimitry Andric let Defs = Regs; 1786fe6060f1SDimitry Andric} 1787fe6060f1SDimitry Andric 1788fe6060f1SDimitry Andricdef ReadFRM : ReadSysReg<SysRegFRM, [FRM]>; 1789fe6060f1SDimitry Andricdef WriteFRM : WriteSysReg<SysRegFRM, [FRM]>; 1790fe6060f1SDimitry Andricdef WriteFRMImm : WriteSysRegImm<SysRegFRM, [FRM]>; 1791bdd1243dSDimitry Andricdef SwapFRMImm : SwapSysRegImm<SysRegFRM, [FRM]>; 1792fe6060f1SDimitry Andric 179306c3fb27SDimitry Andricdef WriteVXRMImm : WriteSysRegImm<SysRegVXRM, [VXRM]>; 179406c3fb27SDimitry Andric 179504eeddc0SDimitry Andriclet hasSideEffects = true in { 179604eeddc0SDimitry Andricdef ReadFFLAGS : ReadSysReg<SysRegFFLAGS, [FFLAGS]>; 179704eeddc0SDimitry Andricdef WriteFFLAGS : WriteSysReg<SysRegFFLAGS, [FFLAGS]>; 179804eeddc0SDimitry Andric} 17990b57cec5SDimitry Andric/// Other pseudo-instructions 18000b57cec5SDimitry Andric 18010b57cec5SDimitry Andric// Pessimistically assume the stack pointer will be clobbered 18020b57cec5SDimitry Andriclet Defs = [X2], Uses = [X2] in { 18030b57cec5SDimitry Andricdef ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 18040b57cec5SDimitry Andric [(callseq_start timm:$amt1, timm:$amt2)]>; 18050b57cec5SDimitry Andricdef ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 18060b57cec5SDimitry Andric [(callseq_end timm:$amt1, timm:$amt2)]>; 18070b57cec5SDimitry Andric} // Defs = [X2], Uses = [X2] 18080b57cec5SDimitry Andric 18090b57cec5SDimitry Andric/// RV64 patterns 18100b57cec5SDimitry Andric 1811e8d8bef9SDimitry Andriclet Predicates = [IsRV64, NotHasStdExtZba] in { 1812*0fca6ea1SDimitry Andricdef : Pat<(i64 (and GPR:$rs1, 0xffffffff)), (SRLI (i64 (SLLI GPR:$rs1, 32)), 32)>; 1813e8d8bef9SDimitry Andric 1814e8d8bef9SDimitry Andric// If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2 1815e8d8bef9SDimitry Andric// shifts instead of 3. This can occur when unsigned is used to index an array. 1816fe6060f1SDimitry Andricdef : Pat<(i64 (shl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)), 1817*0fca6ea1SDimitry Andric (SRLI (i64 (SLLI GPR:$rs1, 32)), (ImmSubFrom32 uimm5:$shamt))>; 1818e8d8bef9SDimitry Andric} 1819e8d8bef9SDimitry Andric 18205f757f3fSDimitry Andricclass binop_allhusers<SDPatternOperator operator> 18215f757f3fSDimitry Andric : PatFrag<(ops node:$lhs, node:$rhs), 18225f757f3fSDimitry Andric (XLenVT (operator node:$lhs, node:$rhs)), [{ 18235f757f3fSDimitry Andric return hasAllHUsers(Node); 18245f757f3fSDimitry Andric}]>; 18255f757f3fSDimitry Andric 1826349cc55cSDimitry Andric// PatFrag to allow ADDW/SUBW/MULW/SLLW to be selected from i64 add/sub/mul/shl 1827349cc55cSDimitry Andric// if only the lower 32 bits of their result is used. 1828349cc55cSDimitry Andricclass binop_allwusers<SDPatternOperator operator> 1829349cc55cSDimitry Andric : PatFrag<(ops node:$lhs, node:$rhs), 183081ad6265SDimitry Andric (i64 (operator node:$lhs, node:$rhs)), [{ 1831349cc55cSDimitry Andric return hasAllWUsers(Node); 1832349cc55cSDimitry Andric}]>; 1833349cc55cSDimitry Andric 1834349cc55cSDimitry Andricdef sexti32_allwusers : PatFrag<(ops node:$src), 1835349cc55cSDimitry Andric (sext_inreg node:$src, i32), [{ 1836349cc55cSDimitry Andric return hasAllWUsers(Node); 1837349cc55cSDimitry Andric}]>; 1838349cc55cSDimitry Andric 1839bdd1243dSDimitry Andricdef ImmSExt32 : SDNodeXForm<imm, [{ 1840bdd1243dSDimitry Andric return CurDAG->getTargetConstant(SignExtend64<32>(N->getSExtValue()), 1841bdd1243dSDimitry Andric SDLoc(N), N->getValueType(0)); 1842bdd1243dSDimitry Andric}]>; 1843bdd1243dSDimitry Andric// Look for constants where the upper 32 bits are 0, but sign extending bit 31 1844bdd1243dSDimitry Andric// would be an simm12. 1845bdd1243dSDimitry Andricdef u32simm12 : ImmLeaf<XLenVT, [{ 1846bdd1243dSDimitry Andric return isUInt<32>(Imm) && isInt<12>(SignExtend64<32>(Imm)); 1847bdd1243dSDimitry Andric}], ImmSExt32>; 1848bdd1243dSDimitry Andric 18490b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 18500b57cec5SDimitry Andric 1851bdd1243dSDimitry Andricdef : Pat<(i64 (and GPR:$rs, LeadingOnesWMask:$mask)), 1852*0fca6ea1SDimitry Andric (SLLI (i64 (SRLIW $rs, LeadingOnesWMask:$mask)), LeadingOnesWMask:$mask)>; 1853bdd1243dSDimitry Andric 18540b57cec5SDimitry Andric/// sext and zext 18550b57cec5SDimitry Andric 1856349cc55cSDimitry Andric// Sign extend is not needed if all users are W instructions. 1857349cc55cSDimitry Andricdef : Pat<(sexti32_allwusers GPR:$rs1), (XLenVT GPR:$rs1)>; 1858349cc55cSDimitry Andric 18590b57cec5SDimitry Andricdef : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>; 18600b57cec5SDimitry Andric 18610b57cec5SDimitry Andric/// ALU operations 18620b57cec5SDimitry Andric 1863fe6060f1SDimitry Andricdef : Pat<(i64 (srl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)), 1864e8d8bef9SDimitry Andric (SRLIW GPR:$rs1, uimm5:$shamt)>; 1865fe6060f1SDimitry Andricdef : Pat<(i64 (srl (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)), 1866e8d8bef9SDimitry Andric (SRLIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>; 18670b57cec5SDimitry Andricdef : Pat<(sra (sext_inreg GPR:$rs1, i32), uimm5:$shamt), 18680b57cec5SDimitry Andric (SRAIW GPR:$rs1, uimm5:$shamt)>; 1869fe6060f1SDimitry Andricdef : Pat<(i64 (sra (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)), 1870e8d8bef9SDimitry Andric (SRAIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>; 18710b57cec5SDimitry Andric 1872e8d8bef9SDimitry Andricdef : PatGprGpr<shiftopw<riscv_sllw>, SLLW>; 1873e8d8bef9SDimitry Andricdef : PatGprGpr<shiftopw<riscv_srlw>, SRLW>; 1874e8d8bef9SDimitry Andricdef : PatGprGpr<shiftopw<riscv_sraw>, SRAW>; 18750b57cec5SDimitry Andric 1876349cc55cSDimitry Andric// Select W instructions if only the lower 32 bits of the result are used. 1877349cc55cSDimitry Andricdef : PatGprGpr<binop_allwusers<add>, ADDW>; 1878349cc55cSDimitry Andricdef : PatGprSimm12<binop_allwusers<add>, ADDIW>; 1879349cc55cSDimitry Andricdef : PatGprGpr<binop_allwusers<sub>, SUBW>; 1880349cc55cSDimitry Andricdef : PatGprImm<binop_allwusers<shl>, SLLIW, uimm5>; 1881349cc55cSDimitry Andric 1882349cc55cSDimitry Andric// If this is a shr of a value sign extended from i32, and all the users only 1883349cc55cSDimitry Andric// use the lower 32 bits, we can use an sraiw to remove the sext_inreg. This 1884349cc55cSDimitry Andric// occurs because SimplifyDemandedBits prefers srl over sra. 1885349cc55cSDimitry Andricdef : Pat<(binop_allwusers<srl> (sext_inreg GPR:$rs1, i32), uimm5:$shamt), 1886349cc55cSDimitry Andric (SRAIW GPR:$rs1, uimm5:$shamt)>; 1887349cc55cSDimitry Andric 1888bdd1243dSDimitry Andric// Use binop_allwusers to recover immediates that may have been broken by 1889bdd1243dSDimitry Andric// SimplifyDemandedBits. 1890*0fca6ea1SDimitry Andricdef : Pat<(binop_allwusers<and> GPR:$rs1, 0xffffffff), 1891*0fca6ea1SDimitry Andric (COPY GPR:$rs1)>; 1892bdd1243dSDimitry Andricdef : Pat<(binop_allwusers<and> GPR:$rs1, u32simm12:$imm), 1893bdd1243dSDimitry Andric (ANDI GPR:$rs1, u32simm12:$imm)>; 1894bdd1243dSDimitry Andric 1895bdd1243dSDimitry Andricdef : Pat<(binop_allwusers<or> GPR:$rs1, u32simm12:$imm), 1896bdd1243dSDimitry Andric (ORI GPR:$rs1, u32simm12:$imm)>; 1897bdd1243dSDimitry Andric 1898bdd1243dSDimitry Andricdef : Pat<(binop_allwusers<xor> GPR:$rs1, u32simm12:$imm), 1899bdd1243dSDimitry Andric (XORI GPR:$rs1, u32simm12:$imm)>; 19000b57cec5SDimitry Andric/// Loads 19010b57cec5SDimitry Andric 190206c3fb27SDimitry Andricdef : LdPat<sextloadi32, LW, i64>; 190306c3fb27SDimitry Andricdef : LdPat<extloadi32, LW, i64>; 190406c3fb27SDimitry Andricdef : LdPat<zextloadi32, LWU, i64>; 190506c3fb27SDimitry Andricdef : LdPat<load, LD, i64>; 19060b57cec5SDimitry Andric 19070b57cec5SDimitry Andric/// Stores 19080b57cec5SDimitry Andric 190906c3fb27SDimitry Andricdef : StPat<truncstorei32, SW, GPR, i64>; 191006c3fb27SDimitry Andricdef : StPat<store, SD, GPR, i64>; 19110b57cec5SDimitry Andric} // Predicates = [IsRV64] 19120b57cec5SDimitry Andric 1913*0fca6ea1SDimitry Andric// On RV64, we can directly read these 64-bit counter CSRs. 1914*0fca6ea1SDimitry Andriclet Predicates = [IsRV64] in { 19150b57cec5SDimitry Andric/// readcyclecounter 191606c3fb27SDimitry Andricdef : Pat<(i64 (readcyclecounter)), (CSRRS CYCLE.Encoding, (XLenVT X0))>; 1917*0fca6ea1SDimitry Andric/// readsteadycounter 1918*0fca6ea1SDimitry Andricdef : Pat<(i64 (readsteadycounter)), (CSRRS TIME.Encoding, (XLenVT X0))>; 1919*0fca6ea1SDimitry Andric} 1920*0fca6ea1SDimitry Andric 1921*0fca6ea1SDimitry Andric// On RV32, ReadCounterWide will be expanded to the suggested loop reading both 1922*0fca6ea1SDimitry Andric// halves of 64-bit counter CSRs. 1923e8d8bef9SDimitry Andriclet Predicates = [IsRV32], usesCustomInserter = 1, hasNoSchedulingInfo = 1 in 1924*0fca6ea1SDimitry Andricdef ReadCounterWide : Pseudo<(outs GPR:$lo, GPR:$hi), (ins i32imm:$csr_lo, i32imm:$csr_hi), 1925*0fca6ea1SDimitry Andric [(set GPR:$lo, GPR:$hi, 1926*0fca6ea1SDimitry Andric (riscv_read_counter_wide csr_sysreg:$csr_lo, csr_sysreg:$csr_hi))], 1927e8d8bef9SDimitry Andric "", "">; 19280b57cec5SDimitry Andric 1929480093f4SDimitry Andric/// traps 1930480093f4SDimitry Andric 1931480093f4SDimitry Andric// We lower `trap` to `unimp`, as this causes a hard exception on nearly all 1932480093f4SDimitry Andric// systems. 1933480093f4SDimitry Andricdef : Pat<(trap), (UNIMP)>; 1934480093f4SDimitry Andric 1935480093f4SDimitry Andric// We lower `debugtrap` to `ebreak`, as this will get the attention of the 1936480093f4SDimitry Andric// debugger if possible. 1937480093f4SDimitry Andricdef : Pat<(debugtrap), (EBREAK)>; 1938480093f4SDimitry Andric 1939bdd1243dSDimitry Andriclet Predicates = [IsRV64], Uses = [X5], 1940*0fca6ea1SDimitry Andric Defs = [X1, X6, X7, X28, X29, X30, X31], Size = 8 in 1941bdd1243dSDimitry Andricdef HWASAN_CHECK_MEMACCESS_SHORTGRANULES 1942bdd1243dSDimitry Andric : Pseudo<(outs), (ins GPRJALR:$ptr, i32imm:$accessinfo), 19435f757f3fSDimitry Andric [(int_hwasan_check_memaccess_shortgranules (i64 X5), GPRJALR:$ptr, 1944bdd1243dSDimitry Andric (i32 timm:$accessinfo))]>; 1945bdd1243dSDimitry Andric 194606c3fb27SDimitry Andric// This gets lowered into a 20-byte instruction sequence (at most) 194706c3fb27SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, 194806c3fb27SDimitry Andric Defs = [ X6, X7, X28, X29, X30, X31 ], Size = 20 in { 194906c3fb27SDimitry Andricdef KCFI_CHECK 195006c3fb27SDimitry Andric : Pseudo<(outs), (ins GPRJALR:$ptr, i32imm:$type), []>, Sched<[]>; 195106c3fb27SDimitry Andric} 195206c3fb27SDimitry Andric 1953fe6060f1SDimitry Andric/// Simple optimization 195406c3fb27SDimitry Andricdef : Pat<(XLenVT (add GPR:$rs1, (AddiPair:$rs2))), 1955*0fca6ea1SDimitry Andric (ADDI (XLenVT (ADDI GPR:$rs1, (AddiPairImmLarge AddiPair:$rs2))), 195681ad6265SDimitry Andric (AddiPairImmSmall GPR:$rs2))>; 1957fe6060f1SDimitry Andric 1958fe6060f1SDimitry Andriclet Predicates = [IsRV64] in { 1959349cc55cSDimitry Andric// Select W instructions if only the lower 32-bits of the result are used. 1960349cc55cSDimitry Andricdef : Pat<(binop_allwusers<add> GPR:$rs1, (AddiPair:$rs2)), 1961*0fca6ea1SDimitry Andric (ADDIW (i64 (ADDIW GPR:$rs1, (AddiPairImmLarge AddiPair:$rs2))), 196281ad6265SDimitry Andric (AddiPairImmSmall AddiPair:$rs2))>; 1963fe6060f1SDimitry Andric} 1964fe6060f1SDimitry Andric 19655f757f3fSDimitry Andric//===----------------------------------------------------------------------===// 19665f757f3fSDimitry Andric// Experimental RV64 i32 legalization patterns. 19675f757f3fSDimitry Andric//===----------------------------------------------------------------------===// 19685f757f3fSDimitry Andric 19695f757f3fSDimitry Andricdef simm12i32 : ImmLeaf<i32, [{return isInt<12>(Imm);}]>; 19705f757f3fSDimitry Andric 19715f757f3fSDimitry Andric// Convert from i32 immediate to i64 target immediate to make SelectionDAG type 19725f757f3fSDimitry Andric// checking happy so we can use ADDIW which expects an XLen immediate. 19735f757f3fSDimitry Andricdef as_i64imm : SDNodeXForm<imm, [{ 19745f757f3fSDimitry Andric return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i64); 19755f757f3fSDimitry Andric}]>; 19765f757f3fSDimitry Andric 19775f757f3fSDimitry Andricdef zext_is_sext : PatFrag<(ops node:$src), (zext node:$src), [{ 19785f757f3fSDimitry Andric KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0), 0); 19795f757f3fSDimitry Andric return Known.isNonNegative(); 19805f757f3fSDimitry Andric}]>; 19815f757f3fSDimitry Andric 19825f757f3fSDimitry Andriclet Predicates = [IsRV64] in { 19835f757f3fSDimitry Andricdef : LdPat<sextloadi8, LB, i32>; 19845f757f3fSDimitry Andricdef : LdPat<extloadi8, LBU, i32>; // Prefer unsigned due to no c.lb in Zcb. 19855f757f3fSDimitry Andricdef : LdPat<sextloadi16, LH, i32>; 19865f757f3fSDimitry Andricdef : LdPat<extloadi16, LH, i32>; 19875f757f3fSDimitry Andricdef : LdPat<zextloadi8, LBU, i32>; 19885f757f3fSDimitry Andricdef : LdPat<zextloadi16, LHU, i32>; 19895f757f3fSDimitry Andric 19905f757f3fSDimitry Andricdef : StPat<truncstorei8, SB, GPR, i32>; 19915f757f3fSDimitry Andricdef : StPat<truncstorei16, SH, GPR, i32>; 19925f757f3fSDimitry Andric 19935f757f3fSDimitry Andricdef : Pat<(anyext GPR:$src), (COPY GPR:$src)>; 19945f757f3fSDimitry Andricdef : Pat<(sext GPR:$src), (ADDIW GPR:$src, 0)>; 19955f757f3fSDimitry Andricdef : Pat<(trunc GPR:$src), (COPY GPR:$src)>; 19965f757f3fSDimitry Andric 19975f757f3fSDimitry Andricdef : PatGprGpr<add, ADDW, i32, i32>; 19985f757f3fSDimitry Andricdef : PatGprGpr<sub, SUBW, i32, i32>; 19995f757f3fSDimitry Andricdef : PatGprGpr<and, AND, i32, i32>; 20005f757f3fSDimitry Andricdef : PatGprGpr<or, OR, i32, i32>; 20015f757f3fSDimitry Andricdef : PatGprGpr<xor, XOR, i32, i32>; 20025f757f3fSDimitry Andricdef : PatGprGpr<shiftopw<shl>, SLLW, i32, i64>; 20035f757f3fSDimitry Andricdef : PatGprGpr<shiftopw<srl>, SRLW, i32, i64>; 20045f757f3fSDimitry Andricdef : PatGprGpr<shiftopw<sra>, SRAW, i32, i64>; 20055f757f3fSDimitry Andric 20065f757f3fSDimitry Andricdef : Pat<(i32 (add GPR:$rs1, simm12i32:$imm)), 20075f757f3fSDimitry Andric (ADDIW GPR:$rs1, (i64 (as_i64imm $imm)))>; 20085f757f3fSDimitry Andricdef : Pat<(i32 (and GPR:$rs1, simm12i32:$imm)), 20095f757f3fSDimitry Andric (ANDI GPR:$rs1, (i64 (as_i64imm $imm)))>; 20105f757f3fSDimitry Andricdef : Pat<(i32 (or GPR:$rs1, simm12i32:$imm)), 20115f757f3fSDimitry Andric (ORI GPR:$rs1, (i64 (as_i64imm $imm)))>; 20125f757f3fSDimitry Andricdef : Pat<(i32 (xor GPR:$rs1, simm12i32:$imm)), 20135f757f3fSDimitry Andric (XORI GPR:$rs1, (i64 (as_i64imm $imm)))>; 20145f757f3fSDimitry Andric 20155f757f3fSDimitry Andricdef : PatGprImm<shl, SLLIW, uimm5, i32>; 20165f757f3fSDimitry Andricdef : PatGprImm<srl, SRLIW, uimm5, i32>; 20175f757f3fSDimitry Andricdef : PatGprImm<sra, SRAIW, uimm5, i32>; 20185f757f3fSDimitry Andric 20195f757f3fSDimitry Andricdef : Pat<(i32 (and GPR:$rs, TrailingOnesMask:$mask)), 2020*0fca6ea1SDimitry Andric (SRLI (i32 (SLLI $rs, (i64 (XLenSubTrailingOnes $mask)))), 20215f757f3fSDimitry Andric (i64 (XLenSubTrailingOnes $mask)))>; 20225f757f3fSDimitry Andric 20235f757f3fSDimitry Andric// Use sext if the sign bit of the input is 0. 20245f757f3fSDimitry Andricdef : Pat<(zext_is_sext GPR:$src), (ADDIW GPR:$src, 0)>; 20255f757f3fSDimitry Andric} 20265f757f3fSDimitry Andric 20275f757f3fSDimitry Andriclet Predicates = [IsRV64, NotHasStdExtZba] in { 2028*0fca6ea1SDimitry Andricdef : Pat<(zext GPR:$src), (SRLI (i64 (SLLI GPR:$src, 32)), 32)>; 20295f757f3fSDimitry Andric 20305f757f3fSDimitry Andric// If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2 20315f757f3fSDimitry Andric// shifts instead of 3. This can occur when unsigned is used to index an array. 20325f757f3fSDimitry Andricdef : Pat<(shl (zext GPR:$rs), uimm5:$shamt), 2033*0fca6ea1SDimitry Andric (SRLI (i64 (SLLI GPR:$rs, 32)), (ImmSubFrom32 uimm5:$shamt))>; 20345f757f3fSDimitry Andric} 20355f757f3fSDimitry Andric 20360b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 20370b57cec5SDimitry Andric// Standard extensions 20380b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 20390b57cec5SDimitry Andric 204006c3fb27SDimitry Andric// Multiply and Division 20410b57cec5SDimitry Andricinclude "RISCVInstrInfoM.td" 204206c3fb27SDimitry Andric 204306c3fb27SDimitry Andric// Atomic 20440b57cec5SDimitry Andricinclude "RISCVInstrInfoA.td" 20451db9f3b2SDimitry Andricinclude "RISCVInstrInfoZa.td" 2046*0fca6ea1SDimitry Andricinclude "RISCVInstrInfoZalasr.td" 204706c3fb27SDimitry Andric 204806c3fb27SDimitry Andric// Scalar FP 20490b57cec5SDimitry Andricinclude "RISCVInstrInfoF.td" 20500b57cec5SDimitry Andricinclude "RISCVInstrInfoD.td" 205106c3fb27SDimitry Andricinclude "RISCVInstrInfoZfh.td" 205206c3fb27SDimitry Andricinclude "RISCVInstrInfoZfbfmin.td" 205306c3fb27SDimitry Andricinclude "RISCVInstrInfoZfa.td" 205406c3fb27SDimitry Andric 205506c3fb27SDimitry Andric// Scalar bitmanip and cryptography 2056349cc55cSDimitry Andricinclude "RISCVInstrInfoZb.td" 205704eeddc0SDimitry Andricinclude "RISCVInstrInfoZk.td" 205806c3fb27SDimitry Andric 205906c3fb27SDimitry Andric// Vector 20605ffd83dbSDimitry Andricinclude "RISCVInstrInfoV.td" 206106c3fb27SDimitry Andricinclude "RISCVInstrInfoZvk.td" 206206c3fb27SDimitry Andric 206306c3fb27SDimitry Andric// Compressed 206406c3fb27SDimitry Andricinclude "RISCVInstrInfoC.td" 206506c3fb27SDimitry Andricinclude "RISCVInstrInfoZc.td" 2066647cbc5dSDimitry Andricinclude "RISCVInstrInfoZcmop.td" 2067647cbc5dSDimitry Andric 2068647cbc5dSDimitry Andric// Integer 2069647cbc5dSDimitry Andricinclude "RISCVInstrInfoZimop.td" 2070647cbc5dSDimitry Andricinclude "RISCVInstrInfoZicbo.td" 2071647cbc5dSDimitry Andricinclude "RISCVInstrInfoZicond.td" 2072647cbc5dSDimitry Andricinclude "RISCVInstrInfoZicfiss.td" 2073bdd1243dSDimitry Andric 2074bdd1243dSDimitry Andric//===----------------------------------------------------------------------===// 2075bdd1243dSDimitry Andric// Vendor extensions 2076bdd1243dSDimitry Andric//===----------------------------------------------------------------------===// 2077bdd1243dSDimitry Andric 2078bdd1243dSDimitry Andricinclude "RISCVInstrInfoXVentana.td" 2079bdd1243dSDimitry Andricinclude "RISCVInstrInfoXTHead.td" 208006c3fb27SDimitry Andricinclude "RISCVInstrInfoXSf.td" 2081*0fca6ea1SDimitry Andricinclude "RISCVInstrInfoSFB.td" 208206c3fb27SDimitry Andricinclude "RISCVInstrInfoXCV.td" 2083*0fca6ea1SDimitry Andricinclude "RISCVInstrInfoXwch.td" 20845f757f3fSDimitry Andric 20855f757f3fSDimitry Andric//===----------------------------------------------------------------------===// 20865f757f3fSDimitry Andric// Global ISel 20875f757f3fSDimitry Andric//===----------------------------------------------------------------------===// 20885f757f3fSDimitry Andric 20895f757f3fSDimitry Andricinclude "RISCVInstrGISel.td" 2090