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