10b57cec5SDimitry Andric//===-- RISCVInstrInfo.td - Target Description for RISCV ---*- tablegen -*-===// 20b57cec5SDimitry Andric// 30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric// 70b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric// 90b57cec5SDimitry Andric// This file describes the RISC-V instructions in TableGen format. 100b57cec5SDimitry Andric// 110b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric// RISC-V specific DAG Nodes. 150b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric// Target-independent type requirements, but with target-specific formats. 180b57cec5SDimitry Andricdef SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, 190b57cec5SDimitry Andric SDTCisVT<1, i32>]>; 200b57cec5SDimitry Andricdef SDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, 210b57cec5SDimitry Andric SDTCisVT<1, i32>]>; 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric// Target-dependent type requirements. 240b57cec5SDimitry Andricdef SDT_RISCVCall : SDTypeProfile<0, -1, [SDTCisVT<0, XLenVT>]>; 250b57cec5SDimitry Andricdef SDT_RISCVSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>, 26349cc55cSDimitry Andric SDTCisVT<3, OtherVT>, 270b57cec5SDimitry Andric SDTCisSameAs<0, 4>, 280b57cec5SDimitry Andric SDTCisSameAs<4, 5>]>; 29fe6060f1SDimitry Andricdef SDT_RISCVBrCC : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>, 30fe6060f1SDimitry Andric SDTCisVT<2, OtherVT>, 31fe6060f1SDimitry Andric SDTCisVT<3, OtherVT>]>; 32fe6060f1SDimitry Andricdef SDT_RISCVReadCSR : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisInt<1>]>; 33fe6060f1SDimitry Andricdef SDT_RISCVWriteCSR : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisInt<1>]>; 34fe6060f1SDimitry Andricdef SDT_RISCVSwapCSR : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisInt<1>, 35fe6060f1SDimitry Andric SDTCisInt<2>]>; 36e8d8bef9SDimitry Andricdef SDT_RISCVReadCycleWide : SDTypeProfile<2, 0, [SDTCisVT<0, i32>, 37e8d8bef9SDimitry Andric SDTCisVT<1, i32>]>; 38fe6060f1SDimitry Andricdef SDT_RISCVIntUnaryOpW : SDTypeProfile<1, 1, [ 39fe6060f1SDimitry Andric SDTCisSameAs<0, 1>, SDTCisVT<0, i64> 40fe6060f1SDimitry Andric]>; 41fe6060f1SDimitry Andricdef SDT_RISCVIntBinOpW : SDTypeProfile<1, 2, [ 42fe6060f1SDimitry Andric SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64> 43fe6060f1SDimitry Andric]>; 44fe6060f1SDimitry Andricdef SDT_RISCVIntShiftDOpW : SDTypeProfile<1, 3, [ 45fe6060f1SDimitry Andric SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64>, SDTCisVT<3, i64> 46fe6060f1SDimitry Andric]>; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric// Target-independent nodes, but with target-specific formats. 490b57cec5SDimitry Andricdef callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart, 500b57cec5SDimitry Andric [SDNPHasChain, SDNPOutGlue]>; 510b57cec5SDimitry Andricdef callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd, 520b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric// Target-dependent nodes. 550b57cec5SDimitry Andricdef riscv_call : SDNode<"RISCVISD::CALL", SDT_RISCVCall, 560b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 570b57cec5SDimitry Andric SDNPVariadic]>; 580b57cec5SDimitry Andricdef riscv_ret_flag : SDNode<"RISCVISD::RET_FLAG", SDTNone, 590b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; 600b57cec5SDimitry Andricdef riscv_uret_flag : SDNode<"RISCVISD::URET_FLAG", SDTNone, 610b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue]>; 620b57cec5SDimitry Andricdef riscv_sret_flag : SDNode<"RISCVISD::SRET_FLAG", SDTNone, 630b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue]>; 640b57cec5SDimitry Andricdef riscv_mret_flag : SDNode<"RISCVISD::MRET_FLAG", 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]>; 72fe6060f1SDimitry Andricdef riscv_sllw : SDNode<"RISCVISD::SLLW", SDT_RISCVIntBinOpW>; 73fe6060f1SDimitry Andricdef riscv_sraw : SDNode<"RISCVISD::SRAW", SDT_RISCVIntBinOpW>; 74fe6060f1SDimitry Andricdef riscv_srlw : SDNode<"RISCVISD::SRLW", SDT_RISCVIntBinOpW>; 75fe6060f1SDimitry Andricdef riscv_read_csr : SDNode<"RISCVISD::READ_CSR", SDT_RISCVReadCSR, 76fe6060f1SDimitry Andric [SDNPHasChain]>; 77fe6060f1SDimitry Andricdef riscv_write_csr : SDNode<"RISCVISD::WRITE_CSR", SDT_RISCVWriteCSR, 78fe6060f1SDimitry Andric [SDNPHasChain]>; 79fe6060f1SDimitry Andricdef riscv_swap_csr : SDNode<"RISCVISD::SWAP_CSR", SDT_RISCVSwapCSR, 80fe6060f1SDimitry Andric [SDNPHasChain]>; 810b57cec5SDimitry Andric 82e8d8bef9SDimitry Andricdef riscv_read_cycle_wide : SDNode<"RISCVISD::READ_CYCLE_WIDE", 83e8d8bef9SDimitry Andric SDT_RISCVReadCycleWide, 84e8d8bef9SDimitry Andric [SDNPHasChain, SDNPSideEffect]>; 85e8d8bef9SDimitry Andric 860b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 870b57cec5SDimitry Andric// Operand and SDNode transformation definitions. 880b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 890b57cec5SDimitry Andric 900b57cec5SDimitry Andricclass ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass { 910b57cec5SDimitry Andric let Name = prefix # "ImmXLen" # suffix; 920b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 930b57cec5SDimitry Andric let DiagnosticType = !strconcat("Invalid", Name); 940b57cec5SDimitry Andric} 950b57cec5SDimitry Andric 960b57cec5SDimitry Andricclass ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass { 970b57cec5SDimitry Andric let Name = prefix # "Imm" # width # suffix; 980b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 990b57cec5SDimitry Andric let DiagnosticType = !strconcat("Invalid", Name); 1000b57cec5SDimitry Andric} 1010b57cec5SDimitry Andric 1028bcb0991SDimitry Andricdef ImmZeroAsmOperand : AsmOperandClass { 1038bcb0991SDimitry Andric let Name = "ImmZero"; 1048bcb0991SDimitry Andric let RenderMethod = "addImmOperands"; 1058bcb0991SDimitry Andric let DiagnosticType = !strconcat("Invalid", Name); 1068bcb0991SDimitry Andric} 1078bcb0991SDimitry Andric 1080b57cec5SDimitry Andricclass SImmAsmOperand<int width, string suffix = ""> 1090b57cec5SDimitry Andric : ImmAsmOperand<"S", width, suffix> { 1100b57cec5SDimitry Andric} 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andricclass UImmAsmOperand<int width, string suffix = ""> 1130b57cec5SDimitry Andric : ImmAsmOperand<"U", width, suffix> { 1140b57cec5SDimitry Andric} 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andricdef FenceArg : AsmOperandClass { 1170b57cec5SDimitry Andric let Name = "FenceArg"; 1180b57cec5SDimitry Andric let RenderMethod = "addFenceArgOperands"; 1190b57cec5SDimitry Andric let DiagnosticType = "InvalidFenceArg"; 1200b57cec5SDimitry Andric} 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andricdef fencearg : Operand<XLenVT> { 1230b57cec5SDimitry Andric let ParserMatchClass = FenceArg; 1240b57cec5SDimitry Andric let PrintMethod = "printFenceArg"; 1250b57cec5SDimitry Andric let DecoderMethod = "decodeUImmOperand<4>"; 1268bcb0991SDimitry Andric let OperandType = "OPERAND_UIMM4"; 1278bcb0991SDimitry Andric let OperandNamespace = "RISCVOp"; 1280b57cec5SDimitry Andric} 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andricdef UImmLog2XLenAsmOperand : AsmOperandClass { 1310b57cec5SDimitry Andric let Name = "UImmLog2XLen"; 1320b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 1330b57cec5SDimitry Andric let DiagnosticType = "InvalidUImmLog2XLen"; 1340b57cec5SDimitry Andric} 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andricdef uimmlog2xlen : Operand<XLenVT>, ImmLeaf<XLenVT, [{ 1370b57cec5SDimitry Andric if (Subtarget->is64Bit()) 1380b57cec5SDimitry Andric return isUInt<6>(Imm); 1390b57cec5SDimitry Andric return isUInt<5>(Imm); 1400b57cec5SDimitry Andric}]> { 1410b57cec5SDimitry Andric let ParserMatchClass = UImmLog2XLenAsmOperand; 1420b57cec5SDimitry Andric // TODO: should ensure invalid shamt is rejected when decoding. 1430b57cec5SDimitry Andric let DecoderMethod = "decodeUImmOperand<6>"; 1440b57cec5SDimitry Andric let MCOperandPredicate = [{ 1450b57cec5SDimitry Andric int64_t Imm; 1460b57cec5SDimitry Andric if (!MCOp.evaluateAsConstantImm(Imm)) 1470b57cec5SDimitry Andric return false; 1480b57cec5SDimitry Andric if (STI.getTargetTriple().isArch64Bit()) 1490b57cec5SDimitry Andric return isUInt<6>(Imm); 1500b57cec5SDimitry Andric return isUInt<5>(Imm); 1510b57cec5SDimitry Andric }]; 1528bcb0991SDimitry Andric let OperandType = "OPERAND_UIMMLOG2XLEN"; 1538bcb0991SDimitry Andric let OperandNamespace = "RISCVOp"; 1540b57cec5SDimitry Andric} 1550b57cec5SDimitry Andric 156349cc55cSDimitry Andricdef uimm2 : Operand<XLenVT> { 157349cc55cSDimitry Andric let ParserMatchClass = UImmAsmOperand<2>; 158349cc55cSDimitry Andric let DecoderMethod = "decodeUImmOperand<2>"; 159349cc55cSDimitry Andric let OperandType = "OPERAND_UIMM2"; 160349cc55cSDimitry Andric let OperandNamespace = "RISCVOp"; 161349cc55cSDimitry Andric} 162349cc55cSDimitry Andric 163349cc55cSDimitry Andricdef uimm3 : Operand<XLenVT> { 164349cc55cSDimitry Andric let ParserMatchClass = UImmAsmOperand<3>; 165349cc55cSDimitry Andric let DecoderMethod = "decodeUImmOperand<3>"; 166349cc55cSDimitry Andric let OperandType = "OPERAND_UIMM3"; 167349cc55cSDimitry Andric let OperandNamespace = "RISCVOp"; 168349cc55cSDimitry Andric} 169349cc55cSDimitry Andric 1700b57cec5SDimitry Andricdef uimm5 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> { 1710b57cec5SDimitry Andric let ParserMatchClass = UImmAsmOperand<5>; 1720b57cec5SDimitry Andric let DecoderMethod = "decodeUImmOperand<5>"; 1738bcb0991SDimitry Andric let OperandType = "OPERAND_UIMM5"; 1748bcb0991SDimitry Andric let OperandNamespace = "RISCVOp"; 1750b57cec5SDimitry Andric} 1760b57cec5SDimitry Andric 1770eae32dcSDimitry Andricdef InsnDirectiveOpcode : AsmOperandClass { 1780eae32dcSDimitry Andric let Name = "InsnDirectiveOpcode"; 1790eae32dcSDimitry Andric let ParserMethod = "parseInsnDirectiveOpcode"; 1800eae32dcSDimitry Andric let RenderMethod = "addImmOperands"; 1810eae32dcSDimitry Andric let PredicateMethod = "isImm"; 1820eae32dcSDimitry Andric} 1830eae32dcSDimitry Andric 1840eae32dcSDimitry Andricdef uimm7_opcode : Operand<XLenVT> { 1850eae32dcSDimitry Andric let ParserMatchClass = InsnDirectiveOpcode; 1860eae32dcSDimitry Andric let DecoderMethod = "decodeUImmOperand<7>"; 1870eae32dcSDimitry Andric let OperandType = "OPERAND_UIMM7"; 1880eae32dcSDimitry Andric let OperandNamespace = "RISCVOp"; 1890eae32dcSDimitry Andric} 1900eae32dcSDimitry Andric 191349cc55cSDimitry Andricdef uimm7 : Operand<XLenVT> { 192349cc55cSDimitry Andric let ParserMatchClass = UImmAsmOperand<7>; 193349cc55cSDimitry Andric let DecoderMethod = "decodeUImmOperand<7>"; 194349cc55cSDimitry Andric let OperandType = "OPERAND_UIMM7"; 195349cc55cSDimitry Andric let OperandNamespace = "RISCVOp"; 196349cc55cSDimitry Andric} 197349cc55cSDimitry Andric 1980b57cec5SDimitry Andricdef simm12 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isInt<12>(Imm);}]> { 1990b57cec5SDimitry Andric let ParserMatchClass = SImmAsmOperand<12>; 2000b57cec5SDimitry Andric let EncoderMethod = "getImmOpValue"; 2010b57cec5SDimitry Andric let DecoderMethod = "decodeSImmOperand<12>"; 2020b57cec5SDimitry Andric let MCOperandPredicate = [{ 2030b57cec5SDimitry Andric int64_t Imm; 2040b57cec5SDimitry Andric if (MCOp.evaluateAsConstantImm(Imm)) 2050b57cec5SDimitry Andric return isInt<12>(Imm); 2060b57cec5SDimitry Andric return MCOp.isBareSymbolRef(); 2070b57cec5SDimitry Andric }]; 2088bcb0991SDimitry Andric let OperandType = "OPERAND_SIMM12"; 2098bcb0991SDimitry Andric let OperandNamespace = "RISCVOp"; 2100b57cec5SDimitry Andric} 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric// A 13-bit signed immediate where the least significant bit is zero. 2130b57cec5SDimitry Andricdef simm13_lsb0 : Operand<OtherVT> { 2140b57cec5SDimitry Andric let ParserMatchClass = SImmAsmOperand<13, "Lsb0">; 215e8d8bef9SDimitry Andric let PrintMethod = "printBranchOperand"; 2160b57cec5SDimitry Andric let EncoderMethod = "getImmOpValueAsr1"; 2170b57cec5SDimitry Andric let DecoderMethod = "decodeSImmOperandAndLsl1<13>"; 2180b57cec5SDimitry Andric let MCOperandPredicate = [{ 2190b57cec5SDimitry Andric int64_t Imm; 2200b57cec5SDimitry Andric if (MCOp.evaluateAsConstantImm(Imm)) 2210b57cec5SDimitry Andric return isShiftedInt<12, 1>(Imm); 2220b57cec5SDimitry Andric return MCOp.isBareSymbolRef(); 2230b57cec5SDimitry Andric }]; 224e8d8bef9SDimitry Andric let OperandType = "OPERAND_PCREL"; 2250b57cec5SDimitry Andric} 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andricclass UImm20Operand : Operand<XLenVT> { 2280b57cec5SDimitry Andric let EncoderMethod = "getImmOpValue"; 2290b57cec5SDimitry Andric let DecoderMethod = "decodeUImmOperand<20>"; 2300b57cec5SDimitry Andric let MCOperandPredicate = [{ 2310b57cec5SDimitry Andric int64_t Imm; 2320b57cec5SDimitry Andric if (MCOp.evaluateAsConstantImm(Imm)) 2330b57cec5SDimitry Andric return isUInt<20>(Imm); 2340b57cec5SDimitry Andric return MCOp.isBareSymbolRef(); 2350b57cec5SDimitry Andric }]; 2368bcb0991SDimitry Andric let OperandType = "OPERAND_UIMM20"; 2378bcb0991SDimitry Andric let OperandNamespace = "RISCVOp"; 2380b57cec5SDimitry Andric} 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andricdef uimm20_lui : UImm20Operand { 2410b57cec5SDimitry Andric let ParserMatchClass = UImmAsmOperand<20, "LUI">; 2420b57cec5SDimitry Andric} 2430b57cec5SDimitry Andricdef uimm20_auipc : UImm20Operand { 2440b57cec5SDimitry Andric let ParserMatchClass = UImmAsmOperand<20, "AUIPC">; 2450b57cec5SDimitry Andric} 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andricdef Simm21Lsb0JALAsmOperand : SImmAsmOperand<21, "Lsb0JAL"> { 2480b57cec5SDimitry Andric let ParserMethod = "parseJALOffset"; 2490b57cec5SDimitry Andric} 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric// A 21-bit signed immediate where the least significant bit is zero. 2520b57cec5SDimitry Andricdef simm21_lsb0_jal : Operand<OtherVT> { 2530b57cec5SDimitry Andric let ParserMatchClass = Simm21Lsb0JALAsmOperand; 254e8d8bef9SDimitry Andric let PrintMethod = "printBranchOperand"; 2550b57cec5SDimitry Andric let EncoderMethod = "getImmOpValueAsr1"; 2560b57cec5SDimitry Andric let DecoderMethod = "decodeSImmOperandAndLsl1<21>"; 2570b57cec5SDimitry Andric let MCOperandPredicate = [{ 2580b57cec5SDimitry Andric int64_t Imm; 2590b57cec5SDimitry Andric if (MCOp.evaluateAsConstantImm(Imm)) 2600b57cec5SDimitry Andric return isShiftedInt<20, 1>(Imm); 2610b57cec5SDimitry Andric return MCOp.isBareSymbolRef(); 2620b57cec5SDimitry Andric }]; 263e8d8bef9SDimitry Andric let OperandType = "OPERAND_PCREL"; 2640b57cec5SDimitry Andric} 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andricdef BareSymbol : AsmOperandClass { 2670b57cec5SDimitry Andric let Name = "BareSymbol"; 2680b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 2690b57cec5SDimitry Andric let DiagnosticType = "InvalidBareSymbol"; 2700b57cec5SDimitry Andric let ParserMethod = "parseBareSymbol"; 2710b57cec5SDimitry Andric} 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric// A bare symbol. 2740b57cec5SDimitry Andricdef bare_symbol : Operand<XLenVT> { 2750b57cec5SDimitry Andric let ParserMatchClass = BareSymbol; 2760b57cec5SDimitry Andric} 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andricdef CallSymbol : AsmOperandClass { 2790b57cec5SDimitry Andric let Name = "CallSymbol"; 2800b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 2810b57cec5SDimitry Andric let DiagnosticType = "InvalidCallSymbol"; 2820b57cec5SDimitry Andric let ParserMethod = "parseCallSymbol"; 2830b57cec5SDimitry Andric} 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric// A bare symbol used in call/tail only. 2860b57cec5SDimitry Andricdef call_symbol : Operand<XLenVT> { 2870b57cec5SDimitry Andric let ParserMatchClass = CallSymbol; 2880b57cec5SDimitry Andric} 2890b57cec5SDimitry Andric 2905ffd83dbSDimitry Andricdef PseudoJumpSymbol : AsmOperandClass { 2915ffd83dbSDimitry Andric let Name = "PseudoJumpSymbol"; 2925ffd83dbSDimitry Andric let RenderMethod = "addImmOperands"; 2935ffd83dbSDimitry Andric let DiagnosticType = "InvalidPseudoJumpSymbol"; 2945ffd83dbSDimitry Andric let ParserMethod = "parsePseudoJumpSymbol"; 2955ffd83dbSDimitry Andric} 2965ffd83dbSDimitry Andric 2975ffd83dbSDimitry Andric// A bare symbol used for pseudo jumps only. 2985ffd83dbSDimitry Andricdef pseudo_jump_symbol : Operand<XLenVT> { 2995ffd83dbSDimitry Andric let ParserMatchClass = PseudoJumpSymbol; 3005ffd83dbSDimitry Andric} 3015ffd83dbSDimitry Andric 3020b57cec5SDimitry Andricdef TPRelAddSymbol : AsmOperandClass { 3030b57cec5SDimitry Andric let Name = "TPRelAddSymbol"; 3040b57cec5SDimitry Andric let RenderMethod = "addImmOperands"; 3050b57cec5SDimitry Andric let DiagnosticType = "InvalidTPRelAddSymbol"; 3060b57cec5SDimitry Andric let ParserMethod = "parseOperandWithModifier"; 3070b57cec5SDimitry Andric} 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric// A bare symbol with the %tprel_add variant. 3100b57cec5SDimitry Andricdef tprel_add_symbol : Operand<XLenVT> { 3110b57cec5SDimitry Andric let ParserMatchClass = TPRelAddSymbol; 3120b57cec5SDimitry Andric} 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andricdef CSRSystemRegister : AsmOperandClass { 3150b57cec5SDimitry Andric let Name = "CSRSystemRegister"; 3160b57cec5SDimitry Andric let ParserMethod = "parseCSRSystemRegister"; 3170b57cec5SDimitry Andric let DiagnosticType = "InvalidCSRSystemRegister"; 3180b57cec5SDimitry Andric} 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andricdef csr_sysreg : Operand<XLenVT> { 3210b57cec5SDimitry Andric let ParserMatchClass = CSRSystemRegister; 3220b57cec5SDimitry Andric let PrintMethod = "printCSRSystemRegister"; 3230b57cec5SDimitry Andric let DecoderMethod = "decodeUImmOperand<12>"; 3248bcb0991SDimitry Andric let OperandType = "OPERAND_UIMM12"; 3258bcb0991SDimitry Andric let OperandNamespace = "RISCVOp"; 3260b57cec5SDimitry Andric} 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric// A parameterized register class alternative to i32imm/i64imm from Target.td. 3290b57cec5SDimitry Andricdef ixlenimm : Operand<XLenVT>; 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andricdef ixlenimm_li : Operand<XLenVT> { 3320b57cec5SDimitry Andric let ParserMatchClass = ImmXLenAsmOperand<"", "LI">; 3330b57cec5SDimitry Andric} 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric// Standalone (codegen-only) immleaf patterns. 336fe6060f1SDimitry Andric 337fe6060f1SDimitry Andric// A 12-bit signed immediate plus one where the imm range will be -2047~2048. 338fe6060f1SDimitry Andricdef simm12_plus1 : ImmLeaf<XLenVT, 339fe6060f1SDimitry Andric [{return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048;}]>; 3400b57cec5SDimitry Andric 341e8d8bef9SDimitry Andric// A 6-bit constant greater than 32. 342e8d8bef9SDimitry Andricdef uimm6gt32 : ImmLeaf<XLenVT, [{ 343e8d8bef9SDimitry Andric return isUInt<6>(Imm) && Imm > 32; 344e8d8bef9SDimitry Andric}]>; 345e8d8bef9SDimitry Andric 3460b57cec5SDimitry Andric// Addressing modes. 3470b57cec5SDimitry Andric// Necessary because a frameindex can't be matched directly in a pattern. 3480b57cec5SDimitry Andricdef AddrFI : ComplexPattern<iPTR, 1, "SelectAddrFI", [frameindex], []>; 349fe6060f1SDimitry Andricdef BaseAddr : ComplexPattern<iPTR, 1, "SelectBaseAddr">; 3500b57cec5SDimitry Andric 3515ffd83dbSDimitry Andric// Return the negation of an immediate value. 3525ffd83dbSDimitry Andricdef NegImm : SDNodeXForm<imm, [{ 3535ffd83dbSDimitry Andric return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N), 3545ffd83dbSDimitry Andric N->getValueType(0)); 3555ffd83dbSDimitry Andric}]>; 3565ffd83dbSDimitry Andric 357e8d8bef9SDimitry Andric// Return an immediate value minus 32. 358e8d8bef9SDimitry Andricdef ImmSub32 : SDNodeXForm<imm, [{ 359e8d8bef9SDimitry Andric return CurDAG->getTargetConstant(N->getSExtValue() - 32, SDLoc(N), 360e8d8bef9SDimitry Andric N->getValueType(0)); 361e8d8bef9SDimitry Andric}]>; 362e8d8bef9SDimitry Andric 363fe6060f1SDimitry Andric// Return an immediate value plus 32. 364fe6060f1SDimitry Andricdef ImmPlus32 : SDNodeXForm<imm, [{ 365fe6060f1SDimitry Andric return CurDAG->getTargetConstant(N->getSExtValue() + 32, SDLoc(N), 366fe6060f1SDimitry Andric N->getValueType(0)); 367fe6060f1SDimitry Andric}]>; 368fe6060f1SDimitry Andric 369e8d8bef9SDimitry Andric// Return an immediate subtracted from XLen. 370e8d8bef9SDimitry Andricdef ImmSubFromXLen : SDNodeXForm<imm, [{ 371e8d8bef9SDimitry Andric uint64_t XLen = Subtarget->getXLen(); 372e8d8bef9SDimitry Andric return CurDAG->getTargetConstant(XLen - N->getZExtValue(), SDLoc(N), 373e8d8bef9SDimitry Andric N->getValueType(0)); 374e8d8bef9SDimitry Andric}]>; 375e8d8bef9SDimitry Andric 376e8d8bef9SDimitry Andric// Return an immediate subtracted from 32. 377e8d8bef9SDimitry Andricdef ImmSubFrom32 : SDNodeXForm<imm, [{ 378e8d8bef9SDimitry Andric return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N), 379e8d8bef9SDimitry Andric N->getValueType(0)); 380e8d8bef9SDimitry Andric}]>; 381e8d8bef9SDimitry Andric 382fe6060f1SDimitry Andric// Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1), 383fe6060f1SDimitry Andric// in which imm = imm0 + imm1 and both imm0 and imm1 are simm12. 384fe6060f1SDimitry Andricdef AddiPair : PatLeaf<(imm), [{ 385fe6060f1SDimitry Andric if (!N->hasOneUse()) 386fe6060f1SDimitry Andric return false; 387fe6060f1SDimitry Andric // The immediate operand must be in range [-4096,-2049] or [2048,4094]. 388fe6060f1SDimitry Andric int64_t Imm = N->getSExtValue(); 389fe6060f1SDimitry Andric return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094); 390fe6060f1SDimitry Andric}]>; 391fe6060f1SDimitry Andric 392fe6060f1SDimitry Andric// Return imm/2. 393fe6060f1SDimitry Andricdef AddiPairImmA : SDNodeXForm<imm, [{ 394fe6060f1SDimitry Andric return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N), 395fe6060f1SDimitry Andric N->getValueType(0)); 396fe6060f1SDimitry Andric}]>; 397fe6060f1SDimitry Andric 398fe6060f1SDimitry Andric// Return imm - imm/2. 399fe6060f1SDimitry Andricdef AddiPairImmB : SDNodeXForm<imm, [{ 400fe6060f1SDimitry Andric int64_t Imm = N->getSExtValue(); 401fe6060f1SDimitry Andric return CurDAG->getTargetConstant(Imm - Imm / 2, SDLoc(N), 402fe6060f1SDimitry Andric N->getValueType(0)); 403fe6060f1SDimitry Andric}]>; 404fe6060f1SDimitry Andric 40504eeddc0SDimitry Andricdef XLenSubTrailingOnes : SDNodeXForm<imm, [{ 40604eeddc0SDimitry Andric uint64_t XLen = Subtarget->getXLen(); 40704eeddc0SDimitry Andric uint64_t TrailingOnes = N->getAPIntValue().countTrailingOnes(); 40804eeddc0SDimitry Andric return CurDAG->getTargetConstant(XLen - TrailingOnes, SDLoc(N), 40904eeddc0SDimitry Andric N->getValueType(0)); 41004eeddc0SDimitry Andric}]>; 41104eeddc0SDimitry Andric 41204eeddc0SDimitry Andric// Checks if this mask is a non-empty sequence of ones starting at the 41304eeddc0SDimitry Andric// least significant bit with the remainder zero and exceeds simm12. 41404eeddc0SDimitry Andricdef TrailingOnesMask : PatLeaf<(imm), [{ 41504eeddc0SDimitry Andric if (!N->hasOneUse()) 41604eeddc0SDimitry Andric return false; 41704eeddc0SDimitry Andric return !isInt<12>(N->getSExtValue()) && isMask_64(N->getZExtValue()); 41804eeddc0SDimitry Andric}], XLenSubTrailingOnes>; 41904eeddc0SDimitry Andric 4200b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 4210b57cec5SDimitry Andric// Instruction Formats 4220b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andricinclude "RISCVInstrFormats.td" 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 4270b57cec5SDimitry Andric// Instruction Class Templates 4280b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 4310b57cec5SDimitry Andricclass BranchCC_rri<bits<3> funct3, string opcodestr> 4320b57cec5SDimitry Andric : RVInstB<funct3, OPC_BRANCH, (outs), 4330b57cec5SDimitry Andric (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12), 43413138422SDimitry Andric opcodestr, "$rs1, $rs2, $imm12">, 4355ffd83dbSDimitry Andric Sched<[WriteJmp, ReadJmp, ReadJmp]> { 4360b57cec5SDimitry Andric let isBranch = 1; 4370b57cec5SDimitry Andric let isTerminator = 1; 4380b57cec5SDimitry Andric} 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0 in 4410b57cec5SDimitry Andricclass Load_ri<bits<3> funct3, string opcodestr> 4420b57cec5SDimitry Andric : RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), 4430b57cec5SDimitry Andric opcodestr, "$rd, ${imm12}(${rs1})">; 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric// Operands for stores are in the order srcreg, base, offset rather than 4460b57cec5SDimitry Andric// reflecting the order these fields are specified in the instruction 4470b57cec5SDimitry Andric// encoding. 4480b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 1 in 4490b57cec5SDimitry Andricclass Store_rri<bits<3> funct3, string opcodestr> 4500b57cec5SDimitry Andric : RVInstS<funct3, OPC_STORE, (outs), 4510b57cec5SDimitry Andric (ins GPR:$rs2, GPR:$rs1, simm12:$imm12), 4520b57cec5SDimitry Andric opcodestr, "$rs2, ${imm12}(${rs1})">; 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 4550b57cec5SDimitry Andricclass ALU_ri<bits<3> funct3, string opcodestr> 4560b57cec5SDimitry Andric : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), 45713138422SDimitry Andric opcodestr, "$rd, $rs1, $imm12">, 45813138422SDimitry Andric Sched<[WriteIALU, ReadIALU]>; 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 461fe6060f1SDimitry Andricclass Shift_ri<bits<5> imm11_7, bits<3> funct3, string opcodestr> 462fe6060f1SDimitry Andric : RVInstIShift<imm11_7, funct3, OPC_OP_IMM, (outs GPR:$rd), 4630b57cec5SDimitry Andric (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr, 46413138422SDimitry Andric "$rd, $rs1, $shamt">, 465fe6060f1SDimitry Andric Sched<[WriteShiftImm, ReadShiftImm]>; 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 4680b57cec5SDimitry Andricclass ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr> 4690b57cec5SDimitry Andric : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), 4700b57cec5SDimitry Andric opcodestr, "$rd, $rs1, $rs2">; 4710b57cec5SDimitry Andric 472e8d8bef9SDimitry Andriclet hasNoSchedulingInfo = 1, 473e8d8bef9SDimitry Andric hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 4740b57cec5SDimitry Andricclass CSR_ir<bits<3> funct3, string opcodestr> 4750b57cec5SDimitry Andric : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins csr_sysreg:$imm12, GPR:$rs1), 47613138422SDimitry Andric opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR, ReadCSR]>; 4770b57cec5SDimitry Andric 478e8d8bef9SDimitry Andriclet hasNoSchedulingInfo = 1, 479e8d8bef9SDimitry Andric hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 4800b57cec5SDimitry Andricclass CSR_ii<bits<3> funct3, string opcodestr> 4810b57cec5SDimitry Andric : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), 4820b57cec5SDimitry Andric (ins csr_sysreg:$imm12, uimm5:$rs1), 48313138422SDimitry Andric opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR]>; 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 486fe6060f1SDimitry Andricclass ShiftW_ri<bits<7> imm11_5, bits<3> funct3, string opcodestr> 487fe6060f1SDimitry Andric : RVInstIShiftW<imm11_5, funct3, OPC_OP_IMM_32, (outs GPR:$rd), 4880b57cec5SDimitry Andric (ins GPR:$rs1, uimm5:$shamt), opcodestr, 48913138422SDimitry Andric "$rd, $rs1, $shamt">, 490fe6060f1SDimitry Andric Sched<[WriteShiftImm32, ReadShiftImm32]>; 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 4930b57cec5SDimitry Andricclass ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr> 4940b57cec5SDimitry Andric : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd), 4950b57cec5SDimitry Andric (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2">; 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andriclet hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 4980b57cec5SDimitry Andricclass Priv<string opcodestr, bits<7> funct7> 4990b57cec5SDimitry Andric : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2), 5000b57cec5SDimitry Andric opcodestr, "">; 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 5030b57cec5SDimitry Andric// Instructions 5040b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { 5070b57cec5SDimitry Andriclet isReMaterializable = 1, isAsCheapAsAMove = 1 in 5080b57cec5SDimitry Andricdef LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20_lui:$imm20), 50913138422SDimitry Andric "lui", "$rd, $imm20">, Sched<[WriteIALU]>; 5100b57cec5SDimitry Andric 5110b57cec5SDimitry Andricdef AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20_auipc:$imm20), 51213138422SDimitry Andric "auipc", "$rd, $imm20">, Sched<[WriteIALU]>; 5130b57cec5SDimitry Andric 5140b57cec5SDimitry Andriclet isCall = 1 in 5150b57cec5SDimitry Andricdef JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20), 51613138422SDimitry Andric "jal", "$rd, $imm20">, Sched<[WriteJal]>; 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andriclet isCall = 1 in 5190b57cec5SDimitry Andricdef JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd), 5200b57cec5SDimitry Andric (ins GPR:$rs1, simm12:$imm12), 52113138422SDimitry Andric "jalr", "$rd, ${imm12}(${rs1})">, 52213138422SDimitry Andric Sched<[WriteJalr, ReadJalr]>; 5230b57cec5SDimitry Andric} // hasSideEffects = 0, mayLoad = 0, mayStore = 0 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andricdef BEQ : BranchCC_rri<0b000, "beq">; 5260b57cec5SDimitry Andricdef BNE : BranchCC_rri<0b001, "bne">; 5270b57cec5SDimitry Andricdef BLT : BranchCC_rri<0b100, "blt">; 5280b57cec5SDimitry Andricdef BGE : BranchCC_rri<0b101, "bge">; 5290b57cec5SDimitry Andricdef BLTU : BranchCC_rri<0b110, "bltu">; 5300b57cec5SDimitry Andricdef BGEU : BranchCC_rri<0b111, "bgeu">; 5310b57cec5SDimitry Andric 53213138422SDimitry Andricdef LB : Load_ri<0b000, "lb">, Sched<[WriteLDB, ReadMemBase]>; 53313138422SDimitry Andricdef LH : Load_ri<0b001, "lh">, Sched<[WriteLDH, ReadMemBase]>; 53413138422SDimitry Andricdef LW : Load_ri<0b010, "lw">, Sched<[WriteLDW, ReadMemBase]>; 53513138422SDimitry Andricdef LBU : Load_ri<0b100, "lbu">, Sched<[WriteLDB, ReadMemBase]>; 53613138422SDimitry Andricdef LHU : Load_ri<0b101, "lhu">, Sched<[WriteLDH, ReadMemBase]>; 5370b57cec5SDimitry Andric 53813138422SDimitry Andricdef SB : Store_rri<0b000, "sb">, Sched<[WriteSTB, ReadStoreData, ReadMemBase]>; 53913138422SDimitry Andricdef SH : Store_rri<0b001, "sh">, Sched<[WriteSTH, ReadStoreData, ReadMemBase]>; 54013138422SDimitry Andricdef SW : Store_rri<0b010, "sw">, Sched<[WriteSTW, ReadStoreData, ReadMemBase]>; 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric// ADDI isn't always rematerializable, but isReMaterializable will be used as 5430b57cec5SDimitry Andric// a hint which is verified in isReallyTriviallyReMaterializable. 5440b57cec5SDimitry Andriclet isReMaterializable = 1, isAsCheapAsAMove = 1 in 5450b57cec5SDimitry Andricdef ADDI : ALU_ri<0b000, "addi">; 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andricdef SLTI : ALU_ri<0b010, "slti">; 5480b57cec5SDimitry Andricdef SLTIU : ALU_ri<0b011, "sltiu">; 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andriclet isReMaterializable = 1, isAsCheapAsAMove = 1 in { 5510b57cec5SDimitry Andricdef XORI : ALU_ri<0b100, "xori">; 5520b57cec5SDimitry Andricdef ORI : ALU_ri<0b110, "ori">; 5530b57cec5SDimitry Andric} 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andricdef ANDI : ALU_ri<0b111, "andi">; 5560b57cec5SDimitry Andric 557fe6060f1SDimitry Andricdef SLLI : Shift_ri<0b00000, 0b001, "slli">; 558fe6060f1SDimitry Andricdef SRLI : Shift_ri<0b00000, 0b101, "srli">; 559fe6060f1SDimitry Andricdef SRAI : Shift_ri<0b01000, 0b101, "srai">; 5600b57cec5SDimitry Andric 56113138422SDimitry Andricdef ADD : ALU_rr<0b0000000, 0b000, "add">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 56213138422SDimitry Andricdef SUB : ALU_rr<0b0100000, 0b000, "sub">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 563fe6060f1SDimitry Andricdef SLL : ALU_rr<0b0000000, 0b001, "sll">, Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 56413138422SDimitry Andricdef SLT : ALU_rr<0b0000000, 0b010, "slt">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 56513138422SDimitry Andricdef SLTU : ALU_rr<0b0000000, 0b011, "sltu">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 56613138422SDimitry Andricdef XOR : ALU_rr<0b0000000, 0b100, "xor">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 567fe6060f1SDimitry Andricdef SRL : ALU_rr<0b0000000, 0b101, "srl">, Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 568fe6060f1SDimitry Andricdef SRA : ALU_rr<0b0100000, 0b101, "sra">, Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 56913138422SDimitry Andricdef OR : ALU_rr<0b0000000, 0b110, "or">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 57013138422SDimitry Andricdef AND : ALU_rr<0b0000000, 0b111, "and">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andriclet hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { 5730b57cec5SDimitry Andricdef FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs), 5740b57cec5SDimitry Andric (ins fencearg:$pred, fencearg:$succ), 57513138422SDimitry Andric "fence", "$pred, $succ">, Sched<[]> { 5760b57cec5SDimitry Andric bits<4> pred; 5770b57cec5SDimitry Andric bits<4> succ; 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric let rs1 = 0; 5800b57cec5SDimitry Andric let rd = 0; 5810b57cec5SDimitry Andric let imm12 = {0b0000,pred,succ}; 5820b57cec5SDimitry Andric} 5830b57cec5SDimitry Andric 58413138422SDimitry Andricdef FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", "">, Sched<[]> { 5850b57cec5SDimitry Andric let rs1 = 0; 5860b57cec5SDimitry Andric let rd = 0; 5870b57cec5SDimitry Andric let imm12 = {0b1000,0b0011,0b0011}; 5880b57cec5SDimitry Andric} 5890b57cec5SDimitry Andric 59013138422SDimitry Andricdef FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", "">, Sched<[]> { 5910b57cec5SDimitry Andric let rs1 = 0; 5920b57cec5SDimitry Andric let rd = 0; 5930b57cec5SDimitry Andric let imm12 = 0; 5940b57cec5SDimitry Andric} 5950b57cec5SDimitry Andric 59613138422SDimitry Andricdef ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", "">, Sched<[WriteJmp]> { 5970b57cec5SDimitry Andric let rs1 = 0; 5980b57cec5SDimitry Andric let rd = 0; 5990b57cec5SDimitry Andric let imm12 = 0; 6000b57cec5SDimitry Andric} 6010b57cec5SDimitry Andric 60213138422SDimitry Andricdef EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", "">, 60313138422SDimitry Andric Sched<[]> { 6040b57cec5SDimitry Andric let rs1 = 0; 6050b57cec5SDimitry Andric let rd = 0; 6060b57cec5SDimitry Andric let imm12 = 1; 6070b57cec5SDimitry Andric} 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric// This is a de facto standard (as set by GNU binutils) 32-bit unimplemented 6100b57cec5SDimitry Andric// instruction (i.e., it should always trap, if your implementation has invalid 6110b57cec5SDimitry Andric// instruction traps). 61213138422SDimitry Andricdef UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", "">, 61313138422SDimitry Andric Sched<[]> { 6140b57cec5SDimitry Andric let rs1 = 0; 6150b57cec5SDimitry Andric let rd = 0; 6160b57cec5SDimitry Andric let imm12 = 0b110000000000; 6170b57cec5SDimitry Andric} 6180b57cec5SDimitry Andric} // hasSideEffects = 1, mayLoad = 0, mayStore = 0 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andricdef CSRRW : CSR_ir<0b001, "csrrw">; 6210b57cec5SDimitry Andricdef CSRRS : CSR_ir<0b010, "csrrs">; 6220b57cec5SDimitry Andricdef CSRRC : CSR_ir<0b011, "csrrc">; 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andricdef CSRRWI : CSR_ii<0b101, "csrrwi">; 6250b57cec5SDimitry Andricdef CSRRSI : CSR_ii<0b110, "csrrsi">; 6260b57cec5SDimitry Andricdef CSRRCI : CSR_ii<0b111, "csrrci">; 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric/// RV64I instructions 6290b57cec5SDimitry Andric 6300b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 63113138422SDimitry Andricdef LWU : Load_ri<0b110, "lwu">, Sched<[WriteLDWU, ReadMemBase]>; 63213138422SDimitry Andricdef LD : Load_ri<0b011, "ld">, Sched<[WriteLDD, ReadMemBase]>; 63313138422SDimitry Andricdef SD : Store_rri<0b011, "sd">, Sched<[WriteSTD, ReadStoreData, ReadMemBase]>; 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 6360b57cec5SDimitry Andricdef ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd), 6370b57cec5SDimitry Andric (ins GPR:$rs1, simm12:$imm12), 63813138422SDimitry Andric "addiw", "$rd, $rs1, $imm12">, 63913138422SDimitry Andric Sched<[WriteIALU32, ReadIALU32]>; 6400b57cec5SDimitry Andric 641fe6060f1SDimitry Andricdef SLLIW : ShiftW_ri<0b0000000, 0b001, "slliw">; 642fe6060f1SDimitry Andricdef SRLIW : ShiftW_ri<0b0000000, 0b101, "srliw">; 643fe6060f1SDimitry Andricdef SRAIW : ShiftW_ri<0b0100000, 0b101, "sraiw">; 6440b57cec5SDimitry Andric 64513138422SDimitry Andricdef ADDW : ALUW_rr<0b0000000, 0b000, "addw">, 64613138422SDimitry Andric Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 64713138422SDimitry Andricdef SUBW : ALUW_rr<0b0100000, 0b000, "subw">, 64813138422SDimitry Andric Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 64913138422SDimitry Andricdef SLLW : ALUW_rr<0b0000000, 0b001, "sllw">, 650fe6060f1SDimitry Andric Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 65113138422SDimitry Andricdef SRLW : ALUW_rr<0b0000000, 0b101, "srlw">, 652fe6060f1SDimitry Andric Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 65313138422SDimitry Andricdef SRAW : ALUW_rr<0b0100000, 0b101, "sraw">, 654fe6060f1SDimitry Andric Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 6550b57cec5SDimitry Andric} // Predicates = [IsRV64] 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 6580b57cec5SDimitry Andric// Privileged instructions 6590b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andriclet isBarrier = 1, isReturn = 1, isTerminator = 1 in { 66213138422SDimitry Andricdef URET : Priv<"uret", 0b0000000>, Sched<[]> { 6630b57cec5SDimitry Andric let rd = 0; 6640b57cec5SDimitry Andric let rs1 = 0; 6650b57cec5SDimitry Andric let rs2 = 0b00010; 6660b57cec5SDimitry Andric} 6670b57cec5SDimitry Andric 66813138422SDimitry Andricdef SRET : Priv<"sret", 0b0001000>, Sched<[]> { 6690b57cec5SDimitry Andric let rd = 0; 6700b57cec5SDimitry Andric let rs1 = 0; 6710b57cec5SDimitry Andric let rs2 = 0b00010; 6720b57cec5SDimitry Andric} 6730b57cec5SDimitry Andric 67413138422SDimitry Andricdef MRET : Priv<"mret", 0b0011000>, Sched<[]> { 6750b57cec5SDimitry Andric let rd = 0; 6760b57cec5SDimitry Andric let rs1 = 0; 6770b57cec5SDimitry Andric let rs2 = 0b00010; 6780b57cec5SDimitry Andric} 6790b57cec5SDimitry Andric} // isBarrier = 1, isReturn = 1, isTerminator = 1 6800b57cec5SDimitry Andric 68113138422SDimitry Andricdef WFI : Priv<"wfi", 0b0001000>, Sched<[]> { 6820b57cec5SDimitry Andric let rd = 0; 6830b57cec5SDimitry Andric let rs1 = 0; 6840b57cec5SDimitry Andric let rs2 = 0b00101; 6850b57cec5SDimitry Andric} 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andriclet hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 6880b57cec5SDimitry Andricdef SFENCE_VMA : RVInstR<0b0001001, 0b000, OPC_SYSTEM, (outs), 6890b57cec5SDimitry Andric (ins GPR:$rs1, GPR:$rs2), 69013138422SDimitry Andric "sfence.vma", "$rs1, $rs2">, Sched<[]> { 6910b57cec5SDimitry Andric let rd = 0; 6920b57cec5SDimitry Andric} 6930b57cec5SDimitry Andric 6940b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 6955ffd83dbSDimitry Andric// Debug instructions 6965ffd83dbSDimitry Andric//===----------------------------------------------------------------------===// 6975ffd83dbSDimitry Andric 6985ffd83dbSDimitry Andriclet isBarrier = 1, isReturn = 1, isTerminator = 1 in { 6995ffd83dbSDimitry Andricdef DRET : Priv<"dret", 0b0111101>, Sched<[]> { 7005ffd83dbSDimitry Andric let rd = 0; 7015ffd83dbSDimitry Andric let rs1 = 0; 7025ffd83dbSDimitry Andric let rs2 = 0b10010; 7035ffd83dbSDimitry Andric} 7045ffd83dbSDimitry Andric} // isBarrier = 1, isReturn = 1, isTerminator = 1 7055ffd83dbSDimitry Andric 7065ffd83dbSDimitry Andric//===----------------------------------------------------------------------===// 7070b57cec5SDimitry Andric// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) 7080b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 7090b57cec5SDimitry Andric 7100b57cec5SDimitry Andricdef : InstAlias<"nop", (ADDI X0, X0, 0)>; 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric// Note that the size is 32 because up to 8 32-bit instructions are needed to 7130b57cec5SDimitry Andric// generate an arbitrary 64-bit immediate. However, the size does not really 7140b57cec5SDimitry Andric// matter since PseudoLI is currently only used in the AsmParser where it gets 7150b57cec5SDimitry Andric// expanded to real instructions immediately. 7160b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32, 7170b57cec5SDimitry Andric isCodeGenOnly = 0, isAsmParserOnly = 1 in 7180b57cec5SDimitry Andricdef PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [], 7190b57cec5SDimitry Andric "li", "$rd, $imm">; 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andricdef PseudoLB : PseudoLoad<"lb">; 7220b57cec5SDimitry Andricdef PseudoLBU : PseudoLoad<"lbu">; 7230b57cec5SDimitry Andricdef PseudoLH : PseudoLoad<"lh">; 7240b57cec5SDimitry Andricdef PseudoLHU : PseudoLoad<"lhu">; 7250b57cec5SDimitry Andricdef PseudoLW : PseudoLoad<"lw">; 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andricdef PseudoSB : PseudoStore<"sb">; 7280b57cec5SDimitry Andricdef PseudoSH : PseudoStore<"sh">; 7290b57cec5SDimitry Andricdef PseudoSW : PseudoStore<"sw">; 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 7320b57cec5SDimitry Andricdef PseudoLWU : PseudoLoad<"lwu">; 7330b57cec5SDimitry Andricdef PseudoLD : PseudoLoad<"ld">; 7340b57cec5SDimitry Andricdef PseudoSD : PseudoStore<"sd">; 7350b57cec5SDimitry Andric} // Predicates = [IsRV64] 7360b57cec5SDimitry Andric 7374824e7fdSDimitry Andricdef : InstAlias<"li $rd, $imm", (ADDI GPR:$rd, X0, simm12:$imm)>; 7380b57cec5SDimitry Andricdef : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>; 7390b57cec5SDimitry Andricdef : InstAlias<"not $rd, $rs", (XORI GPR:$rd, GPR:$rs, -1)>; 7400b57cec5SDimitry Andricdef : InstAlias<"neg $rd, $rs", (SUB GPR:$rd, X0, GPR:$rs)>; 7410b57cec5SDimitry Andric 7420b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 7430b57cec5SDimitry Andricdef : InstAlias<"negw $rd, $rs", (SUBW GPR:$rd, X0, GPR:$rs)>; 7440b57cec5SDimitry Andricdef : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs, 0)>; 7450b57cec5SDimitry Andric} // Predicates = [IsRV64] 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andricdef : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs, 1)>; 7480b57cec5SDimitry Andricdef : InstAlias<"snez $rd, $rs", (SLTU GPR:$rd, X0, GPR:$rs)>; 7490b57cec5SDimitry Andricdef : InstAlias<"sltz $rd, $rs", (SLT GPR:$rd, GPR:$rs, X0)>; 7500b57cec5SDimitry Andricdef : InstAlias<"sgtz $rd, $rs", (SLT GPR:$rd, X0, GPR:$rs)>; 7510b57cec5SDimitry Andric 7520b57cec5SDimitry Andric// sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu 7530b57cec5SDimitry Andric// form will always be printed. Therefore, set a zero weight. 7540b57cec5SDimitry Andricdef : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>; 7550b57cec5SDimitry Andricdef : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>; 7560b57cec5SDimitry Andric 7570b57cec5SDimitry Andricdef : InstAlias<"beqz $rs, $offset", 7580b57cec5SDimitry Andric (BEQ GPR:$rs, X0, simm13_lsb0:$offset)>; 7590b57cec5SDimitry Andricdef : InstAlias<"bnez $rs, $offset", 7600b57cec5SDimitry Andric (BNE GPR:$rs, X0, simm13_lsb0:$offset)>; 7610b57cec5SDimitry Andricdef : InstAlias<"blez $rs, $offset", 7620b57cec5SDimitry Andric (BGE X0, GPR:$rs, simm13_lsb0:$offset)>; 7630b57cec5SDimitry Andricdef : InstAlias<"bgez $rs, $offset", 7640b57cec5SDimitry Andric (BGE GPR:$rs, X0, simm13_lsb0:$offset)>; 7650b57cec5SDimitry Andricdef : InstAlias<"bltz $rs, $offset", 7660b57cec5SDimitry Andric (BLT GPR:$rs, X0, simm13_lsb0:$offset)>; 7670b57cec5SDimitry Andricdef : InstAlias<"bgtz $rs, $offset", 7680b57cec5SDimitry Andric (BLT X0, GPR:$rs, simm13_lsb0:$offset)>; 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric// Always output the canonical mnemonic for the pseudo branch instructions. 7710b57cec5SDimitry Andric// The GNU tools emit the canonical mnemonic for the branch pseudo instructions 7720b57cec5SDimitry Andric// as well (e.g. "bgt" will be recognised by the assembler but never printed by 7730b57cec5SDimitry Andric// objdump). Match this behaviour by setting a zero weight. 7740b57cec5SDimitry Andricdef : InstAlias<"bgt $rs, $rt, $offset", 7750b57cec5SDimitry Andric (BLT GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 7760b57cec5SDimitry Andricdef : InstAlias<"ble $rs, $rt, $offset", 7770b57cec5SDimitry Andric (BGE GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 7780b57cec5SDimitry Andricdef : InstAlias<"bgtu $rs, $rt, $offset", 7790b57cec5SDimitry Andric (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 7800b57cec5SDimitry Andricdef : InstAlias<"bleu $rs, $rt, $offset", 7810b57cec5SDimitry Andric (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 7820b57cec5SDimitry Andric 7830b57cec5SDimitry Andricdef : InstAlias<"j $offset", (JAL X0, simm21_lsb0_jal:$offset)>; 7840b57cec5SDimitry Andricdef : InstAlias<"jal $offset", (JAL X1, simm21_lsb0_jal:$offset)>; 7850b57cec5SDimitry Andric 7860b57cec5SDimitry Andric// Non-zero offset aliases of "jalr" are the lowest weight, followed by the 7870b57cec5SDimitry Andric// two-register form, then the one-register forms and finally "ret". 7880b57cec5SDimitry Andricdef : InstAlias<"jr $rs", (JALR X0, GPR:$rs, 0), 3>; 7890b57cec5SDimitry Andricdef : InstAlias<"jr ${offset}(${rs})", (JALR X0, GPR:$rs, simm12:$offset)>; 7900b57cec5SDimitry Andricdef : InstAlias<"jalr $rs", (JALR X1, GPR:$rs, 0), 3>; 7910b57cec5SDimitry Andricdef : InstAlias<"jalr ${offset}(${rs})", (JALR X1, GPR:$rs, simm12:$offset)>; 7920b57cec5SDimitry Andricdef : InstAlias<"jalr $rd, $rs", (JALR GPR:$rd, GPR:$rs, 0), 2>; 7930b57cec5SDimitry Andricdef : InstAlias<"ret", (JALR X0, X1, 0), 4>; 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric// Non-canonical forms for jump targets also accepted by the assembler. 7960b57cec5SDimitry Andricdef : InstAlias<"jr $rs, $offset", (JALR X0, GPR:$rs, simm12:$offset), 0>; 7970b57cec5SDimitry Andricdef : InstAlias<"jalr $rs, $offset", (JALR X1, GPR:$rs, simm12:$offset), 0>; 7980b57cec5SDimitry Andricdef : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12:$offset), 0>; 7990b57cec5SDimitry Andric 8000b57cec5SDimitry Andricdef : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw 8010b57cec5SDimitry Andric 8020b57cec5SDimitry Andricdef : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>; 8030b57cec5SDimitry Andricdef : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, CYCLE.Encoding, X0)>; 8040b57cec5SDimitry Andricdef : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, TIME.Encoding, X0)>; 8050b57cec5SDimitry Andric 8060b57cec5SDimitry Andriclet Predicates = [IsRV32] in { 8070b57cec5SDimitry Andricdef : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, INSTRETH.Encoding, X0)>; 8080b57cec5SDimitry Andricdef : InstAlias<"rdcycleh $rd", (CSRRS GPR:$rd, CYCLEH.Encoding, X0)>; 8090b57cec5SDimitry Andricdef : InstAlias<"rdtimeh $rd", (CSRRS GPR:$rd, TIMEH.Encoding, X0)>; 8100b57cec5SDimitry Andric} // Predicates = [IsRV32] 8110b57cec5SDimitry Andric 8120b57cec5SDimitry Andricdef : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, csr_sysreg:$csr, X0)>; 8130b57cec5SDimitry Andricdef : InstAlias<"csrw $csr, $rs", (CSRRW X0, csr_sysreg:$csr, GPR:$rs)>; 8140b57cec5SDimitry Andricdef : InstAlias<"csrs $csr, $rs", (CSRRS X0, csr_sysreg:$csr, GPR:$rs)>; 8150b57cec5SDimitry Andricdef : InstAlias<"csrc $csr, $rs", (CSRRC X0, csr_sysreg:$csr, GPR:$rs)>; 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andricdef : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>; 8180b57cec5SDimitry Andricdef : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>; 8190b57cec5SDimitry Andricdef : InstAlias<"csrci $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>; 8200b57cec5SDimitry Andric 8210b57cec5SDimitry Andriclet EmitPriority = 0 in { 8220b57cec5SDimitry Andricdef : InstAlias<"csrw $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>; 8230b57cec5SDimitry Andricdef : InstAlias<"csrs $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>; 8240b57cec5SDimitry Andricdef : InstAlias<"csrc $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>; 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andricdef : InstAlias<"csrrw $rd, $csr, $imm", (CSRRWI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 8270b57cec5SDimitry Andricdef : InstAlias<"csrrs $rd, $csr, $imm", (CSRRSI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 8280b57cec5SDimitry Andricdef : InstAlias<"csrrc $rd, $csr, $imm", (CSRRCI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 8290b57cec5SDimitry Andric} 8300b57cec5SDimitry Andric 8310b57cec5SDimitry Andricdef : InstAlias<"sfence.vma", (SFENCE_VMA X0, X0)>; 8320b57cec5SDimitry Andricdef : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>; 8330b57cec5SDimitry Andric 8340b57cec5SDimitry Andriclet EmitPriority = 0 in { 8350b57cec5SDimitry Andricdef : InstAlias<"lb $rd, (${rs1})", 8360b57cec5SDimitry Andric (LB GPR:$rd, GPR:$rs1, 0)>; 8370b57cec5SDimitry Andricdef : InstAlias<"lh $rd, (${rs1})", 8380b57cec5SDimitry Andric (LH GPR:$rd, GPR:$rs1, 0)>; 8390b57cec5SDimitry Andricdef : InstAlias<"lw $rd, (${rs1})", 8400b57cec5SDimitry Andric (LW GPR:$rd, GPR:$rs1, 0)>; 8410b57cec5SDimitry Andricdef : InstAlias<"lbu $rd, (${rs1})", 8420b57cec5SDimitry Andric (LBU GPR:$rd, GPR:$rs1, 0)>; 8430b57cec5SDimitry Andricdef : InstAlias<"lhu $rd, (${rs1})", 8440b57cec5SDimitry Andric (LHU GPR:$rd, GPR:$rs1, 0)>; 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andricdef : InstAlias<"sb $rs2, (${rs1})", 8470b57cec5SDimitry Andric (SB GPR:$rs2, GPR:$rs1, 0)>; 8480b57cec5SDimitry Andricdef : InstAlias<"sh $rs2, (${rs1})", 8490b57cec5SDimitry Andric (SH GPR:$rs2, GPR:$rs1, 0)>; 8500b57cec5SDimitry Andricdef : InstAlias<"sw $rs2, (${rs1})", 8510b57cec5SDimitry Andric (SW GPR:$rs2, GPR:$rs1, 0)>; 8520b57cec5SDimitry Andric 8530b57cec5SDimitry Andricdef : InstAlias<"add $rd, $rs1, $imm12", 8540b57cec5SDimitry Andric (ADDI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 8550b57cec5SDimitry Andricdef : InstAlias<"and $rd, $rs1, $imm12", 8560b57cec5SDimitry Andric (ANDI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 8570b57cec5SDimitry Andricdef : InstAlias<"xor $rd, $rs1, $imm12", 8580b57cec5SDimitry Andric (XORI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 8590b57cec5SDimitry Andricdef : InstAlias<"or $rd, $rs1, $imm12", 8600b57cec5SDimitry Andric (ORI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 8610b57cec5SDimitry Andricdef : InstAlias<"sll $rd, $rs1, $shamt", 8620b57cec5SDimitry Andric (SLLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 8630b57cec5SDimitry Andricdef : InstAlias<"srl $rd, $rs1, $shamt", 8640b57cec5SDimitry Andric (SRLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 8650b57cec5SDimitry Andricdef : InstAlias<"sra $rd, $rs1, $shamt", 8660b57cec5SDimitry Andric (SRAI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 8670b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 8680b57cec5SDimitry Andricdef : InstAlias<"lwu $rd, (${rs1})", 8690b57cec5SDimitry Andric (LWU GPR:$rd, GPR:$rs1, 0)>; 8700b57cec5SDimitry Andricdef : InstAlias<"ld $rd, (${rs1})", 8710b57cec5SDimitry Andric (LD GPR:$rd, GPR:$rs1, 0)>; 8720b57cec5SDimitry Andricdef : InstAlias<"sd $rs2, (${rs1})", 8730b57cec5SDimitry Andric (SD GPR:$rs2, GPR:$rs1, 0)>; 8740b57cec5SDimitry Andric 8750b57cec5SDimitry Andricdef : InstAlias<"addw $rd, $rs1, $imm12", 8760b57cec5SDimitry Andric (ADDIW GPR:$rd, GPR:$rs1, simm12:$imm12)>; 8770b57cec5SDimitry Andricdef : InstAlias<"sllw $rd, $rs1, $shamt", 8780b57cec5SDimitry Andric (SLLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 8790b57cec5SDimitry Andricdef : InstAlias<"srlw $rd, $rs1, $shamt", 8800b57cec5SDimitry Andric (SRLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 8810b57cec5SDimitry Andricdef : InstAlias<"sraw $rd, $rs1, $shamt", 8820b57cec5SDimitry Andric (SRAIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 8830b57cec5SDimitry Andric} // Predicates = [IsRV64] 8840b57cec5SDimitry Andricdef : InstAlias<"slt $rd, $rs1, $imm12", 8850b57cec5SDimitry Andric (SLTI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 8860b57cec5SDimitry Andricdef : InstAlias<"sltu $rd, $rs1, $imm12", 8870b57cec5SDimitry Andric (SLTIU GPR:$rd, GPR:$rs1, simm12:$imm12)>; 8880b57cec5SDimitry Andric} 8890b57cec5SDimitry Andric 8900b57cec5SDimitry Andricdef : MnemonicAlias<"move", "mv">; 8910b57cec5SDimitry Andric 8920b57cec5SDimitry Andric// The SCALL and SBREAK instructions wererenamed to ECALL and EBREAK in 8930b57cec5SDimitry Andric// version 2.1 of the user-level ISA. Like the GNU toolchain, we still accept 8940b57cec5SDimitry Andric// the old name for backwards compatibility. 8950b57cec5SDimitry Andricdef : MnemonicAlias<"scall", "ecall">; 8960b57cec5SDimitry Andricdef : MnemonicAlias<"sbreak", "ebreak">; 8970b57cec5SDimitry Andric 898e8d8bef9SDimitry Andric// This alias was added to the spec in December 2020. Don't print it by default 899e8d8bef9SDimitry Andric// to allow assembly we print to be compatible with versions of GNU assembler 900e8d8bef9SDimitry Andric// that don't support this alias. 901e8d8bef9SDimitry Andricdef : InstAlias<"zext.b $rd, $rs", (ANDI GPR:$rd, GPR:$rs, 0xFF), 0>; 902e8d8bef9SDimitry Andric 9030b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 904349cc55cSDimitry Andric// .insn directive instructions 905349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 906349cc55cSDimitry Andric 907349cc55cSDimitry Andric// isCodeGenOnly = 1 to hide them from the tablegened assembly parser. 908349cc55cSDimitry Andriclet isCodeGenOnly = 1, hasSideEffects = 1, mayLoad = 1, mayStore = 1, 909349cc55cSDimitry Andric hasNoSchedulingInfo = 1 in { 9100eae32dcSDimitry Andricdef InsnR : DirectiveInsnR<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3, 911349cc55cSDimitry Andric uimm7:$funct7, AnyReg:$rs1, 912349cc55cSDimitry Andric AnyReg:$rs2), 913349cc55cSDimitry Andric "$opcode, $funct3, $funct7, $rd, $rs1, $rs2">; 9140eae32dcSDimitry Andricdef InsnR4 : DirectiveInsnR4<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 915349cc55cSDimitry Andric uimm3:$funct3, 916349cc55cSDimitry Andric uimm2:$funct2, 917349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2, 918349cc55cSDimitry Andric AnyReg:$rs3), 919349cc55cSDimitry Andric "$opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3">; 9200eae32dcSDimitry Andricdef InsnI : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3, 921349cc55cSDimitry Andric AnyReg:$rs1, simm12:$imm12), 922349cc55cSDimitry Andric "$opcode, $funct3, $rd, $rs1, $imm12">; 9230eae32dcSDimitry Andricdef InsnI_Mem : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 924349cc55cSDimitry Andric uimm3:$funct3, 925349cc55cSDimitry Andric AnyReg:$rs1, 926349cc55cSDimitry Andric simm12:$imm12), 927349cc55cSDimitry Andric "$opcode, $funct3, $rd, ${imm12}(${rs1})">; 9280eae32dcSDimitry Andricdef InsnB : DirectiveInsnB<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3, 929349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2, 930349cc55cSDimitry Andric simm13_lsb0:$imm12), 931349cc55cSDimitry Andric "$opcode, $funct3, $rs1, $rs2, $imm12">; 9320eae32dcSDimitry Andricdef InsnU : DirectiveInsnU<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 933349cc55cSDimitry Andric uimm20_lui:$imm20), 934349cc55cSDimitry Andric "$opcode, $rd, $imm20">; 9350eae32dcSDimitry Andricdef InsnJ : DirectiveInsnJ<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 936349cc55cSDimitry Andric simm21_lsb0_jal:$imm20), 937349cc55cSDimitry Andric "$opcode, $rd, $imm20">; 9380eae32dcSDimitry Andricdef InsnS : DirectiveInsnS<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3, 939349cc55cSDimitry Andric AnyReg:$rs2, AnyReg:$rs1, 940349cc55cSDimitry Andric simm12:$imm12), 941349cc55cSDimitry Andric "$opcode, $funct3, $rs2, ${imm12}(${rs1})">; 942349cc55cSDimitry Andric} 943349cc55cSDimitry Andric 944349cc55cSDimitry Andric// Use InstAliases to match these so that we can combine the insn and format 945349cc55cSDimitry Andric// into a mnemonic to use as the key for the tablegened asm matcher table. The 946349cc55cSDimitry Andric// parser will take care of creating these fake mnemonics and will only do it 947349cc55cSDimitry Andric// for known formats. 948349cc55cSDimitry Andriclet EmitPriority = 0 in { 949349cc55cSDimitry Andricdef : InstAlias<".insn_r $opcode, $funct3, $funct7, $rd, $rs1, $rs2", 9500eae32dcSDimitry Andric (InsnR AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm7:$funct7, 951349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2)>; 952349cc55cSDimitry Andric// Accept 4 register form of ".insn r" as alias for ".insn r4". 953349cc55cSDimitry Andricdef : InstAlias<".insn_r $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3", 9540eae32dcSDimitry Andric (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2, 955349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>; 956349cc55cSDimitry Andricdef : InstAlias<".insn_r4 $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3", 9570eae32dcSDimitry Andric (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2, 958349cc55cSDimitry Andric AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>; 959349cc55cSDimitry Andricdef : InstAlias<".insn_i $opcode, $funct3, $rd, $rs1, $imm12", 9600eae32dcSDimitry Andric (InsnI AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 961349cc55cSDimitry Andric simm12:$imm12)>; 962349cc55cSDimitry Andricdef : InstAlias<".insn_i $opcode, $funct3, $rd, ${imm12}(${rs1})", 9630eae32dcSDimitry Andric (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, 964349cc55cSDimitry Andric AnyReg:$rs1, simm12:$imm12)>; 965349cc55cSDimitry Andricdef : InstAlias<".insn_b $opcode, $funct3, $rs1, $rs2, $imm12", 9660eae32dcSDimitry Andric (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 967349cc55cSDimitry Andric AnyReg:$rs2, simm13_lsb0:$imm12)>; 968349cc55cSDimitry Andric// Accept sb as an alias for b. 969349cc55cSDimitry Andricdef : InstAlias<".insn_sb $opcode, $funct3, $rs1, $rs2, $imm12", 9700eae32dcSDimitry Andric (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 971349cc55cSDimitry Andric AnyReg:$rs2, simm13_lsb0:$imm12)>; 972349cc55cSDimitry Andricdef : InstAlias<".insn_u $opcode, $rd, $imm20", 9730eae32dcSDimitry Andric (InsnU AnyReg:$rd, uimm7_opcode:$opcode, uimm20_lui:$imm20)>; 974349cc55cSDimitry Andricdef : InstAlias<".insn_j $opcode, $rd, $imm20", 9750eae32dcSDimitry Andric (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>; 976349cc55cSDimitry Andric// Accept uj as an alias for j. 977349cc55cSDimitry Andricdef : InstAlias<".insn_uj $opcode, $rd, $imm20", 9780eae32dcSDimitry Andric (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>; 979349cc55cSDimitry Andricdef : InstAlias<".insn_s $opcode, $funct3, $rs2, ${imm12}(${rs1})", 9800eae32dcSDimitry Andric (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2, 981349cc55cSDimitry Andric AnyReg:$rs1, simm12:$imm12)>; 982349cc55cSDimitry Andric} 983349cc55cSDimitry Andric 984349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 9850b57cec5SDimitry Andric// Pseudo-instructions and codegen patterns 9860b57cec5SDimitry Andric// 9870b57cec5SDimitry Andric// Naming convention: For 'generic' pattern classes, we use the naming 9880b57cec5SDimitry Andric// convention PatTy1Ty2. For pattern classes which offer a more complex 9895ffd83dbSDimitry Andric// expansion, prefix the class name, e.g. BccPat. 9900b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 9910b57cec5SDimitry Andric 9920b57cec5SDimitry Andric/// Generic pattern classes 9930b57cec5SDimitry Andric 994fe6060f1SDimitry Andricclass PatGpr<SDPatternOperator OpNode, RVInst Inst> 995fe6060f1SDimitry Andric : Pat<(OpNode GPR:$rs1), (Inst GPR:$rs1)>; 9960b57cec5SDimitry Andricclass PatGprGpr<SDPatternOperator OpNode, RVInst Inst> 9970b57cec5SDimitry Andric : Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>; 998fe6060f1SDimitry Andric 999fe6060f1SDimitry Andricclass PatGprImm<SDPatternOperator OpNode, RVInst Inst, ImmLeaf ImmType> 1000fe6060f1SDimitry Andric : Pat<(XLenVT (OpNode (XLenVT GPR:$rs1), ImmType:$imm)), 1001fe6060f1SDimitry Andric (Inst GPR:$rs1, ImmType:$imm)>; 10020b57cec5SDimitry Andricclass PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst> 1003fe6060f1SDimitry Andric : PatGprImm<OpNode, Inst, simm12>; 10040b57cec5SDimitry Andricclass PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst> 1005fe6060f1SDimitry Andric : PatGprImm<OpNode, Inst, uimmlog2xlen>; 10060b57cec5SDimitry Andric 10070b57cec5SDimitry Andric/// Predicates 10080b57cec5SDimitry Andric 10090b57cec5SDimitry Andricdef IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{ 10100b57cec5SDimitry Andric return isOrEquivalentToAdd(N); 10110b57cec5SDimitry Andric}]>; 10120b57cec5SDimitry Andricdef assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{ 1013e8d8bef9SDimitry Andric return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32); 10140b57cec5SDimitry Andric}]>; 1015fe6060f1SDimitry Andricdef sexti32 : ComplexPattern<i64, 1, "selectSExti32">; 10160b57cec5SDimitry Andricdef assertzexti32 : PatFrag<(ops node:$src), (assertzext node:$src), [{ 1017e8d8bef9SDimitry Andric return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32); 10180b57cec5SDimitry Andric}]>; 1019fe6060f1SDimitry Andricdef zexti32 : ComplexPattern<i64, 1, "selectZExti32">; 10200b57cec5SDimitry Andric 1021fe6060f1SDimitry Andricdef add_oneuse : PatFrag<(ops node:$A, node:$B), (add node:$A, node:$B), [{ 1022fe6060f1SDimitry Andric return N->hasOneUse(); 1023e8d8bef9SDimitry Andric}]>; 1024e8d8bef9SDimitry Andric 1025fe6060f1SDimitry Andricdef mul_oneuse : PatFrag<(ops node:$A, node:$B), (mul node:$A, node:$B), [{ 1026fe6060f1SDimitry Andric return N->hasOneUse(); 1027e8d8bef9SDimitry Andric}]>; 1028e8d8bef9SDimitry Andric 1029349cc55cSDimitry Andricdef mul_const_oneuse : PatFrag<(ops node:$A, node:$B), 1030349cc55cSDimitry Andric (mul node:$A, node:$B), [{ 1031349cc55cSDimitry Andric if (auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1))) 1032349cc55cSDimitry Andric if (N1C->hasOneUse()) 1033349cc55cSDimitry Andric return true; 1034349cc55cSDimitry Andric return false; 1035349cc55cSDimitry Andric}]>; 1036349cc55cSDimitry Andric 103704eeddc0SDimitry Andricdef sext_oneuse : PatFrag<(ops node:$A), (sext node:$A), [{ 103804eeddc0SDimitry Andric return N->hasOneUse(); 103904eeddc0SDimitry Andric}]>; 104004eeddc0SDimitry Andric 104104eeddc0SDimitry Andricdef zext_oneuse : PatFrag<(ops node:$A), (zext node:$A), [{ 104204eeddc0SDimitry Andric return N->hasOneUse(); 104304eeddc0SDimitry Andric}]>; 104404eeddc0SDimitry Andric 104504eeddc0SDimitry Andricdef anyext_oneuse : PatFrag<(ops node:$A), (anyext node:$A), [{ 104604eeddc0SDimitry Andric return N->hasOneUse(); 104704eeddc0SDimitry Andric}]>; 104804eeddc0SDimitry Andric 104904eeddc0SDimitry Andricdef fpext_oneuse : PatFrag<(ops node:$A), 105004eeddc0SDimitry Andric (any_fpextend node:$A), [{ 105104eeddc0SDimitry Andric return N->hasOneUse(); 105204eeddc0SDimitry Andric}]>; 105304eeddc0SDimitry Andric 10540b57cec5SDimitry Andric/// Simple arithmetic operations 10550b57cec5SDimitry Andric 10560b57cec5SDimitry Andricdef : PatGprGpr<add, ADD>; 10570b57cec5SDimitry Andricdef : PatGprSimm12<add, ADDI>; 10580b57cec5SDimitry Andricdef : PatGprGpr<sub, SUB>; 10590b57cec5SDimitry Andricdef : PatGprGpr<or, OR>; 10600b57cec5SDimitry Andricdef : PatGprSimm12<or, ORI>; 10610b57cec5SDimitry Andricdef : PatGprGpr<and, AND>; 10620b57cec5SDimitry Andricdef : PatGprSimm12<and, ANDI>; 10630b57cec5SDimitry Andricdef : PatGprGpr<xor, XOR>; 10640b57cec5SDimitry Andricdef : PatGprSimm12<xor, XORI>; 10650b57cec5SDimitry Andricdef : PatGprUimmLog2XLen<shl, SLLI>; 10660b57cec5SDimitry Andricdef : PatGprUimmLog2XLen<srl, SRLI>; 10670b57cec5SDimitry Andricdef : PatGprUimmLog2XLen<sra, SRAI>; 10680b57cec5SDimitry Andric 106904eeddc0SDimitry Andric// AND with trailing ones mask exceeding simm12. 107004eeddc0SDimitry Andricdef : Pat<(XLenVT (and GPR:$rs, TrailingOnesMask:$mask)), 107104eeddc0SDimitry Andric (SRLI (SLLI $rs, TrailingOnesMask:$mask), TrailingOnesMask:$mask)>; 107204eeddc0SDimitry Andric 10730b57cec5SDimitry Andric// Match both a plain shift and one where the shift amount is masked (this is 10740b57cec5SDimitry Andric// typically introduced when the legalizer promotes the shift amount and 10750b57cec5SDimitry Andric// zero-extends it). For RISC-V, the mask is unnecessary as shifts in the base 10760b57cec5SDimitry Andric// ISA only read the least significant 5 bits (RV32I) or 6 bits (RV64I). 1077fe6060f1SDimitry Andricdef shiftMaskXLen : ComplexPattern<XLenVT, 1, "selectShiftMaskXLen", [], [], 0>; 1078fe6060f1SDimitry Andricdef shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>; 1079fe6060f1SDimitry Andric 10800b57cec5SDimitry Andricclass shiftop<SDPatternOperator operator> 1081fe6060f1SDimitry Andric : PatFrag<(ops node:$val, node:$count), 1082fe6060f1SDimitry Andric (operator node:$val, (XLenVT (shiftMaskXLen node:$count)))>; 1083e8d8bef9SDimitry Andricclass shiftopw<SDPatternOperator operator> 1084fe6060f1SDimitry Andric : PatFrag<(ops node:$val, node:$count), 1085fe6060f1SDimitry Andric (operator node:$val, (i64 (shiftMask32 node:$count)))>; 10860b57cec5SDimitry Andric 10870b57cec5SDimitry Andricdef : PatGprGpr<shiftop<shl>, SLL>; 10880b57cec5SDimitry Andricdef : PatGprGpr<shiftop<srl>, SRL>; 10890b57cec5SDimitry Andricdef : PatGprGpr<shiftop<sra>, SRA>; 10900b57cec5SDimitry Andric 10910b57cec5SDimitry Andric// This is a special case of the ADD instruction used to facilitate the use of a 10920b57cec5SDimitry Andric// fourth operand to emit a relocation on a symbol relating to this instruction. 10930b57cec5SDimitry Andric// The relocation does not affect any bits of the instruction itself but is used 10940b57cec5SDimitry Andric// as a hint to the linker. 10950b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in 10960b57cec5SDimitry Andricdef PseudoAddTPRel : Pseudo<(outs GPR:$rd), 10970b57cec5SDimitry Andric (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [], 10980b57cec5SDimitry Andric "add", "$rd, $rs1, $rs2, $src">; 10990b57cec5SDimitry Andric 11000b57cec5SDimitry Andric/// FrameIndex calculations 11010b57cec5SDimitry Andric 1102e8d8bef9SDimitry Andricdef : Pat<(add (XLenVT AddrFI:$Rs), simm12:$imm12), 1103e8d8bef9SDimitry Andric (ADDI (XLenVT AddrFI:$Rs), simm12:$imm12)>; 1104e8d8bef9SDimitry Andricdef : Pat<(IsOrAdd (XLenVT AddrFI:$Rs), simm12:$imm12), 1105e8d8bef9SDimitry Andric (ADDI (XLenVT AddrFI:$Rs), simm12:$imm12)>; 11060b57cec5SDimitry Andric 11070b57cec5SDimitry Andric/// Setcc 11080b57cec5SDimitry Andric 11090b57cec5SDimitry Andricdef : PatGprGpr<setlt, SLT>; 11100b57cec5SDimitry Andricdef : PatGprSimm12<setlt, SLTI>; 11110b57cec5SDimitry Andricdef : PatGprGpr<setult, SLTU>; 11120b57cec5SDimitry Andricdef : PatGprSimm12<setult, SLTIU>; 11130b57cec5SDimitry Andric 11140b57cec5SDimitry Andric// Define pattern expansions for setcc operations that aren't directly 11150b57cec5SDimitry Andric// handled by a RISC-V instruction. 11160b57cec5SDimitry Andricdef : Pat<(seteq GPR:$rs1, 0), (SLTIU GPR:$rs1, 1)>; 11170b57cec5SDimitry Andricdef : Pat<(seteq GPR:$rs1, GPR:$rs2), (SLTIU (XOR GPR:$rs1, GPR:$rs2), 1)>; 11185ffd83dbSDimitry Andricdef : Pat<(seteq GPR:$rs1, simm12_plus1:$imm12), 11195ffd83dbSDimitry Andric (SLTIU (ADDI GPR:$rs1, (NegImm simm12_plus1:$imm12)), 1)>; 11200b57cec5SDimitry Andricdef : Pat<(setne GPR:$rs1, 0), (SLTU X0, GPR:$rs1)>; 11210b57cec5SDimitry Andricdef : Pat<(setne GPR:$rs1, GPR:$rs2), (SLTU X0, (XOR GPR:$rs1, GPR:$rs2))>; 11225ffd83dbSDimitry Andricdef : Pat<(setne GPR:$rs1, simm12_plus1:$imm12), 11235ffd83dbSDimitry Andric (SLTU X0, (ADDI GPR:$rs1, (NegImm simm12_plus1:$imm12)))>; 11240b57cec5SDimitry Andricdef : Pat<(setugt GPR:$rs1, GPR:$rs2), (SLTU GPR:$rs2, GPR:$rs1)>; 11250b57cec5SDimitry Andricdef : Pat<(setuge GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs1, GPR:$rs2), 1)>; 11260b57cec5SDimitry Andricdef : Pat<(setule GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs2, GPR:$rs1), 1)>; 11270b57cec5SDimitry Andricdef : Pat<(setgt GPR:$rs1, GPR:$rs2), (SLT GPR:$rs2, GPR:$rs1)>; 11280b57cec5SDimitry Andricdef : Pat<(setge GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs1, GPR:$rs2), 1)>; 11290b57cec5SDimitry Andricdef : Pat<(setle GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs2, GPR:$rs1), 1)>; 11300b57cec5SDimitry Andric 1131349cc55cSDimitry Andricdef IntCCtoRISCVCC : SDNodeXForm<riscv_selectcc, [{ 1132349cc55cSDimitry Andric ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get(); 1133349cc55cSDimitry Andric RISCVCC::CondCode BrCC = getRISCVCCForIntCC(CC); 1134349cc55cSDimitry Andric return CurDAG->getTargetConstant(BrCC, SDLoc(N), Subtarget->getXLenVT()); 1135349cc55cSDimitry Andric}]>; 1136349cc55cSDimitry Andric 1137349cc55cSDimitry Andricdef riscv_selectcc_frag : PatFrag<(ops node:$lhs, node:$rhs, node:$cc, 1138349cc55cSDimitry Andric node:$truev, node:$falsev), 1139349cc55cSDimitry Andric (riscv_selectcc node:$lhs, node:$rhs, 1140349cc55cSDimitry Andric node:$cc, node:$truev, 1141349cc55cSDimitry Andric node:$falsev), [{}], 1142349cc55cSDimitry Andric IntCCtoRISCVCC>; 1143349cc55cSDimitry Andric 11440b57cec5SDimitry Andriclet usesCustomInserter = 1 in 11450b57cec5SDimitry Andricclass SelectCC_rrirr<RegisterClass valty, RegisterClass cmpty> 11460b57cec5SDimitry Andric : Pseudo<(outs valty:$dst), 11470b57cec5SDimitry Andric (ins cmpty:$lhs, cmpty:$rhs, ixlenimm:$imm, 11480b57cec5SDimitry Andric valty:$truev, valty:$falsev), 1149349cc55cSDimitry Andric [(set valty:$dst, 1150349cc55cSDimitry Andric (riscv_selectcc_frag:$imm cmpty:$lhs, cmpty:$rhs, cond, 1151349cc55cSDimitry Andric valty:$truev, valty:$falsev))]>; 11520b57cec5SDimitry Andric 11530b57cec5SDimitry Andricdef Select_GPR_Using_CC_GPR : SelectCC_rrirr<GPR, GPR>; 11540b57cec5SDimitry Andric 11550b57cec5SDimitry Andric/// Branches and jumps 11560b57cec5SDimitry Andric 1157fe6060f1SDimitry Andric// Match `riscv_brcc` and lower to the appropriate RISC-V branch instruction. 1158fe6060f1SDimitry Andricclass BccPat<CondCode Cond, RVInstB Inst> 1159fe6060f1SDimitry Andric : Pat<(riscv_brcc GPR:$rs1, GPR:$rs2, Cond, bb:$imm12), 11600b57cec5SDimitry Andric (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>; 11610b57cec5SDimitry Andric 1162fe6060f1SDimitry Andricdef : BccPat<SETEQ, BEQ>; 1163fe6060f1SDimitry Andricdef : BccPat<SETNE, BNE>; 1164fe6060f1SDimitry Andricdef : BccPat<SETLT, BLT>; 1165fe6060f1SDimitry Andricdef : BccPat<SETGE, BGE>; 1166fe6060f1SDimitry Andricdef : BccPat<SETULT, BLTU>; 1167fe6060f1SDimitry Andricdef : BccPat<SETUGE, BGEU>; 11680b57cec5SDimitry Andric 11690b57cec5SDimitry Andriclet isBarrier = 1, isBranch = 1, isTerminator = 1 in 11700b57cec5SDimitry Andricdef PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>, 11710b57cec5SDimitry Andric PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>; 11720b57cec5SDimitry Andric 11730b57cec5SDimitry Andriclet isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in 1174fe6060f1SDimitry Andricdef PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12:$imm12), []>, 11750b57cec5SDimitry Andric PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; 11760b57cec5SDimitry Andric 1177fe6060f1SDimitry Andricdef : Pat<(brind GPRJALR:$rs1), (PseudoBRIND GPRJALR:$rs1, 0)>; 1178fe6060f1SDimitry Andricdef : Pat<(brind (add GPRJALR:$rs1, simm12:$imm12)), 1179fe6060f1SDimitry Andric (PseudoBRIND GPRJALR:$rs1, simm12:$imm12)>; 11800b57cec5SDimitry Andric 1181480093f4SDimitry Andric// PseudoCALLReg is a generic pseudo instruction for calls which will eventually 11820b57cec5SDimitry Andric// expand to auipc and jalr while encoding, with any given register used as the 11830b57cec5SDimitry Andric// destination. 11840b57cec5SDimitry Andric// Define AsmString to print "call" when compile with -S flag. 11850b57cec5SDimitry Andric// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 11860b57cec5SDimitry Andriclet isCall = 1, isBarrier = 1, isCodeGenOnly = 0, hasSideEffects = 0, 11870b57cec5SDimitry Andric mayStore = 0, mayLoad = 0 in 11880b57cec5SDimitry Andricdef PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), []> { 11890b57cec5SDimitry Andric let AsmString = "call\t$rd, $func"; 11900b57cec5SDimitry Andric} 11910b57cec5SDimitry Andric 11920b57cec5SDimitry Andric// PseudoCALL is a pseudo instruction which will eventually expand to auipc 11930b57cec5SDimitry Andric// and jalr while encoding. This is desirable, as an auipc+jalr pair with 11940b57cec5SDimitry Andric// R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker 11950b57cec5SDimitry Andric// if the offset fits in a signed 21-bit immediate. 11960b57cec5SDimitry Andric// Define AsmString to print "call" when compile with -S flag. 11970b57cec5SDimitry Andric// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 11980b57cec5SDimitry Andriclet isCall = 1, Defs = [X1], isCodeGenOnly = 0 in 11990b57cec5SDimitry Andricdef PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), []> { 12000b57cec5SDimitry Andric let AsmString = "call\t$func"; 12010b57cec5SDimitry Andric} 12020b57cec5SDimitry Andric 12030b57cec5SDimitry Andricdef : Pat<(riscv_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>; 12040b57cec5SDimitry Andricdef : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>; 12050b57cec5SDimitry Andric 12060b57cec5SDimitry Andricdef : Pat<(riscv_uret_flag), (URET X0, X0)>; 12070b57cec5SDimitry Andricdef : Pat<(riscv_sret_flag), (SRET X0, X0)>; 12080b57cec5SDimitry Andricdef : Pat<(riscv_mret_flag), (MRET X0, X0)>; 12090b57cec5SDimitry Andric 12100b57cec5SDimitry Andriclet isCall = 1, Defs = [X1] in 1211fe6060f1SDimitry Andricdef PseudoCALLIndirect : Pseudo<(outs), (ins GPRJALR:$rs1), 1212fe6060f1SDimitry Andric [(riscv_call GPRJALR:$rs1)]>, 12130b57cec5SDimitry Andric PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>; 12140b57cec5SDimitry Andric 12150b57cec5SDimitry Andriclet isBarrier = 1, isReturn = 1, isTerminator = 1 in 12160b57cec5SDimitry Andricdef PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_flag)]>, 12170b57cec5SDimitry Andric PseudoInstExpansion<(JALR X0, X1, 0)>; 12180b57cec5SDimitry Andric 12190b57cec5SDimitry Andric// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually 12200b57cec5SDimitry Andric// expand to auipc and jalr while encoding. 12210b57cec5SDimitry Andric// Define AsmString to print "tail" when compile with -S flag. 12220b57cec5SDimitry Andriclet isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2], 12230b57cec5SDimitry Andric isCodeGenOnly = 0 in 12240b57cec5SDimitry Andricdef PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), []> { 12250b57cec5SDimitry Andric let AsmString = "tail\t$dst"; 12260b57cec5SDimitry Andric} 12270b57cec5SDimitry Andric 12280b57cec5SDimitry Andriclet isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in 12290b57cec5SDimitry Andricdef PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1), 12300b57cec5SDimitry Andric [(riscv_tail GPRTC:$rs1)]>, 12310b57cec5SDimitry Andric PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>; 12320b57cec5SDimitry Andric 12330b57cec5SDimitry Andricdef : Pat<(riscv_tail (iPTR tglobaladdr:$dst)), 12340b57cec5SDimitry Andric (PseudoTAIL texternalsym:$dst)>; 12350b57cec5SDimitry Andricdef : Pat<(riscv_tail (iPTR texternalsym:$dst)), 12360b57cec5SDimitry Andric (PseudoTAIL texternalsym:$dst)>; 12370b57cec5SDimitry Andric 123875b4d546SDimitry Andriclet isCall = 0, isBarrier = 1, isBranch = 1, isTerminator = 1, 123975b4d546SDimitry Andric isCodeGenOnly = 0, hasSideEffects = 0, mayStore = 0, mayLoad = 0 in 12405ffd83dbSDimitry Andricdef PseudoJump : Pseudo<(outs GPR:$rd), (ins pseudo_jump_symbol:$target), []> { 12415ffd83dbSDimitry Andric let AsmString = "jump\t$target, $rd"; 12425ffd83dbSDimitry Andric} 12435ffd83dbSDimitry Andric 12440b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0, 12450b57cec5SDimitry Andric isAsmParserOnly = 1 in 12460b57cec5SDimitry Andricdef PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 12470b57cec5SDimitry Andric "lla", "$dst, $src">; 12480b57cec5SDimitry Andric 12490b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, 12500b57cec5SDimitry Andric isAsmParserOnly = 1 in 12510b57cec5SDimitry Andricdef PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 12520b57cec5SDimitry Andric "la", "$dst, $src">; 12530b57cec5SDimitry Andric 12540b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, 12550b57cec5SDimitry Andric isAsmParserOnly = 1 in 12560b57cec5SDimitry Andricdef PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 12570b57cec5SDimitry Andric "la.tls.ie", "$dst, $src">; 12580b57cec5SDimitry Andric 12590b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, 12600b57cec5SDimitry Andric isAsmParserOnly = 1 in 12610b57cec5SDimitry Andricdef PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 12620b57cec5SDimitry Andric "la.tls.gd", "$dst, $src">; 12630b57cec5SDimitry Andric 1264e8d8bef9SDimitry Andric 1265e8d8bef9SDimitry Andric/// Sign/Zero Extends 1266e8d8bef9SDimitry Andric 1267e8d8bef9SDimitry Andric// There are single-instruction versions of these in Zbb, so disable these 1268e8d8bef9SDimitry Andric// Pseudos if that extension is present. 1269e8d8bef9SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, 1270e8d8bef9SDimitry Andric mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in { 1271e8d8bef9SDimitry Andricdef PseudoSEXT_B : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.b", "$rd, $rs">; 1272e8d8bef9SDimitry Andricdef PseudoSEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.h", "$rd, $rs">; 1273e8d8bef9SDimitry Andric// rv64's sext.w is defined above, using InstAlias<"sext.w ... 1274e8d8bef9SDimitry Andric// zext.b is defined above, using InstAlias<"zext.b ... 1275e8d8bef9SDimitry Andricdef PseudoZEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.h", "$rd, $rs">; 1276e8d8bef9SDimitry Andric} // hasSideEffects = 0, ... 1277e8d8bef9SDimitry Andric 1278e8d8bef9SDimitry Andriclet Predicates = [IsRV64], hasSideEffects = 0, mayLoad = 0, mayStore = 0, 1279e8d8bef9SDimitry Andric isCodeGenOnly = 0, isAsmParserOnly = 1 in { 1280e8d8bef9SDimitry Andricdef PseudoZEXT_W : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.w", "$rd, $rs">; 1281e8d8bef9SDimitry Andric} // Predicates = [IsRV64], ... 1282e8d8bef9SDimitry Andric 12830b57cec5SDimitry Andric/// Loads 12840b57cec5SDimitry Andric 1285fe6060f1SDimitry Andricmulticlass LdPat<PatFrag LoadOp, RVInst Inst, ValueType vt = XLenVT> { 1286fe6060f1SDimitry Andric def : Pat<(vt (LoadOp BaseAddr:$rs1)), (Inst BaseAddr:$rs1, 0)>; 1287fe6060f1SDimitry Andric def : Pat<(vt (LoadOp (add BaseAddr:$rs1, simm12:$imm12))), 1288fe6060f1SDimitry Andric (Inst BaseAddr:$rs1, simm12:$imm12)>; 1289fe6060f1SDimitry Andric def : Pat<(vt (LoadOp (IsOrAdd AddrFI:$rs1, simm12:$imm12))), 12900b57cec5SDimitry Andric (Inst AddrFI:$rs1, simm12:$imm12)>; 12910b57cec5SDimitry Andric} 12920b57cec5SDimitry Andric 12930b57cec5SDimitry Andricdefm : LdPat<sextloadi8, LB>; 12940b57cec5SDimitry Andricdefm : LdPat<extloadi8, LB>; 12950b57cec5SDimitry Andricdefm : LdPat<sextloadi16, LH>; 12960b57cec5SDimitry Andricdefm : LdPat<extloadi16, LH>; 1297fe6060f1SDimitry Andricdefm : LdPat<load, LW, i32>, Requires<[IsRV32]>; 12980b57cec5SDimitry Andricdefm : LdPat<zextloadi8, LBU>; 12990b57cec5SDimitry Andricdefm : LdPat<zextloadi16, LHU>; 13000b57cec5SDimitry Andric 13010b57cec5SDimitry Andric/// Stores 13020b57cec5SDimitry Andric 1303fe6060f1SDimitry Andricmulticlass StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy, 1304fe6060f1SDimitry Andric ValueType vt> { 1305fe6060f1SDimitry Andric def : Pat<(StoreOp (vt StTy:$rs2), BaseAddr:$rs1), 1306fe6060f1SDimitry Andric (Inst StTy:$rs2, BaseAddr:$rs1, 0)>; 1307fe6060f1SDimitry Andric def : Pat<(StoreOp (vt StTy:$rs2), (add BaseAddr:$rs1, simm12:$imm12)), 1308fe6060f1SDimitry Andric (Inst StTy:$rs2, BaseAddr:$rs1, simm12:$imm12)>; 1309fe6060f1SDimitry Andric def : Pat<(StoreOp (vt StTy:$rs2), (IsOrAdd AddrFI:$rs1, simm12:$imm12)), 13100b57cec5SDimitry Andric (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>; 13110b57cec5SDimitry Andric} 13120b57cec5SDimitry Andric 1313fe6060f1SDimitry Andricdefm : StPat<truncstorei8, SB, GPR, XLenVT>; 1314fe6060f1SDimitry Andricdefm : StPat<truncstorei16, SH, GPR, XLenVT>; 1315fe6060f1SDimitry Andricdefm : StPat<store, SW, GPR, i32>, Requires<[IsRV32]>; 13160b57cec5SDimitry Andric 13170b57cec5SDimitry Andric/// Fences 13180b57cec5SDimitry Andric 13190b57cec5SDimitry Andric// Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set 13200b57cec5SDimitry Andric// Manual: Volume I. 13210b57cec5SDimitry Andric 13220b57cec5SDimitry Andric// fence acquire -> fence r, rw 1323480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 4), (timm)), (FENCE 0b10, 0b11)>; 13240b57cec5SDimitry Andric// fence release -> fence rw, w 1325480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 5), (timm)), (FENCE 0b11, 0b1)>; 13260b57cec5SDimitry Andric// fence acq_rel -> fence.tso 1327480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 6), (timm)), (FENCE_TSO)>; 13280b57cec5SDimitry Andric// fence seq_cst -> fence rw, rw 1329480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 7), (timm)), (FENCE 0b11, 0b11)>; 13300b57cec5SDimitry Andric 13310b57cec5SDimitry Andric// Lowering for atomic load and store is defined in RISCVInstrInfoA.td. 13320b57cec5SDimitry Andric// Although these are lowered to fence+load/store instructions defined in the 13330b57cec5SDimitry Andric// base RV32I/RV64I ISA, this lowering is only used when the A extension is 13340b57cec5SDimitry Andric// present. This is necessary as it isn't valid to mix __atomic_* libcalls 13350b57cec5SDimitry Andric// with inline atomic operations for the same object. 13360b57cec5SDimitry Andric 1337fe6060f1SDimitry Andric/// Access to system registers 1338fe6060f1SDimitry Andric 1339fe6060f1SDimitry Andric// Helpers for defining specific operations. They are defined for each system 1340fe6060f1SDimitry Andric// register separately. Side effect is not used because dependencies are 1341fe6060f1SDimitry Andric// expressed via use-def properties. 1342fe6060f1SDimitry Andric 1343fe6060f1SDimitry Andricclass ReadSysReg<SysReg SR, list<Register> Regs> 1344fe6060f1SDimitry Andric : Pseudo<(outs GPR:$rd), (ins), 1345fe6060f1SDimitry Andric [(set GPR:$rd, (riscv_read_csr (XLenVT SR.Encoding)))]>, 1346fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRS GPR:$rd, SR.Encoding, X0)> { 1347fe6060f1SDimitry Andric let hasSideEffects = 0; 1348fe6060f1SDimitry Andric let Uses = Regs; 1349fe6060f1SDimitry Andric} 1350fe6060f1SDimitry Andric 1351fe6060f1SDimitry Andricclass WriteSysReg<SysReg SR, list<Register> Regs> 1352fe6060f1SDimitry Andric : Pseudo<(outs), (ins GPR:$val), 1353fe6060f1SDimitry Andric [(riscv_write_csr (XLenVT SR.Encoding), GPR:$val)]>, 1354fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRW X0, SR.Encoding, GPR:$val)> { 1355fe6060f1SDimitry Andric let hasSideEffects = 0; 1356fe6060f1SDimitry Andric let Defs = Regs; 1357fe6060f1SDimitry Andric} 1358fe6060f1SDimitry Andric 1359fe6060f1SDimitry Andricclass WriteSysRegImm<SysReg SR, list<Register> Regs> 1360fe6060f1SDimitry Andric : Pseudo<(outs), (ins uimm5:$val), 1361fe6060f1SDimitry Andric [(riscv_write_csr (XLenVT SR.Encoding), uimm5:$val)]>, 1362fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRWI X0, SR.Encoding, uimm5:$val)> { 1363fe6060f1SDimitry Andric let hasSideEffects = 0; 1364fe6060f1SDimitry Andric let Defs = Regs; 1365fe6060f1SDimitry Andric} 1366fe6060f1SDimitry Andric 1367fe6060f1SDimitry Andricclass SwapSysReg<SysReg SR, list<Register> Regs> 1368fe6060f1SDimitry Andric : Pseudo<(outs GPR:$rd), (ins GPR:$val), 1369fe6060f1SDimitry Andric [(set GPR:$rd, (riscv_swap_csr (XLenVT SR.Encoding), GPR:$val))]>, 1370fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRW GPR:$rd, SR.Encoding, GPR:$val)> { 1371fe6060f1SDimitry Andric let hasSideEffects = 0; 1372fe6060f1SDimitry Andric let Uses = Regs; 1373fe6060f1SDimitry Andric let Defs = Regs; 1374fe6060f1SDimitry Andric} 1375fe6060f1SDimitry Andric 1376fe6060f1SDimitry Andricclass SwapSysRegImm<SysReg SR, list<Register> Regs> 1377fe6060f1SDimitry Andric : Pseudo<(outs GPR:$rd), (ins uimm5:$val), 1378fe6060f1SDimitry Andric [(set GPR:$rd, (riscv_swap_csr (XLenVT SR.Encoding), uimm5:$val))]>, 1379fe6060f1SDimitry Andric PseudoInstExpansion<(CSRRWI GPR:$rd, SR.Encoding, uimm5:$val)> { 1380fe6060f1SDimitry Andric let hasSideEffects = 0; 1381fe6060f1SDimitry Andric let Uses = Regs; 1382fe6060f1SDimitry Andric let Defs = Regs; 1383fe6060f1SDimitry Andric} 1384fe6060f1SDimitry Andric 1385fe6060f1SDimitry Andricdef ReadFRM : ReadSysReg<SysRegFRM, [FRM]>; 1386fe6060f1SDimitry Andricdef WriteFRM : WriteSysReg<SysRegFRM, [FRM]>; 1387fe6060f1SDimitry Andricdef WriteFRMImm : WriteSysRegImm<SysRegFRM, [FRM]>; 1388fe6060f1SDimitry Andric 138904eeddc0SDimitry Andriclet hasSideEffects = true in { 139004eeddc0SDimitry Andricdef ReadFFLAGS : ReadSysReg<SysRegFFLAGS, [FFLAGS]>; 139104eeddc0SDimitry Andricdef WriteFFLAGS : WriteSysReg<SysRegFFLAGS, [FFLAGS]>; 139204eeddc0SDimitry Andric} 13930b57cec5SDimitry Andric/// Other pseudo-instructions 13940b57cec5SDimitry Andric 13950b57cec5SDimitry Andric// Pessimistically assume the stack pointer will be clobbered 13960b57cec5SDimitry Andriclet Defs = [X2], Uses = [X2] in { 13970b57cec5SDimitry Andricdef ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 13980b57cec5SDimitry Andric [(callseq_start timm:$amt1, timm:$amt2)]>; 13990b57cec5SDimitry Andricdef ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 14000b57cec5SDimitry Andric [(callseq_end timm:$amt1, timm:$amt2)]>; 14010b57cec5SDimitry Andric} // Defs = [X2], Uses = [X2] 14020b57cec5SDimitry Andric 14030b57cec5SDimitry Andric/// RV64 patterns 14040b57cec5SDimitry Andric 1405e8d8bef9SDimitry Andriclet Predicates = [IsRV64, NotHasStdExtZba] in { 1406fe6060f1SDimitry Andricdef : Pat<(i64 (and GPR:$rs1, 0xffffffff)), (SRLI (SLLI GPR:$rs1, 32), 32)>; 1407e8d8bef9SDimitry Andric 1408e8d8bef9SDimitry Andric// If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2 1409e8d8bef9SDimitry Andric// shifts instead of 3. This can occur when unsigned is used to index an array. 1410fe6060f1SDimitry Andricdef : Pat<(i64 (shl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)), 1411e8d8bef9SDimitry Andric (SRLI (SLLI GPR:$rs1, 32), (ImmSubFrom32 uimm5:$shamt))>; 1412e8d8bef9SDimitry Andric} 1413e8d8bef9SDimitry Andric 1414349cc55cSDimitry Andric// PatFrag to allow ADDW/SUBW/MULW/SLLW to be selected from i64 add/sub/mul/shl 1415349cc55cSDimitry Andric// if only the lower 32 bits of their result is used. 1416349cc55cSDimitry Andricclass binop_allwusers<SDPatternOperator operator> 1417349cc55cSDimitry Andric : PatFrag<(ops node:$lhs, node:$rhs), 1418349cc55cSDimitry Andric (operator node:$lhs, node:$rhs), [{ 1419349cc55cSDimitry Andric return hasAllWUsers(Node); 1420349cc55cSDimitry Andric}]>; 1421349cc55cSDimitry Andric 1422349cc55cSDimitry Andricdef sexti32_allwusers : PatFrag<(ops node:$src), 1423349cc55cSDimitry Andric (sext_inreg node:$src, i32), [{ 1424349cc55cSDimitry Andric return hasAllWUsers(Node); 1425349cc55cSDimitry Andric}]>; 1426349cc55cSDimitry Andric 14270b57cec5SDimitry Andriclet Predicates = [IsRV64] in { 14280b57cec5SDimitry Andric 14290b57cec5SDimitry Andric/// sext and zext 14300b57cec5SDimitry Andric 1431349cc55cSDimitry Andric// Sign extend is not needed if all users are W instructions. 1432349cc55cSDimitry Andricdef : Pat<(sexti32_allwusers GPR:$rs1), (XLenVT GPR:$rs1)>; 1433349cc55cSDimitry Andric 14340b57cec5SDimitry Andricdef : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>; 14350b57cec5SDimitry Andric 14360b57cec5SDimitry Andric/// ALU operations 14370b57cec5SDimitry Andric 1438fe6060f1SDimitry Andricdef : Pat<(i64 (srl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)), 1439e8d8bef9SDimitry Andric (SRLIW GPR:$rs1, uimm5:$shamt)>; 1440fe6060f1SDimitry Andricdef : Pat<(i64 (srl (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)), 1441e8d8bef9SDimitry Andric (SRLIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>; 14420b57cec5SDimitry Andricdef : Pat<(sra (sext_inreg GPR:$rs1, i32), uimm5:$shamt), 14430b57cec5SDimitry Andric (SRAIW GPR:$rs1, uimm5:$shamt)>; 1444fe6060f1SDimitry Andricdef : Pat<(i64 (sra (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)), 1445e8d8bef9SDimitry Andric (SRAIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>; 14460b57cec5SDimitry Andric 1447e8d8bef9SDimitry Andricdef : PatGprGpr<shiftopw<riscv_sllw>, SLLW>; 1448e8d8bef9SDimitry Andricdef : PatGprGpr<shiftopw<riscv_srlw>, SRLW>; 1449e8d8bef9SDimitry Andricdef : PatGprGpr<shiftopw<riscv_sraw>, SRAW>; 14500b57cec5SDimitry Andric 1451349cc55cSDimitry Andric// Select W instructions if only the lower 32 bits of the result are used. 1452349cc55cSDimitry Andricdef : PatGprGpr<binop_allwusers<add>, ADDW>; 1453349cc55cSDimitry Andricdef : PatGprSimm12<binop_allwusers<add>, ADDIW>; 1454349cc55cSDimitry Andricdef : PatGprGpr<binop_allwusers<sub>, SUBW>; 1455349cc55cSDimitry Andricdef : PatGprImm<binop_allwusers<shl>, SLLIW, uimm5>; 1456349cc55cSDimitry Andric 1457349cc55cSDimitry Andric// If this is a shr of a value sign extended from i32, and all the users only 1458349cc55cSDimitry Andric// use the lower 32 bits, we can use an sraiw to remove the sext_inreg. This 1459349cc55cSDimitry Andric// occurs because SimplifyDemandedBits prefers srl over sra. 1460349cc55cSDimitry Andricdef : Pat<(binop_allwusers<srl> (sext_inreg GPR:$rs1, i32), uimm5:$shamt), 1461349cc55cSDimitry Andric (SRAIW GPR:$rs1, uimm5:$shamt)>; 1462349cc55cSDimitry Andric 14630b57cec5SDimitry Andric/// Loads 14640b57cec5SDimitry Andric 1465fe6060f1SDimitry Andricdefm : LdPat<sextloadi32, LW, i64>; 1466fe6060f1SDimitry Andricdefm : LdPat<extloadi32, LW, i64>; 1467fe6060f1SDimitry Andricdefm : LdPat<zextloadi32, LWU, i64>; 1468fe6060f1SDimitry Andricdefm : LdPat<load, LD, i64>; 14690b57cec5SDimitry Andric 14700b57cec5SDimitry Andric/// Stores 14710b57cec5SDimitry Andric 1472fe6060f1SDimitry Andricdefm : StPat<truncstorei32, SW, GPR, i64>; 1473fe6060f1SDimitry Andricdefm : StPat<store, SD, GPR, i64>; 14740b57cec5SDimitry Andric} // Predicates = [IsRV64] 14750b57cec5SDimitry Andric 14760b57cec5SDimitry Andric/// readcyclecounter 14770b57cec5SDimitry Andric// On RV64, we can directly read the 64-bit "cycle" CSR. 14780b57cec5SDimitry Andriclet Predicates = [IsRV64] in 1479fe6060f1SDimitry Andricdef : Pat<(i64 (readcyclecounter)), (CSRRS CYCLE.Encoding, X0)>; 14800b57cec5SDimitry Andric// On RV32, ReadCycleWide will be expanded to the suggested loop reading both 14810b57cec5SDimitry Andric// halves of the 64-bit "cycle" CSR. 1482e8d8bef9SDimitry Andriclet Predicates = [IsRV32], usesCustomInserter = 1, hasNoSchedulingInfo = 1 in 1483e8d8bef9SDimitry Andricdef ReadCycleWide : Pseudo<(outs GPR:$lo, GPR:$hi), (ins), 1484e8d8bef9SDimitry Andric [(set GPR:$lo, GPR:$hi, (riscv_read_cycle_wide))], 1485e8d8bef9SDimitry Andric "", "">; 14860b57cec5SDimitry Andric 1487480093f4SDimitry Andric/// traps 1488480093f4SDimitry Andric 1489480093f4SDimitry Andric// We lower `trap` to `unimp`, as this causes a hard exception on nearly all 1490480093f4SDimitry Andric// systems. 1491480093f4SDimitry Andricdef : Pat<(trap), (UNIMP)>; 1492480093f4SDimitry Andric 1493480093f4SDimitry Andric// We lower `debugtrap` to `ebreak`, as this will get the attention of the 1494480093f4SDimitry Andric// debugger if possible. 1495480093f4SDimitry Andricdef : Pat<(debugtrap), (EBREAK)>; 1496480093f4SDimitry Andric 1497fe6060f1SDimitry Andric/// Simple optimization 1498fe6060f1SDimitry Andricdef : Pat<(add GPR:$rs1, (AddiPair:$rs2)), 1499fe6060f1SDimitry Andric (ADDI (ADDI GPR:$rs1, (AddiPairImmB AddiPair:$rs2)), 1500fe6060f1SDimitry Andric (AddiPairImmA GPR:$rs2))>; 1501fe6060f1SDimitry Andric 1502fe6060f1SDimitry Andriclet Predicates = [IsRV64] in { 1503349cc55cSDimitry Andric// Select W instructions if only the lower 32-bits of the result are used. 1504349cc55cSDimitry Andricdef : Pat<(binop_allwusers<add> GPR:$rs1, (AddiPair:$rs2)), 1505fe6060f1SDimitry Andric (ADDIW (ADDIW GPR:$rs1, (AddiPairImmB AddiPair:$rs2)), 1506fe6060f1SDimitry Andric (AddiPairImmA AddiPair:$rs2))>; 1507fe6060f1SDimitry Andric} 1508fe6060f1SDimitry Andric 15090b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 15100b57cec5SDimitry Andric// Standard extensions 15110b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 15120b57cec5SDimitry Andric 15130b57cec5SDimitry Andricinclude "RISCVInstrInfoM.td" 15140b57cec5SDimitry Andricinclude "RISCVInstrInfoA.td" 15150b57cec5SDimitry Andricinclude "RISCVInstrInfoF.td" 15160b57cec5SDimitry Andricinclude "RISCVInstrInfoD.td" 15170b57cec5SDimitry Andricinclude "RISCVInstrInfoC.td" 1518349cc55cSDimitry Andricinclude "RISCVInstrInfoZb.td" 151904eeddc0SDimitry Andricinclude "RISCVInstrInfoZk.td" 15205ffd83dbSDimitry Andricinclude "RISCVInstrInfoV.td" 1521e8d8bef9SDimitry Andricinclude "RISCVInstrInfoZfh.td" 1522