1//== LoongArchInstrInfo.td - Target Description for LoongArch -*- tablegen -*-// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file describes the LoongArch instructions in TableGen format. 10// 11//===----------------------------------------------------------------------===// 12 13//===----------------------------------------------------------------------===// 14// LoongArch specific DAG Nodes. 15//===----------------------------------------------------------------------===// 16 17// Target-independent type requirements, but with target-specific formats. 18def SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, 19 SDTCisVT<1, i32>]>; 20def SDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, 21 SDTCisVT<1, i32>]>; 22 23// Target-dependent type requirements. 24def SDT_LoongArchCall : SDTypeProfile<0, -1, [SDTCisVT<0, GRLenVT>]>; 25def SDT_LoongArchIntBinOpW : SDTypeProfile<1, 2, [ 26 SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64> 27]>; 28 29def SDT_LoongArchBStrIns: SDTypeProfile<1, 4, [ 30 SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<3>, 31 SDTCisSameAs<3, 4> 32]>; 33 34def SDT_LoongArchBStrPick: SDTypeProfile<1, 3, [ 35 SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisInt<2>, SDTCisSameAs<2, 3> 36]>; 37 38// "VI" means no output and an integer input. 39def SDT_LoongArchVI : SDTypeProfile<0, 1, [SDTCisVT<0, GRLenVT>]>; 40 41def SDT_LoongArchCsrrd : SDTypeProfile<1, 1, [SDTCisInt<0>, 42 SDTCisVT<1, GRLenVT>]>; 43def SDT_LoongArchCsrwr : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>, 44 SDTCisVT<2, GRLenVT>]>; 45def SDT_LoongArchCsrxchg : SDTypeProfile<1, 3, [SDTCisInt<0>, 46 SDTCisSameAs<0, 1>, 47 SDTCisSameAs<0, 2>, 48 SDTCisVT<3, GRLenVT>]>; 49def SDT_LoongArchIocsrwr : SDTypeProfile<0, 2, [SDTCisInt<0>, 50 SDTCisSameAs<0, 1>]>; 51def SDT_LoongArchMovgr2fcsr : SDTypeProfile<0, 2, [SDTCisVT<0, GRLenVT>, 52 SDTCisSameAs<0, 1>]>; 53def SDT_LoongArchMovfcsr2gr : SDTypeProfile<1, 1, [SDTCisVT<0, GRLenVT>, 54 SDTCisSameAs<0, 1>]>; 55 56// TODO: Add LoongArch specific DAG Nodes 57// Target-independent nodes, but with target-specific formats. 58def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart, 59 [SDNPHasChain, SDNPOutGlue]>; 60def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd, 61 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; 62 63// Target-dependent nodes. 64def loongarch_call : SDNode<"LoongArchISD::CALL", SDT_LoongArchCall, 65 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 66 SDNPVariadic]>; 67def loongarch_ret : SDNode<"LoongArchISD::RET", SDTNone, 68 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; 69def loongarch_tail : SDNode<"LoongArchISD::TAIL", SDT_LoongArchCall, 70 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 71 SDNPVariadic]>; 72def loongarch_sll_w : SDNode<"LoongArchISD::SLL_W", SDT_LoongArchIntBinOpW>; 73def loongarch_sra_w : SDNode<"LoongArchISD::SRA_W", SDT_LoongArchIntBinOpW>; 74def loongarch_srl_w : SDNode<"LoongArchISD::SRL_W", SDT_LoongArchIntBinOpW>; 75def loongarch_rotr_w : SDNode<"LoongArchISD::ROTR_W", SDT_LoongArchIntBinOpW>; 76def loongarch_rotl_w : SDNode<"LoongArchISD::ROTL_W", SDT_LoongArchIntBinOpW>; 77def loongarch_crc_w_b_w 78 : SDNode<"LoongArchISD::CRC_W_B_W", SDT_LoongArchIntBinOpW>; 79def loongarch_crc_w_h_w 80 : SDNode<"LoongArchISD::CRC_W_H_W", SDT_LoongArchIntBinOpW>; 81def loongarch_crc_w_w_w 82 : SDNode<"LoongArchISD::CRC_W_W_W", SDT_LoongArchIntBinOpW>; 83def loongarch_crc_w_d_w 84 : SDNode<"LoongArchISD::CRC_W_D_W", SDT_LoongArchIntBinOpW>; 85def loongarch_crcc_w_b_w 86 : SDNode<"LoongArchISD::CRCC_W_B_W", SDT_LoongArchIntBinOpW>; 87def loongarch_crcc_w_h_w 88 : SDNode<"LoongArchISD::CRCC_W_H_W", SDT_LoongArchIntBinOpW>; 89def loongarch_crcc_w_w_w 90 : SDNode<"LoongArchISD::CRCC_W_W_W", SDT_LoongArchIntBinOpW>; 91def loongarch_crcc_w_d_w 92 : SDNode<"LoongArchISD::CRCC_W_D_W", SDT_LoongArchIntBinOpW>; 93def loongarch_bstrins 94 : SDNode<"LoongArchISD::BSTRINS", SDT_LoongArchBStrIns>; 95def loongarch_bstrpick 96 : SDNode<"LoongArchISD::BSTRPICK", SDT_LoongArchBStrPick>; 97def loongarch_revb_2h : SDNode<"LoongArchISD::REVB_2H", SDTUnaryOp>; 98def loongarch_revb_2w : SDNode<"LoongArchISD::REVB_2W", SDTUnaryOp>; 99def loongarch_bitrev_4b : SDNode<"LoongArchISD::BITREV_4B", SDTUnaryOp>; 100def loongarch_bitrev_w : SDNode<"LoongArchISD::BITREV_W", SDTUnaryOp>; 101def loongarch_clzw : SDNode<"LoongArchISD::CLZ_W", SDTIntBitCountUnaryOp>; 102def loongarch_ctzw : SDNode<"LoongArchISD::CTZ_W", SDTIntBitCountUnaryOp>; 103def loongarch_dbar : SDNode<"LoongArchISD::DBAR", SDT_LoongArchVI, 104 [SDNPHasChain, SDNPSideEffect]>; 105def loongarch_ibar : SDNode<"LoongArchISD::IBAR", SDT_LoongArchVI, 106 [SDNPHasChain, SDNPSideEffect]>; 107def loongarch_break : SDNode<"LoongArchISD::BREAK", SDT_LoongArchVI, 108 [SDNPHasChain, SDNPSideEffect]>; 109def loongarch_movfcsr2gr : SDNode<"LoongArchISD::MOVFCSR2GR", SDT_LoongArchMovfcsr2gr>; 110def loongarch_movgr2fcsr : SDNode<"LoongArchISD::MOVGR2FCSR", SDT_LoongArchMovgr2fcsr, 111 [SDNPHasChain, SDNPSideEffect]>; 112def loongarch_syscall : SDNode<"LoongArchISD::SYSCALL", SDT_LoongArchVI, 113 [SDNPHasChain, SDNPSideEffect]>; 114def loongarch_csrrd : SDNode<"LoongArchISD::CSRRD", SDT_LoongArchCsrrd, 115 [SDNPHasChain, SDNPSideEffect]>; 116def loongarch_csrwr : SDNode<"LoongArchISD::CSRWR", SDT_LoongArchCsrwr, 117 [SDNPHasChain, SDNPSideEffect]>; 118def loongarch_csrxchg : SDNode<"LoongArchISD::CSRXCHG", 119 SDT_LoongArchCsrxchg, 120 [SDNPHasChain, SDNPSideEffect]>; 121def loongarch_iocsrrd_b : SDNode<"LoongArchISD::IOCSRRD_B", SDTUnaryOp, 122 [SDNPHasChain, SDNPSideEffect]>; 123def loongarch_iocsrrd_h : SDNode<"LoongArchISD::IOCSRRD_H", SDTUnaryOp, 124 [SDNPHasChain, SDNPSideEffect]>; 125def loongarch_iocsrrd_w : SDNode<"LoongArchISD::IOCSRRD_W", SDTUnaryOp, 126 [SDNPHasChain, SDNPSideEffect]>; 127def loongarch_iocsrrd_d : SDNode<"LoongArchISD::IOCSRRD_D", SDTUnaryOp, 128 [SDNPHasChain, SDNPSideEffect]>; 129def loongarch_iocsrwr_b : SDNode<"LoongArchISD::IOCSRWR_B", 130 SDT_LoongArchIocsrwr, 131 [SDNPHasChain, SDNPSideEffect]>; 132def loongarch_iocsrwr_h : SDNode<"LoongArchISD::IOCSRWR_H", 133 SDT_LoongArchIocsrwr, 134 [SDNPHasChain, SDNPSideEffect]>; 135def loongarch_iocsrwr_w : SDNode<"LoongArchISD::IOCSRWR_W", 136 SDT_LoongArchIocsrwr, 137 [SDNPHasChain, SDNPSideEffect]>; 138def loongarch_iocsrwr_d : SDNode<"LoongArchISD::IOCSRWR_D", 139 SDT_LoongArchIocsrwr, 140 [SDNPHasChain, SDNPSideEffect]>; 141def loongarch_cpucfg : SDNode<"LoongArchISD::CPUCFG", SDTUnaryOp, 142 [SDNPHasChain, SDNPSideEffect]>; 143 144//===----------------------------------------------------------------------===// 145// Operand and SDNode transformation definitions. 146//===----------------------------------------------------------------------===// 147 148class ImmAsmOperand<string prefix, int width, string suffix> 149 : AsmOperandClass { 150 let Name = prefix # "Imm" # width # suffix; 151 let DiagnosticType = !strconcat("Invalid", Name); 152 let RenderMethod = "addImmOperands"; 153} 154 155class SImmAsmOperand<int width, string suffix = ""> 156 : ImmAsmOperand<"S", width, suffix> { 157} 158 159class UImmAsmOperand<int width, string suffix = ""> 160 : ImmAsmOperand<"U", width, suffix> { 161} 162 163// A parse method for "$r*" or "$r*, 0", where the 0 is be silently ignored. 164// Only used for "AM*" instructions, in order to be compatible with GAS. 165def AtomicMemAsmOperand : AsmOperandClass { 166 let Name = "AtomicMemAsmOperand"; 167 let RenderMethod = "addRegOperands"; 168 let PredicateMethod = "isGPR"; 169 let ParserMethod = "parseAtomicMemOp"; 170} 171 172def GPRMemAtomic : RegisterOperand<GPR> { 173 let ParserMatchClass = AtomicMemAsmOperand; 174 let PrintMethod = "printAtomicMemOp"; 175} 176 177// A parameterized register class alternative to i32imm/i64imm from Target.td. 178def grlenimm : Operand<GRLenVT>; 179def imm32 : Operand<GRLenVT> { 180 let ParserMatchClass = ImmAsmOperand<"", 32, "">; 181} 182 183def uimm2 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<2>(Imm);}]> { 184 let ParserMatchClass = UImmAsmOperand<2>; 185} 186 187def uimm2_plus1 : Operand<GRLenVT>, 188 ImmLeaf<GRLenVT, [{return isUInt<2>(Imm - 1);}]> { 189 let ParserMatchClass = UImmAsmOperand<2, "plus1">; 190 let EncoderMethod = "getImmOpValueSub1"; 191 let DecoderMethod = "decodeUImmOperand<2, 1>"; 192} 193 194def uimm3 : Operand<GRLenVT> { 195 let ParserMatchClass = UImmAsmOperand<3>; 196} 197 198def uimm5 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<5>(Imm);}]> { 199 let ParserMatchClass = UImmAsmOperand<5>; 200} 201 202def uimm6 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<6>(Imm);}]> { 203 let ParserMatchClass = UImmAsmOperand<6>; 204} 205 206def uimm8 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<8>(Imm);}]> { 207 let ParserMatchClass = UImmAsmOperand<8>; 208} 209 210class UImm12Operand : Operand<GRLenVT>, 211 ImmLeaf <GRLenVT, [{return isUInt<12>(Imm);}]> { 212 let DecoderMethod = "decodeUImmOperand<12>"; 213} 214 215def uimm12 : UImm12Operand { 216 let ParserMatchClass = UImmAsmOperand<12>; 217} 218 219def uimm12_ori : UImm12Operand { 220 let ParserMatchClass = UImmAsmOperand<12, "ori">; 221} 222 223def uimm14 : Operand<GRLenVT>, 224 ImmLeaf <GRLenVT, [{return isUInt<14>(Imm);}]> { 225 let ParserMatchClass = UImmAsmOperand<14>; 226} 227 228def uimm15 : Operand<GRLenVT>, 229 ImmLeaf <GRLenVT, [{return isUInt<15>(Imm);}]> { 230 let ParserMatchClass = UImmAsmOperand<15>; 231} 232 233class SImm12Operand : Operand<GRLenVT>, 234 ImmLeaf <GRLenVT, [{return isInt<12>(Imm);}]> { 235 let DecoderMethod = "decodeSImmOperand<12>"; 236} 237 238def simm12 : SImm12Operand { 239 let ParserMatchClass = SImmAsmOperand<12>; 240} 241 242def simm12_addlike : SImm12Operand { 243 let ParserMatchClass = SImmAsmOperand<12, "addlike">; 244} 245 246def simm12_lu52id : SImm12Operand { 247 let ParserMatchClass = SImmAsmOperand<12, "lu52id">; 248} 249 250def simm14_lsl2 : Operand<GRLenVT>, 251 ImmLeaf<GRLenVT, [{return isShiftedInt<14,2>(Imm);}]> { 252 let ParserMatchClass = SImmAsmOperand<14, "lsl2">; 253 let EncoderMethod = "getImmOpValueAsr2"; 254 let DecoderMethod = "decodeSImmOperand<14, 2>"; 255} 256 257def simm16 : Operand<GRLenVT> { 258 let ParserMatchClass = SImmAsmOperand<16>; 259 let DecoderMethod = "decodeSImmOperand<16>"; 260} 261 262def simm16_lsl2 : Operand<GRLenVT>, 263 ImmLeaf<GRLenVT, [{return isInt<16>(Imm>>2);}]> { 264 let ParserMatchClass = SImmAsmOperand<16, "lsl2">; 265 let EncoderMethod = "getImmOpValueAsr2"; 266 let DecoderMethod = "decodeSImmOperand<16, 2>"; 267} 268 269def simm16_lsl2_br : Operand<OtherVT> { 270 let ParserMatchClass = SImmAsmOperand<16, "lsl2">; 271 let EncoderMethod = "getImmOpValueAsr2"; 272 let DecoderMethod = "decodeSImmOperand<16, 2>"; 273} 274 275class SImm20Operand : Operand<GRLenVT> { 276 let DecoderMethod = "decodeSImmOperand<20>"; 277} 278 279def simm20 : SImm20Operand { 280 let ParserMatchClass = SImmAsmOperand<20>; 281} 282 283def simm20_pcalau12i : SImm20Operand { 284 let ParserMatchClass = SImmAsmOperand<20, "pcalau12i">; 285} 286 287def simm20_lu12iw : SImm20Operand { 288 let ParserMatchClass = SImmAsmOperand<20, "lu12iw">; 289} 290 291def simm20_lu32id : SImm20Operand { 292 let ParserMatchClass = SImmAsmOperand<20, "lu32id">; 293} 294 295def simm21_lsl2 : Operand<OtherVT> { 296 let ParserMatchClass = SImmAsmOperand<21, "lsl2">; 297 let EncoderMethod = "getImmOpValueAsr2"; 298 let DecoderMethod = "decodeSImmOperand<21, 2>"; 299} 300 301def SImm26OperandB: AsmOperandClass { 302 let Name = "SImm26OperandB"; 303 let PredicateMethod = "isSImm26Operand"; 304 let RenderMethod = "addImmOperands"; 305 let DiagnosticType = "InvalidSImm26Operand"; 306 let ParserMethod = "parseImmediate"; 307} 308 309// A symbol or an imm used in B/PseudoBR. 310def simm26_b : Operand<OtherVT> { 311 let ParserMatchClass = SImm26OperandB; 312 let EncoderMethod = "getImmOpValueAsr2"; 313 let DecoderMethod = "decodeSImmOperand<26, 2>"; 314} 315 316def SImm26OperandBL: AsmOperandClass { 317 let Name = "SImm26OperandBL"; 318 let PredicateMethod = "isSImm26Operand"; 319 let RenderMethod = "addImmOperands"; 320 let DiagnosticType = "InvalidSImm26Operand"; 321 let ParserMethod = "parseSImm26Operand"; 322} 323 324// A symbol or an imm used in BL/PseudoCALL/PseudoTAIL. 325def simm26_symbol : Operand<GRLenVT> { 326 let ParserMatchClass = SImm26OperandBL; 327 let EncoderMethod = "getImmOpValueAsr2"; 328 let DecoderMethod = "decodeSImmOperand<26, 2>"; 329} 330 331def BareSymbol : AsmOperandClass { 332 let Name = "BareSymbol"; 333 let RenderMethod = "addImmOperands"; 334 let DiagnosticType = "InvalidBareSymbol"; 335 let ParserMethod = "parseImmediate"; 336} 337 338// A bare symbol used in "PseudoLA_*" instructions. 339def bare_symbol : Operand<GRLenVT> { 340 let ParserMatchClass = BareSymbol; 341} 342 343// Standalone (codegen-only) immleaf patterns. 344 345// A 12-bit signed immediate plus one where the imm range will be [-2047, 2048]. 346def simm12_plus1 : ImmLeaf<GRLenVT, 347 [{return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048;}]>; 348 349// Return the negation of an immediate value. 350def NegImm : SDNodeXForm<imm, [{ 351 return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N), 352 N->getValueType(0)); 353}]>; 354 355// FP immediate patterns. 356def fpimm0 : PatLeaf<(fpimm), [{return N->isExactlyValue(+0.0);}]>; 357def fpimm0neg : PatLeaf<(fpimm), [{return N->isExactlyValue(-0.0);}]>; 358def fpimm1 : PatLeaf<(fpimm), [{return N->isExactlyValue(+1.0);}]>; 359 360// Return an immediate subtracted from 32. 361def ImmSubFrom32 : SDNodeXForm<imm, [{ 362 return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N), 363 N->getValueType(0)); 364}]>; 365 366def BaseAddr : ComplexPattern<iPTR, 1, "SelectBaseAddr">; 367def NonFIBaseAddr : ComplexPattern<iPTR, 1, "selectNonFIBaseAddr">; 368 369def fma_nsz : PatFrag<(ops node:$fj, node:$fk, node:$fa), 370 (fma node:$fj, node:$fk, node:$fa), [{ 371 return N->getFlags().hasNoSignedZeros(); 372}]>; 373 374//===----------------------------------------------------------------------===// 375// Instruction Formats 376//===----------------------------------------------------------------------===// 377 378include "LoongArchInstrFormats.td" 379include "LoongArchFloatInstrFormats.td" 380 381//===----------------------------------------------------------------------===// 382// Instruction Class Templates 383//===----------------------------------------------------------------------===// 384 385class ALU_3R<bits<17> op, string opstr> 386 : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), opstr, "$rd, $rj, $rk">; 387class ALU_2R<bits<22> op, string opstr> 388 : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), opstr, "$rd, $rj">; 389 390class ALU_3RI2<bits<15> op, string opstr, Operand ImmOpnd> 391 : Fmt3RI2<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk, ImmOpnd:$imm2), opstr, 392 "$rd, $rj, $rk, $imm2">; 393class ALU_3RI3<bits<14> op, string opstr, Operand ImmOpnd> 394 : Fmt3RI3<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk, ImmOpnd:$imm3), opstr, 395 "$rd, $rj, $rk, $imm3">; 396class ALU_2RI5<bits<17> op, string opstr, Operand ImmOpnd> 397 : Fmt2RI5<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm5), opstr, 398 "$rd, $rj, $imm5">; 399class ALU_2RI6<bits<16> op, string opstr, Operand ImmOpnd> 400 : Fmt2RI6<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm6), opstr, 401 "$rd, $rj, $imm6">; 402class ALU_2RI12<bits<10> op, string opstr, Operand ImmOpnd> 403 : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm12), opstr, 404 "$rd, $rj, $imm12">; 405class ALU_2RI16<bits<6> op, string opstr, Operand ImmOpnd> 406 : Fmt2RI16<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm16), opstr, 407 "$rd, $rj, $imm16">; 408class ALU_1RI20<bits<7> op, string opstr, Operand ImmOpnd> 409 : Fmt1RI20<op, (outs GPR:$rd), (ins ImmOpnd:$imm20), opstr, "$rd, $imm20">; 410 411class MISC_I15<bits<17> op, string opstr> 412 : FmtI15<op, (outs), (ins uimm15:$imm15), opstr, "$imm15">; 413 414class RDTIME_2R<bits<22> op, string opstr> 415 : Fmt2R<op, (outs GPR:$rd, GPR:$rj), (ins), opstr, "$rd, $rj">; 416 417class BrCC_2RI16<bits<6> op, string opstr> 418 : Fmt2RI16<op, (outs), (ins GPR:$rj, GPR:$rd, simm16_lsl2_br:$imm16), opstr, 419 "$rj, $rd, $imm16"> { 420 let isBranch = 1; 421 let isTerminator = 1; 422} 423class BrCCZ_1RI21<bits<6> op, string opstr> 424 : Fmt1RI21<op, (outs), (ins GPR:$rj, simm21_lsl2:$imm21), opstr, 425 "$rj, $imm21"> { 426 let isBranch = 1; 427 let isTerminator = 1; 428} 429class Br_I26<bits<6> op, string opstr> 430 : FmtI26<op, (outs), (ins simm26_b:$imm26), opstr, "$imm26"> { 431 let isBranch = 1; 432 let isTerminator = 1; 433} 434 435let mayLoad = 1 in { 436class LOAD_3R<bits<17> op, string opstr> 437 : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), opstr, "$rd, $rj, $rk">; 438class LOAD_2RI12<bits<10> op, string opstr> 439 : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, simm12_addlike:$imm12), opstr, 440 "$rd, $rj, $imm12">; 441class LOAD_2RI14<bits<8> op, string opstr> 442 : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14), opstr, 443 "$rd, $rj, $imm14">; 444} // mayLoad = 1 445 446let mayStore = 1 in { 447class STORE_3R<bits<17> op, string opstr> 448 : Fmt3R<op, (outs), (ins GPR:$rd, GPR:$rj, GPR:$rk), opstr, 449 "$rd, $rj, $rk">; 450class STORE_2RI12<bits<10> op, string opstr> 451 : Fmt2RI12<op, (outs), (ins GPR:$rd, GPR:$rj, simm12_addlike:$imm12), opstr, 452 "$rd, $rj, $imm12">; 453class STORE_2RI14<bits<8> op, string opstr> 454 : Fmt2RI14<op, (outs), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14), opstr, 455 "$rd, $rj, $imm14">; 456} // mayStore = 1 457 458let mayLoad = 1, mayStore = 1, Constraints = "@earlyclobber $rd" in 459class AM_3R<bits<17> op, string opstr> 460 : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rk, GPRMemAtomic:$rj), opstr, 461 "$rd, $rk, $rj">; 462 463let mayLoad = 1 in 464class LLBase<bits<8> op, string opstr> 465 : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14), opstr, 466 "$rd, $rj, $imm14">; 467 468let mayStore = 1, Constraints = "$rd = $dst" in 469class SCBase<bits<8> op, string opstr> 470 : Fmt2RI14<op, (outs GPR:$dst), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14), 471 opstr, "$rd, $rj, $imm14">; 472 473class IOCSRRD<bits<22> op, string opstr> 474 : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), opstr, "$rd, $rj">; 475 476class IOCSRWR<bits<22> op, string opstr> 477 : Fmt2R<op, (outs), (ins GPR:$rd, GPR:$rj), opstr, "$rd, $rj">; 478 479//===----------------------------------------------------------------------===// 480// Basic Integer Instructions 481//===----------------------------------------------------------------------===// 482 483// Arithmetic Operation Instructions 484def ADD_W : ALU_3R<0b00000000000100000, "add.w">; 485def SUB_W : ALU_3R<0b00000000000100010, "sub.w">; 486def ADDI_W : ALU_2RI12<0b0000001010, "addi.w", simm12_addlike>; 487def ALSL_W : ALU_3RI2<0b000000000000010, "alsl.w", uimm2_plus1>; 488def LU12I_W : ALU_1RI20<0b0001010, "lu12i.w", simm20_lu12iw>; 489def SLT : ALU_3R<0b00000000000100100, "slt">; 490def SLTU : ALU_3R<0b00000000000100101, "sltu">; 491def SLTI : ALU_2RI12<0b0000001000, "slti", simm12>; 492def SLTUI : ALU_2RI12<0b0000001001, "sltui", simm12>; 493def PCADDI : ALU_1RI20<0b0001100, "pcaddi", simm20>; 494def PCADDU12I : ALU_1RI20<0b0001110, "pcaddu12i", simm20>; 495def PCALAU12I : ALU_1RI20<0b0001101, "pcalau12i", simm20_pcalau12i>; 496def AND : ALU_3R<0b00000000000101001, "and">; 497def OR : ALU_3R<0b00000000000101010, "or">; 498def NOR : ALU_3R<0b00000000000101000, "nor">; 499def XOR : ALU_3R<0b00000000000101011, "xor">; 500def ANDN : ALU_3R<0b00000000000101101, "andn">; 501def ORN : ALU_3R<0b00000000000101100, "orn">; 502def ANDI : ALU_2RI12<0b0000001101, "andi", uimm12>; 503def ORI : ALU_2RI12<0b0000001110, "ori", uimm12_ori>; 504def XORI : ALU_2RI12<0b0000001111, "xori", uimm12>; 505def MUL_W : ALU_3R<0b00000000000111000, "mul.w">; 506def MULH_W : ALU_3R<0b00000000000111001, "mulh.w">; 507def MULH_WU : ALU_3R<0b00000000000111010, "mulh.wu">; 508let usesCustomInserter = true in { 509def DIV_W : ALU_3R<0b00000000001000000, "div.w">; 510def MOD_W : ALU_3R<0b00000000001000001, "mod.w">; 511def DIV_WU : ALU_3R<0b00000000001000010, "div.wu">; 512def MOD_WU : ALU_3R<0b00000000001000011, "mod.wu">; 513} // usesCustomInserter = true 514 515// Bit-shift Instructions 516def SLL_W : ALU_3R<0b00000000000101110, "sll.w">; 517def SRL_W : ALU_3R<0b00000000000101111, "srl.w">; 518def SRA_W : ALU_3R<0b00000000000110000, "sra.w">; 519def ROTR_W : ALU_3R<0b00000000000110110, "rotr.w">; 520 521def SLLI_W : ALU_2RI5<0b00000000010000001, "slli.w", uimm5>; 522def SRLI_W : ALU_2RI5<0b00000000010001001, "srli.w", uimm5>; 523def SRAI_W : ALU_2RI5<0b00000000010010001, "srai.w", uimm5>; 524def ROTRI_W : ALU_2RI5<0b00000000010011001, "rotri.w", uimm5>; 525 526// Bit-manipulation Instructions 527def EXT_W_B : ALU_2R<0b0000000000000000010111, "ext.w.b">; 528def EXT_W_H : ALU_2R<0b0000000000000000010110, "ext.w.h">; 529def CLO_W : ALU_2R<0b0000000000000000000100, "clo.w">; 530def CLZ_W : ALU_2R<0b0000000000000000000101, "clz.w">; 531def CTO_W : ALU_2R<0b0000000000000000000110, "cto.w">; 532def CTZ_W : ALU_2R<0b0000000000000000000111, "ctz.w">; 533def BYTEPICK_W : ALU_3RI2<0b000000000000100, "bytepick.w", uimm2>; 534def REVB_2H : ALU_2R<0b0000000000000000001100, "revb.2h">; 535def BITREV_4B : ALU_2R<0b0000000000000000010010, "bitrev.4b">; 536def BITREV_W : ALU_2R<0b0000000000000000010100, "bitrev.w">; 537let Constraints = "$rd = $dst" in { 538def BSTRINS_W : FmtBSTR_W<0b000000000110, (outs GPR:$dst), 539 (ins GPR:$rd, GPR:$rj, uimm5:$msbw, uimm5:$lsbw), 540 "bstrins.w", "$rd, $rj, $msbw, $lsbw">; 541} 542def BSTRPICK_W : FmtBSTR_W<0b000000000111, (outs GPR:$rd), 543 (ins GPR:$rj, uimm5:$msbw, uimm5:$lsbw), 544 "bstrpick.w", "$rd, $rj, $msbw, $lsbw">; 545def MASKEQZ : ALU_3R<0b00000000000100110, "maskeqz">; 546def MASKNEZ : ALU_3R<0b00000000000100111, "masknez">; 547 548// Branch Instructions 549def BEQ : BrCC_2RI16<0b010110, "beq">; 550def BNE : BrCC_2RI16<0b010111, "bne">; 551def BLT : BrCC_2RI16<0b011000, "blt">; 552def BGE : BrCC_2RI16<0b011001, "bge">; 553def BLTU : BrCC_2RI16<0b011010, "bltu">; 554def BGEU : BrCC_2RI16<0b011011, "bgeu">; 555def BEQZ : BrCCZ_1RI21<0b010000, "beqz">; 556def BNEZ : BrCCZ_1RI21<0b010001, "bnez">; 557def B : Br_I26<0b010100, "b">; 558 559let isCall = 1, Defs=[R1] in 560def BL : FmtI26<0b010101, (outs), (ins simm26_symbol:$imm26), "bl", "$imm26">; 561def JIRL : Fmt2RI16<0b010011, (outs GPR:$rd), 562 (ins GPR:$rj, simm16_lsl2:$imm16), "jirl", 563 "$rd, $rj, $imm16">; 564 565// Common Memory Access Instructions 566def LD_B : LOAD_2RI12<0b0010100000, "ld.b">; 567def LD_H : LOAD_2RI12<0b0010100001, "ld.h">; 568def LD_W : LOAD_2RI12<0b0010100010, "ld.w">; 569def LD_BU : LOAD_2RI12<0b0010101000, "ld.bu">; 570def LD_HU : LOAD_2RI12<0b0010101001, "ld.hu">; 571def ST_B : STORE_2RI12<0b0010100100, "st.b">; 572def ST_H : STORE_2RI12<0b0010100101, "st.h">; 573def ST_W : STORE_2RI12<0b0010100110, "st.w">; 574def PRELD : FmtPRELD<(outs), (ins uimm5:$imm5, GPR:$rj, simm12:$imm12), "preld", 575 "$imm5, $rj, $imm12">; 576 577// Atomic Memory Access Instructions 578def LL_W : LLBase<0b00100000, "ll.w">; 579def SC_W : SCBase<0b00100001, "sc.w">; 580 581// Barrier Instructions 582def DBAR : MISC_I15<0b00111000011100100, "dbar">; 583def IBAR : MISC_I15<0b00111000011100101, "ibar">; 584 585// Other Miscellaneous Instructions 586def SYSCALL : MISC_I15<0b00000000001010110, "syscall">; 587def BREAK : MISC_I15<0b00000000001010100, "break">; 588def RDTIMEL_W : RDTIME_2R<0b0000000000000000011000, "rdtimel.w">; 589def RDTIMEH_W : RDTIME_2R<0b0000000000000000011001, "rdtimeh.w">; 590def CPUCFG : ALU_2R<0b0000000000000000011011, "cpucfg">; 591 592// Cache Maintenance Instructions 593def CACOP : FmtCACOP<(outs), (ins uimm5:$op, GPR:$rj, simm12:$imm12), "cacop", 594 "$op, $rj, $imm12">; 595 596/// LA64 instructions 597 598let Predicates = [IsLA64] in { 599 600// Arithmetic Operation Instructions for 64-bits 601def ADD_D : ALU_3R<0b00000000000100001, "add.d">; 602def SUB_D : ALU_3R<0b00000000000100011, "sub.d">; 603def ADDI_D : ALU_2RI12<0b0000001011, "addi.d", simm12_addlike>; 604def ADDU16I_D : ALU_2RI16<0b000100, "addu16i.d", simm16>; 605def ALSL_WU : ALU_3RI2<0b000000000000011, "alsl.wu", uimm2_plus1>; 606def ALSL_D : ALU_3RI2<0b000000000010110, "alsl.d", uimm2_plus1>; 607let Constraints = "$rd = $dst" in { 608def LU32I_D : Fmt1RI20<0b0001011, (outs GPR:$dst), 609 (ins GPR:$rd, simm20_lu32id:$imm20), "lu32i.d", 610 "$rd, $imm20">; 611} 612def LU52I_D : ALU_2RI12<0b0000001100, "lu52i.d", simm12_lu52id>; 613def PCADDU18I : ALU_1RI20<0b0001111, "pcaddu18i", simm20>; 614def MUL_D : ALU_3R<0b00000000000111011, "mul.d">; 615def MULH_D : ALU_3R<0b00000000000111100, "mulh.d">; 616def MULH_DU : ALU_3R<0b00000000000111101, "mulh.du">; 617def MULW_D_W : ALU_3R<0b00000000000111110, "mulw.d.w">; 618def MULW_D_WU : ALU_3R<0b00000000000111111, "mulw.d.wu">; 619let usesCustomInserter = true in { 620def DIV_D : ALU_3R<0b00000000001000100, "div.d">; 621def MOD_D : ALU_3R<0b00000000001000101, "mod.d">; 622def DIV_DU : ALU_3R<0b00000000001000110, "div.du">; 623def MOD_DU : ALU_3R<0b00000000001000111, "mod.du">; 624} // usesCustomInserter = true 625 626// Bit-shift Instructions for 64-bits 627def SLL_D : ALU_3R<0b00000000000110001, "sll.d">; 628def SRL_D : ALU_3R<0b00000000000110010, "srl.d">; 629def SRA_D : ALU_3R<0b00000000000110011, "sra.d">; 630def ROTR_D : ALU_3R<0b00000000000110111, "rotr.d">; 631def SLLI_D : ALU_2RI6<0b0000000001000001, "slli.d", uimm6>; 632def SRLI_D : ALU_2RI6<0b0000000001000101, "srli.d", uimm6>; 633def SRAI_D : ALU_2RI6<0b0000000001001001, "srai.d", uimm6>; 634def ROTRI_D : ALU_2RI6<0b0000000001001101, "rotri.d", uimm6>; 635 636// Bit-manipulation Instructions for 64-bits 637def CLO_D : ALU_2R<0b0000000000000000001000, "clo.d">; 638def CLZ_D : ALU_2R<0b0000000000000000001001, "clz.d">; 639def CTO_D : ALU_2R<0b0000000000000000001010, "cto.d">; 640def CTZ_D : ALU_2R<0b0000000000000000001011, "ctz.d">; 641def BYTEPICK_D : ALU_3RI3<0b00000000000011, "bytepick.d", uimm3>; 642def REVB_4H : ALU_2R<0b0000000000000000001101, "revb.4h">; 643def REVB_2W : ALU_2R<0b0000000000000000001110, "revb.2w">; 644def REVB_D : ALU_2R<0b0000000000000000001111, "revb.d">; 645def REVH_2W : ALU_2R<0b0000000000000000010000, "revh.2w">; 646def REVH_D : ALU_2R<0b0000000000000000010001, "revh.d">; 647def BITREV_8B : ALU_2R<0b0000000000000000010011, "bitrev.8b">; 648def BITREV_D : ALU_2R<0b0000000000000000010101, "bitrev.d">; 649let Constraints = "$rd = $dst" in { 650def BSTRINS_D : FmtBSTR_D<0b0000000010, (outs GPR:$dst), 651 (ins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd), 652 "bstrins.d", "$rd, $rj, $msbd, $lsbd">; 653} 654def BSTRPICK_D : FmtBSTR_D<0b0000000011, (outs GPR:$rd), 655 (ins GPR:$rj, uimm6:$msbd, uimm6:$lsbd), 656 "bstrpick.d", "$rd, $rj, $msbd, $lsbd">; 657 658// Common Memory Access Instructions for 64-bits 659def LD_WU : LOAD_2RI12<0b0010101010, "ld.wu">; 660def LD_D : LOAD_2RI12<0b0010100011, "ld.d">; 661def ST_D : STORE_2RI12<0b0010100111, "st.d">; 662def LDX_B : LOAD_3R<0b00111000000000000, "ldx.b">; 663def LDX_H : LOAD_3R<0b00111000000001000, "ldx.h">; 664def LDX_W : LOAD_3R<0b00111000000010000, "ldx.w">; 665def LDX_D : LOAD_3R<0b00111000000011000, "ldx.d">; 666def LDX_BU : LOAD_3R<0b00111000001000000, "ldx.bu">; 667def LDX_HU : LOAD_3R<0b00111000001001000, "ldx.hu">; 668def LDX_WU : LOAD_3R<0b00111000001010000, "ldx.wu">; 669def STX_B : STORE_3R<0b00111000000100000, "stx.b">; 670def STX_H : STORE_3R<0b00111000000101000, "stx.h">; 671def STX_W : STORE_3R<0b00111000000110000, "stx.w">; 672def STX_D : STORE_3R<0b00111000000111000, "stx.d">; 673def LDPTR_W : LOAD_2RI14<0b00100100, "ldptr.w">; 674def LDPTR_D : LOAD_2RI14<0b00100110, "ldptr.d">; 675def STPTR_W : STORE_2RI14<0b00100101, "stptr.w">; 676def STPTR_D : STORE_2RI14<0b00100111, "stptr.d">; 677def PRELDX : FmtPRELDX<(outs), (ins uimm5:$imm5, GPR:$rj, GPR:$rk), "preldx", 678 "$imm5, $rj, $rk">; 679 680// Bound Check Memory Access Instructions 681def LDGT_B : LOAD_3R<0b00111000011110000, "ldgt.b">; 682def LDGT_H : LOAD_3R<0b00111000011110001, "ldgt.h">; 683def LDGT_W : LOAD_3R<0b00111000011110010, "ldgt.w">; 684def LDGT_D : LOAD_3R<0b00111000011110011, "ldgt.d">; 685def LDLE_B : LOAD_3R<0b00111000011110100, "ldle.b">; 686def LDLE_H : LOAD_3R<0b00111000011110101, "ldle.h">; 687def LDLE_W : LOAD_3R<0b00111000011110110, "ldle.w">; 688def LDLE_D : LOAD_3R<0b00111000011110111, "ldle.d">; 689def STGT_B : STORE_3R<0b00111000011111000, "stgt.b">; 690def STGT_H : STORE_3R<0b00111000011111001, "stgt.h">; 691def STGT_W : STORE_3R<0b00111000011111010, "stgt.w">; 692def STGT_D : STORE_3R<0b00111000011111011, "stgt.d">; 693def STLE_B : STORE_3R<0b00111000011111100, "stle.b">; 694def STLE_H : STORE_3R<0b00111000011111101, "stle.h">; 695def STLE_W : STORE_3R<0b00111000011111110, "stle.w">; 696def STLE_D : STORE_3R<0b00111000011111111, "stle.d">; 697 698// Atomic Memory Access Instructions for 64-bits 699def AMSWAP_W : AM_3R<0b00111000011000000, "amswap.w">; 700def AMSWAP_D : AM_3R<0b00111000011000001, "amswap.d">; 701def AMADD_W : AM_3R<0b00111000011000010, "amadd.w">; 702def AMADD_D : AM_3R<0b00111000011000011, "amadd.d">; 703def AMAND_W : AM_3R<0b00111000011000100, "amand.w">; 704def AMAND_D : AM_3R<0b00111000011000101, "amand.d">; 705def AMOR_W : AM_3R<0b00111000011000110, "amor.w">; 706def AMOR_D : AM_3R<0b00111000011000111, "amor.d">; 707def AMXOR_W : AM_3R<0b00111000011001000, "amxor.w">; 708def AMXOR_D : AM_3R<0b00111000011001001, "amxor.d">; 709def AMMAX_W : AM_3R<0b00111000011001010, "ammax.w">; 710def AMMAX_D : AM_3R<0b00111000011001011, "ammax.d">; 711def AMMIN_W : AM_3R<0b00111000011001100, "ammin.w">; 712def AMMIN_D : AM_3R<0b00111000011001101, "ammin.d">; 713def AMMAX_WU : AM_3R<0b00111000011001110, "ammax.wu">; 714def AMMAX_DU : AM_3R<0b00111000011001111, "ammax.du">; 715def AMMIN_WU : AM_3R<0b00111000011010000, "ammin.wu">; 716def AMMIN_DU : AM_3R<0b00111000011010001, "ammin.du">; 717def AMSWAP_DB_W : AM_3R<0b00111000011010010, "amswap_db.w">; 718def AMSWAP_DB_D : AM_3R<0b00111000011010011, "amswap_db.d">; 719def AMADD_DB_W : AM_3R<0b00111000011010100, "amadd_db.w">; 720def AMADD_DB_D : AM_3R<0b00111000011010101, "amadd_db.d">; 721def AMAND_DB_W : AM_3R<0b00111000011010110, "amand_db.w">; 722def AMAND_DB_D : AM_3R<0b00111000011010111, "amand_db.d">; 723def AMOR_DB_W : AM_3R<0b00111000011011000, "amor_db.w">; 724def AMOR_DB_D : AM_3R<0b00111000011011001, "amor_db.d">; 725def AMXOR_DB_W : AM_3R<0b00111000011011010, "amxor_db.w">; 726def AMXOR_DB_D : AM_3R<0b00111000011011011, "amxor_db.d">; 727def AMMAX_DB_W : AM_3R<0b00111000011011100, "ammax_db.w">; 728def AMMAX_DB_D : AM_3R<0b00111000011011101, "ammax_db.d">; 729def AMMIN_DB_W : AM_3R<0b00111000011011110, "ammin_db.w">; 730def AMMIN_DB_D : AM_3R<0b00111000011011111, "ammin_db.d">; 731def AMMAX_DB_WU : AM_3R<0b00111000011100000, "ammax_db.wu">; 732def AMMAX_DB_DU : AM_3R<0b00111000011100001, "ammax_db.du">; 733def AMMIN_DB_WU : AM_3R<0b00111000011100010, "ammin_db.wu">; 734def AMMIN_DB_DU : AM_3R<0b00111000011100011, "ammin_db.du">; 735def LL_D : LLBase<0b00100010, "ll.d">; 736def SC_D : SCBase<0b00100011, "sc.d">; 737 738// CRC Check Instructions 739def CRC_W_B_W : ALU_3R<0b00000000001001000, "crc.w.b.w">; 740def CRC_W_H_W : ALU_3R<0b00000000001001001, "crc.w.h.w">; 741def CRC_W_W_W : ALU_3R<0b00000000001001010, "crc.w.w.w">; 742def CRC_W_D_W : ALU_3R<0b00000000001001011, "crc.w.d.w">; 743def CRCC_W_B_W : ALU_3R<0b00000000001001100, "crcc.w.b.w">; 744def CRCC_W_H_W : ALU_3R<0b00000000001001101, "crcc.w.h.w">; 745def CRCC_W_W_W : ALU_3R<0b00000000001001110, "crcc.w.w.w">; 746def CRCC_W_D_W : ALU_3R<0b00000000001001111, "crcc.w.d.w">; 747 748// Other Miscellaneous Instructions for 64-bits 749def ASRTLE_D : FmtASRT<0b00000000000000010, (outs), (ins GPR:$rj, GPR:$rk), 750 "asrtle.d", "$rj, $rk">; 751def ASRTGT_D : FmtASRT<0b00000000000000011, (outs), (ins GPR:$rj, GPR:$rk), 752 "asrtgt.d", "$rj, $rk">; 753def RDTIME_D : RDTIME_2R<0b0000000000000000011010, "rdtime.d">; 754} // Predicates = [IsLA64] 755 756//===----------------------------------------------------------------------===// 757// Pseudo-instructions and codegen patterns 758// 759// Naming convention: For 'generic' pattern classes, we use the naming 760// convention PatTy1Ty2. 761//===----------------------------------------------------------------------===// 762 763/// Generic pattern classes 764 765class PatGprGpr<SDPatternOperator OpNode, LAInst Inst> 766 : Pat<(OpNode GPR:$rj, GPR:$rk), (Inst GPR:$rj, GPR:$rk)>; 767class PatGprGpr_32<SDPatternOperator OpNode, LAInst Inst> 768 : Pat<(sext_inreg (OpNode GPR:$rj, GPR:$rk), i32), (Inst GPR:$rj, GPR:$rk)>; 769class PatGpr<SDPatternOperator OpNode, LAInst Inst> 770 : Pat<(OpNode GPR:$rj), (Inst GPR:$rj)>; 771 772class PatGprImm<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd> 773 : Pat<(OpNode GPR:$rj, ImmOpnd:$imm), 774 (Inst GPR:$rj, ImmOpnd:$imm)>; 775class PatGprImm_32<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd> 776 : Pat<(sext_inreg (OpNode GPR:$rj, ImmOpnd:$imm), i32), 777 (Inst GPR:$rj, ImmOpnd:$imm)>; 778 779/// Predicates 780def AddLike: PatFrags<(ops node:$A, node:$B), 781 [(add node:$A, node:$B), (or node:$A, node:$B)], [{ 782 return N->getOpcode() == ISD::ADD || isOrEquivalentToAdd(N); 783}]>; 784 785/// Simple arithmetic operations 786 787// Match both a plain shift and one where the shift amount is masked (this is 788// typically introduced when the legalizer promotes the shift amount and 789// zero-extends it). For LoongArch, the mask is unnecessary as shifts in the 790// base ISA only read the least significant 5 bits (LA32) or 6 bits (LA64). 791def shiftMaskGRLen 792 : ComplexPattern<GRLenVT, 1, "selectShiftMaskGRLen", [], [], 0>; 793def shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>; 794 795def sexti32 : ComplexPattern<i64, 1, "selectSExti32">; 796def zexti32 : ComplexPattern<i64, 1, "selectZExti32">; 797 798class shiftop<SDPatternOperator operator> 799 : PatFrag<(ops node:$val, node:$count), 800 (operator node:$val, (GRLenVT (shiftMaskGRLen node:$count)))>; 801class shiftopw<SDPatternOperator operator> 802 : PatFrag<(ops node:$val, node:$count), 803 (operator node:$val, (i64 (shiftMask32 node:$count)))>; 804 805let Predicates = [IsLA32] in { 806def : PatGprGpr<add, ADD_W>; 807def : PatGprImm<add, ADDI_W, simm12>; 808def : PatGprGpr<sub, SUB_W>; 809def : PatGprGpr<sdiv, DIV_W>; 810def : PatGprGpr<udiv, DIV_WU>; 811def : PatGprGpr<srem, MOD_W>; 812def : PatGprGpr<urem, MOD_WU>; 813def : PatGprGpr<mul, MUL_W>; 814def : PatGprGpr<mulhs, MULH_W>; 815def : PatGprGpr<mulhu, MULH_WU>; 816def : PatGprGpr<rotr, ROTR_W>; 817def : PatGprImm<rotr, ROTRI_W, uimm5>; 818} // Predicates = [IsLA32] 819 820let Predicates = [IsLA64] in { 821def : PatGprGpr<add, ADD_D>; 822def : PatGprGpr_32<add, ADD_W>; 823def : PatGprImm<add, ADDI_D, simm12>; 824def : PatGprImm_32<add, ADDI_W, simm12>; 825def : PatGprGpr<sub, SUB_D>; 826def : PatGprGpr_32<sub, SUB_W>; 827def : PatGprGpr<sdiv, DIV_D>; 828def : PatGprGpr<udiv, DIV_DU>; 829def : PatGprGpr<srem, MOD_D>; 830def : PatGprGpr<urem, MOD_DU>; 831def : PatGprGpr<rotr, ROTR_D>; 832def : PatGprGpr<loongarch_rotr_w, ROTR_W>; 833def : PatGprImm<rotr, ROTRI_D, uimm6>; 834def : PatGprImm_32<rotr, ROTRI_W, uimm5>; 835def : Pat<(loongarch_rotl_w GPR:$rj, uimm5:$imm), 836 (ROTRI_W GPR:$rj, (ImmSubFrom32 uimm5:$imm))>; 837def : Pat<(sext_inreg (loongarch_rotl_w GPR:$rj, uimm5:$imm), i32), 838 (ROTRI_W GPR:$rj, (ImmSubFrom32 uimm5:$imm))>; 839// TODO: Select "_W[U]" instructions for i32xi32 if only lower 32 bits of the 840// product are used. 841def : PatGprGpr<mul, MUL_D>; 842def : PatGprGpr<mulhs, MULH_D>; 843def : PatGprGpr<mulhu, MULH_DU>; 844// Select MULW_D_W for calculating the full 64 bits product of i32xi32 signed 845// multiplication. 846def : Pat<(i64 (mul (sext_inreg GPR:$rj, i32), (sext_inreg GPR:$rk, i32))), 847 (MULW_D_W GPR:$rj, GPR:$rk)>; 848// Select MULW_D_WU for calculating the full 64 bits product of i32xi32 849// unsigned multiplication. 850def : Pat<(i64 (mul (loongarch_bstrpick GPR:$rj, (i64 31), (i64 0)), 851 (loongarch_bstrpick GPR:$rk, (i64 31), (i64 0)))), 852 (MULW_D_WU GPR:$rj, GPR:$rk)>; 853} // Predicates = [IsLA64] 854 855def : PatGprGpr<and, AND>; 856def : PatGprImm<and, ANDI, uimm12>; 857def : PatGprGpr<or, OR>; 858def : PatGprImm<or, ORI, uimm12>; 859def : PatGprGpr<xor, XOR>; 860def : PatGprImm<xor, XORI, uimm12>; 861def : Pat<(not GPR:$rj), (NOR GPR:$rj, R0)>; 862def : Pat<(not (or GPR:$rj, GPR:$rk)), (NOR GPR:$rj, GPR:$rk)>; 863def : Pat<(or GPR:$rj, (not GPR:$rk)), (ORN GPR:$rj, GPR:$rk)>; 864def : Pat<(and GPR:$rj, (not GPR:$rk)), (ANDN GPR:$rj, GPR:$rk)>; 865 866/// Traps 867 868// We lower `trap` to `amswap.w rd:$r0, rk:$r1, rj:$r0`, as this is guaranteed 869// to trap with an INE (non-existent on LA32, explicitly documented to INE on 870// LA64). And the resulting signal is different from `debugtrap` like on some 871// other existing ports so programs/porters might have an easier time. 872def PseudoUNIMP : Pseudo<(outs), (ins), [(trap)]>, 873 PseudoInstExpansion<(AMSWAP_W R0, R1, R0)>; 874 875// We lower `debugtrap` to `break 0`, as this is guaranteed to exist and work, 876// even for LA32 Primary. Also, because so far the ISA does not provide a 877// specific trap instruction/kind exclusively for alerting the debugger, 878// every other project uses the generic immediate of 0 for this. 879def : Pat<(debugtrap), (BREAK 0)>; 880 881/// Bit counting operations 882 883let Predicates = [IsLA64] in { 884def : PatGpr<ctlz, CLZ_D>; 885def : PatGpr<cttz, CTZ_D>; 886def : Pat<(ctlz (not GPR:$rj)), (CLO_D GPR:$rj)>; 887def : Pat<(cttz (not GPR:$rj)), (CTO_D GPR:$rj)>; 888def : PatGpr<loongarch_clzw, CLZ_W>; 889def : PatGpr<loongarch_ctzw, CTZ_W>; 890def : Pat<(loongarch_clzw (not GPR:$rj)), (CLO_W GPR:$rj)>; 891def : Pat<(loongarch_ctzw (not GPR:$rj)), (CTO_W GPR:$rj)>; 892} // Predicates = [IsLA64] 893 894let Predicates = [IsLA32] in { 895def : PatGpr<ctlz, CLZ_W>; 896def : PatGpr<cttz, CTZ_W>; 897def : Pat<(ctlz (not GPR:$rj)), (CLO_W GPR:$rj)>; 898def : Pat<(cttz (not GPR:$rj)), (CTO_W GPR:$rj)>; 899} // Predicates = [IsLA32] 900 901/// FrameIndex calculations 902let Predicates = [IsLA32] in { 903def : Pat<(AddLike (i32 BaseAddr:$rj), simm12:$imm12), 904 (ADDI_W (i32 BaseAddr:$rj), simm12:$imm12)>; 905} // Predicates = [IsLA32] 906let Predicates = [IsLA64] in { 907def : Pat<(AddLike (i64 BaseAddr:$rj), simm12:$imm12), 908 (ADDI_D (i64 BaseAddr:$rj), simm12:$imm12)>; 909} // Predicates = [IsLA64] 910 911/// Shifted addition 912let Predicates = [IsLA32] in { 913def : Pat<(add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)), 914 (ALSL_W GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>; 915} // Predicates = [IsLA32] 916let Predicates = [IsLA64] in { 917def : Pat<(add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)), 918 (ALSL_D GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>; 919def : Pat<(loongarch_bstrpick (add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)), 920 (i64 31), (i64 0)), 921 (ALSL_WU GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>; 922} // Predicates = [IsLA64] 923 924/// Shift 925 926let Predicates = [IsLA32] in { 927def : PatGprGpr<shiftop<shl>, SLL_W>; 928def : PatGprGpr<shiftop<sra>, SRA_W>; 929def : PatGprGpr<shiftop<srl>, SRL_W>; 930def : PatGprImm<shl, SLLI_W, uimm5>; 931def : PatGprImm<sra, SRAI_W, uimm5>; 932def : PatGprImm<srl, SRLI_W, uimm5>; 933} // Predicates = [IsLA32] 934 935let Predicates = [IsLA64] in { 936def : PatGprGpr<shiftopw<loongarch_sll_w>, SLL_W>; 937def : PatGprGpr<shiftopw<loongarch_sra_w>, SRA_W>; 938def : PatGprGpr<shiftopw<loongarch_srl_w>, SRL_W>; 939def : PatGprGpr<shiftop<shl>, SLL_D>; 940def : PatGprGpr<shiftop<sra>, SRA_D>; 941def : PatGprGpr<shiftop<srl>, SRL_D>; 942def : PatGprImm<shl, SLLI_D, uimm6>; 943def : PatGprImm<sra, SRAI_D, uimm6>; 944def : PatGprImm<srl, SRLI_D, uimm6>; 945} // Predicates = [IsLA64] 946 947/// sext and zext 948 949def : Pat<(sext_inreg GPR:$rj, i8), (EXT_W_B GPR:$rj)>; 950def : Pat<(sext_inreg GPR:$rj, i16), (EXT_W_H GPR:$rj)>; 951 952let Predicates = [IsLA64] in { 953def : Pat<(sext_inreg GPR:$rj, i32), (ADDI_W GPR:$rj, 0)>; 954} // Predicates = [IsLA64] 955 956/// Setcc 957 958def : PatGprGpr<setlt, SLT>; 959def : PatGprImm<setlt, SLTI, simm12>; 960def : PatGprGpr<setult, SLTU>; 961def : PatGprImm<setult, SLTUI, simm12>; 962 963// Define pattern expansions for setcc operations that aren't directly 964// handled by a LoongArch instruction. 965def : Pat<(seteq GPR:$rj, 0), (SLTUI GPR:$rj, 1)>; 966def : Pat<(seteq GPR:$rj, GPR:$rk), (SLTUI (XOR GPR:$rj, GPR:$rk), 1)>; 967let Predicates = [IsLA32] in { 968def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12), 969 (SLTUI (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>; 970} // Predicates = [IsLA32] 971let Predicates = [IsLA64] in { 972def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12), 973 (SLTUI (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>; 974} // Predicates = [IsLA64] 975def : Pat<(setne GPR:$rj, 0), (SLTU R0, GPR:$rj)>; 976def : Pat<(setne GPR:$rj, GPR:$rk), (SLTU R0, (XOR GPR:$rj, GPR:$rk))>; 977let Predicates = [IsLA32] in { 978def : Pat<(setne GPR:$rj, simm12_plus1:$imm12), 979 (SLTU R0, (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)))>; 980} // Predicates = [IsLA32] 981let Predicates = [IsLA64] in { 982def : Pat<(setne GPR:$rj, simm12_plus1:$imm12), 983 (SLTU R0, (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)))>; 984} // Predicates = [IsLA64] 985def : Pat<(setugt GPR:$rj, GPR:$rk), (SLTU GPR:$rk, GPR:$rj)>; 986def : Pat<(setuge GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rj, GPR:$rk), 1)>; 987def : Pat<(setule GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rk, GPR:$rj), 1)>; 988def : Pat<(setgt GPR:$rj, GPR:$rk), (SLT GPR:$rk, GPR:$rj)>; 989def : Pat<(setge GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rj, GPR:$rk), 1)>; 990def : Pat<(setle GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rk, GPR:$rj), 1)>; 991 992/// Select 993 994def : Pat<(select GPR:$cond, GPR:$t, GPR:$f), 995 (OR (MASKEQZ GPR:$t, GPR:$cond), (MASKNEZ GPR:$f, GPR:$cond))>; 996 997/// Branches and jumps 998 999class BccPat<PatFrag CondOp, LAInst Inst> 1000 : Pat<(brcond (GRLenVT (CondOp GPR:$rj, GPR:$rd)), bb:$imm16), 1001 (Inst GPR:$rj, GPR:$rd, bb:$imm16)>; 1002 1003def : BccPat<seteq, BEQ>; 1004def : BccPat<setne, BNE>; 1005def : BccPat<setlt, BLT>; 1006def : BccPat<setge, BGE>; 1007def : BccPat<setult, BLTU>; 1008def : BccPat<setuge, BGEU>; 1009 1010class BccSwapPat<PatFrag CondOp, LAInst InstBcc> 1011 : Pat<(brcond (GRLenVT (CondOp GPR:$rd, GPR:$rj)), bb:$imm16), 1012 (InstBcc GPR:$rj, GPR:$rd, bb:$imm16)>; 1013 1014// Condition codes that don't have matching LoongArch branch instructions, but 1015// are trivially supported by swapping the two input operands. 1016def : BccSwapPat<setgt, BLT>; 1017def : BccSwapPat<setle, BGE>; 1018def : BccSwapPat<setugt, BLTU>; 1019def : BccSwapPat<setule, BGEU>; 1020 1021// An extra pattern is needed for a brcond without a setcc (i.e. where the 1022// condition was calculated elsewhere). 1023def : Pat<(brcond GPR:$rj, bb:$imm21), (BNEZ GPR:$rj, bb:$imm21)>; 1024 1025def : Pat<(brcond (GRLenVT (seteq GPR:$rj, 0)), bb:$imm21), 1026 (BEQZ GPR:$rj, bb:$imm21)>; 1027def : Pat<(brcond (GRLenVT (setne GPR:$rj, 0)), bb:$imm21), 1028 (BNEZ GPR:$rj, bb:$imm21)>; 1029 1030let isBarrier = 1, isBranch = 1, isTerminator = 1 in 1031def PseudoBR : Pseudo<(outs), (ins simm26_b:$imm26), [(br bb:$imm26)]>, 1032 PseudoInstExpansion<(B simm26_b:$imm26)>; 1033 1034let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in 1035def PseudoBRIND : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>, 1036 PseudoInstExpansion<(JIRL R0, GPR:$rj, simm16_lsl2:$imm16)>; 1037 1038def : Pat<(brind GPR:$rj), (PseudoBRIND GPR:$rj, 0)>; 1039def : Pat<(brind (add GPR:$rj, simm16_lsl2:$imm16)), 1040 (PseudoBRIND GPR:$rj, simm16_lsl2:$imm16)>; 1041 1042let isCall = 1, Defs = [R1] in 1043def PseudoCALL : Pseudo<(outs), (ins simm26_symbol:$func)>; 1044 1045def : Pat<(loongarch_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>; 1046def : Pat<(loongarch_call texternalsym:$func), (PseudoCALL texternalsym:$func)>; 1047 1048let isCall = 1, Defs = [R1] in 1049def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rj), 1050 [(loongarch_call GPR:$rj)]>, 1051 PseudoInstExpansion<(JIRL R1, GPR:$rj, 0)>; 1052 1053let isCall = 1, Defs = [R1] in 1054def PseudoJIRL_CALL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>, 1055 PseudoInstExpansion<(JIRL R1, GPR:$rj, 1056 simm16_lsl2:$imm16)>; 1057 1058let isBarrier = 1, isReturn = 1, isTerminator = 1 in 1059def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>, 1060 PseudoInstExpansion<(JIRL R0, R1, 0)>; 1061 1062let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in 1063def PseudoTAIL : Pseudo<(outs), (ins simm26_symbol:$dst)>; 1064 1065def : Pat<(loongarch_tail (iPTR tglobaladdr:$dst)), 1066 (PseudoTAIL tglobaladdr:$dst)>; 1067def : Pat<(loongarch_tail (iPTR texternalsym:$dst)), 1068 (PseudoTAIL texternalsym:$dst)>; 1069 1070let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in 1071def PseudoTAILIndirect : Pseudo<(outs), (ins GPRT:$rj), 1072 [(loongarch_tail GPRT:$rj)]>, 1073 PseudoInstExpansion<(JIRL R0, GPR:$rj, 0)>; 1074 1075let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in 1076def PseudoB_TAIL : Pseudo<(outs), (ins simm26_b:$imm26)>, 1077 PseudoInstExpansion<(B simm26_b:$imm26)>; 1078 1079let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in 1080def PseudoJIRL_TAIL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>, 1081 PseudoInstExpansion<(JIRL R0, GPR:$rj, 1082 simm16_lsl2:$imm16)>; 1083 1084/// Load address (la*) macro instructions. 1085 1086// Define isCodeGenOnly = 0 to expose them to tablegened assembly parser. 1087let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0, 1088 isAsmParserOnly = 1 in { 1089def PseudoLA_ABS : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1090 "la.abs", "$dst, $src">; 1091def PseudoLA_ABS_LARGE : Pseudo<(outs GPR:$dst), 1092 (ins GPR:$tmp, bare_symbol:$src), [], 1093 "la.abs", "$dst, $src">; 1094def PseudoLA_PCREL : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1095 "la.pcrel", "$dst, $src">; 1096def PseudoLA_PCREL_LARGE : Pseudo<(outs GPR:$dst), 1097 (ins GPR:$tmp, bare_symbol:$src), [], 1098 "la.pcrel", "$dst, $tmp, $src">, 1099 Requires<[IsLA64]>; 1100def PseudoLA_TLS_LE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1101 "la.tls.le", "$dst, $src">; 1102} 1103let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, 1104 isAsmParserOnly = 1 in { 1105def PseudoLA_GOT : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1106 "la.got", "$dst, $src">; 1107def PseudoLA_GOT_LARGE : Pseudo<(outs GPR:$dst), 1108 (ins GPR:$tmp, bare_symbol:$src), [], 1109 "la.got", "$dst, $tmp, $src">, 1110 Requires<[IsLA64]>; 1111def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1112 "la.tls.ie", "$dst, $src">; 1113def PseudoLA_TLS_IE_LARGE : Pseudo<(outs GPR:$dst), 1114 (ins GPR:$tmp, bare_symbol:$src), [], 1115 "la.tls.ie", "$dst, $tmp, $src">, 1116 Requires<[IsLA64]>; 1117def PseudoLA_TLS_LD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1118 "la.tls.ld", "$dst, $src">; 1119def PseudoLA_TLS_LD_LARGE : Pseudo<(outs GPR:$dst), 1120 (ins GPR:$tmp, bare_symbol:$src), [], 1121 "la.tls.ld", "$dst, $tmp, $src">, 1122 Requires<[IsLA64]>; 1123def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1124 "la.tls.gd", "$dst, $src">; 1125def PseudoLA_TLS_GD_LARGE : Pseudo<(outs GPR:$dst), 1126 (ins GPR:$tmp, bare_symbol:$src), [], 1127 "la.tls.gd", "$dst, $tmp, $src">, 1128 Requires<[IsLA64]>; 1129} 1130 1131// Load address inst alias: "la", "la.global" and "la.local". 1132// Default: 1133// la = la.global = la.got 1134// la.local = la.pcrel 1135// With feature "+la-global-with-pcrel": 1136// la = la.global = la.pcrel 1137// With feature "+la-global-with-abs": 1138// la = la.global = la.abs 1139// With feature "+la-local-with-abs": 1140// la.local = la.abs 1141// With features "+la-global-with-pcrel,+la-global-with-abs"(disorder): 1142// la = la.global = la.pcrel 1143// Note: To keep consistent with gnu-as behavior, the "la" can only have one 1144// register operand. 1145def : InstAlias<"la $dst, $src", (PseudoLA_GOT GPR:$dst, bare_symbol:$src)>; 1146def : InstAlias<"la.global $dst, $src", 1147 (PseudoLA_GOT GPR:$dst, bare_symbol:$src)>; 1148def : InstAlias<"la.global $dst, $tmp, $src", 1149 (PseudoLA_GOT_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1150def : InstAlias<"la.local $dst, $src", 1151 (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>; 1152def : InstAlias<"la.local $dst, $tmp, $src", 1153 (PseudoLA_PCREL_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1154 1155// Note: Keep HasLaGlobalWithPcrel before HasLaGlobalWithAbs to ensure 1156// "la-global-with-pcrel" takes effect when bose "la-global-with-pcrel" and 1157// "la-global-with-abs" are enabled. 1158let Predicates = [HasLaGlobalWithPcrel] in { 1159def : InstAlias<"la $dst, $src", (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>; 1160def : InstAlias<"la.global $dst, $src", 1161 (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>; 1162def : InstAlias<"la.global $dst, $tmp, $src", 1163 (PseudoLA_PCREL_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1164} // Predicates = [HasLaGlobalWithPcrel] 1165 1166let Predicates = [HasLaGlobalWithAbs] in { 1167def : InstAlias<"la $dst, $src", (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>; 1168def : InstAlias<"la.global $dst, $src", 1169 (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>; 1170def : InstAlias<"la.global $dst, $tmp, $src", 1171 (PseudoLA_ABS_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1172} // Predicates = [HasLaGlobalWithAbs] 1173 1174let Predicates = [HasLaLocalWithAbs] in { 1175def : InstAlias<"la.local $dst, $src", 1176 (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>; 1177def : InstAlias<"la.local $dst, $tmp, $src", 1178 (PseudoLA_ABS_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1179} // Predicates = [HasLaLocalWithAbs] 1180 1181/// BSTRINS and BSTRPICK 1182 1183let Predicates = [IsLA32] in { 1184def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd), 1185 (BSTRINS_W GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>; 1186def : Pat<(loongarch_bstrpick GPR:$rj, uimm5:$msbd, uimm5:$lsbd), 1187 (BSTRPICK_W GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>; 1188} // Predicates = [IsLA32] 1189 1190let Predicates = [IsLA64] in { 1191def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd), 1192 (BSTRINS_D GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>; 1193def : Pat<(loongarch_bstrpick GPR:$rj, uimm6:$msbd, uimm6:$lsbd), 1194 (BSTRPICK_D GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>; 1195} // Predicates = [IsLA64] 1196 1197/// Byte-swapping and bit-reversal 1198 1199def : Pat<(loongarch_revb_2h GPR:$rj), (REVB_2H GPR:$rj)>; 1200def : Pat<(loongarch_bitrev_4b GPR:$rj), (BITREV_4B GPR:$rj)>; 1201 1202let Predicates = [IsLA32] in { 1203def : Pat<(bswap GPR:$rj), (ROTRI_W (REVB_2H GPR:$rj), 16)>; 1204def : Pat<(bitreverse GPR:$rj), (BITREV_W GPR:$rj)>; 1205def : Pat<(bswap (bitreverse GPR:$rj)), (BITREV_4B GPR:$rj)>; 1206def : Pat<(bitreverse (bswap GPR:$rj)), (BITREV_4B GPR:$rj)>; 1207} // Predicates = [IsLA32] 1208 1209let Predicates = [IsLA64] in { 1210def : Pat<(loongarch_revb_2w GPR:$rj), (REVB_2W GPR:$rj)>; 1211def : Pat<(bswap GPR:$rj), (REVB_D GPR:$rj)>; 1212def : Pat<(loongarch_bitrev_w GPR:$rj), (BITREV_W GPR:$rj)>; 1213def : Pat<(bitreverse GPR:$rj), (BITREV_D GPR:$rj)>; 1214def : Pat<(bswap (bitreverse GPR:$rj)), (BITREV_8B GPR:$rj)>; 1215def : Pat<(bitreverse (bswap GPR:$rj)), (BITREV_8B GPR:$rj)>; 1216} // Predicates = [IsLA64] 1217 1218/// Loads 1219 1220multiclass LdPat<PatFrag LoadOp, LAInst Inst, ValueType vt = GRLenVT> { 1221 def : Pat<(vt (LoadOp BaseAddr:$rj)), (Inst BaseAddr:$rj, 0)>; 1222 def : Pat<(vt (LoadOp (AddLike BaseAddr:$rj, simm12:$imm12))), 1223 (Inst BaseAddr:$rj, simm12:$imm12)>; 1224} 1225 1226defm : LdPat<sextloadi8, LD_B>; 1227defm : LdPat<extloadi8, LD_B>; 1228defm : LdPat<sextloadi16, LD_H>; 1229defm : LdPat<extloadi16, LD_H>; 1230defm : LdPat<load, LD_W>, Requires<[IsLA32]>; 1231defm : LdPat<zextloadi8, LD_BU>; 1232defm : LdPat<zextloadi16, LD_HU>; 1233let Predicates = [IsLA64] in { 1234defm : LdPat<sextloadi32, LD_W, i64>; 1235defm : LdPat<extloadi32, LD_W, i64>; 1236defm : LdPat<zextloadi32, LD_WU, i64>; 1237defm : LdPat<load, LD_D, i64>; 1238} // Predicates = [IsLA64] 1239 1240// LA64 register-register-addressed loads 1241let Predicates = [IsLA64] in { 1242class RegRegLdPat<PatFrag LoadOp, LAInst Inst, ValueType vt> 1243 : Pat<(vt (LoadOp (add NonFIBaseAddr:$rj, GPR:$rk))), 1244 (Inst NonFIBaseAddr:$rj, GPR:$rk)>; 1245 1246def : RegRegLdPat<extloadi8, LDX_B, i64>; 1247def : RegRegLdPat<sextloadi8, LDX_B, i64>; 1248def : RegRegLdPat<zextloadi8, LDX_BU, i64>; 1249def : RegRegLdPat<extloadi16, LDX_H, i64>; 1250def : RegRegLdPat<sextloadi16, LDX_H, i64>; 1251def : RegRegLdPat<zextloadi16, LDX_HU, i64>; 1252def : RegRegLdPat<extloadi32, LDX_W, i64>; 1253def : RegRegLdPat<sextloadi32, LDX_W, i64>; 1254def : RegRegLdPat<zextloadi32, LDX_WU, i64>; 1255def : RegRegLdPat<load, LDX_D, i64>; 1256} // Predicates = [IsLA64] 1257 1258/// Stores 1259 1260multiclass StPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy, 1261 ValueType vt> { 1262 def : Pat<(StoreOp (vt StTy:$rd), BaseAddr:$rj), 1263 (Inst StTy:$rd, BaseAddr:$rj, 0)>; 1264 def : Pat<(StoreOp (vt StTy:$rd), (AddLike BaseAddr:$rj, simm12:$imm12)), 1265 (Inst StTy:$rd, BaseAddr:$rj, simm12:$imm12)>; 1266} 1267 1268defm : StPat<truncstorei8, ST_B, GPR, GRLenVT>; 1269defm : StPat<truncstorei16, ST_H, GPR, GRLenVT>; 1270defm : StPat<store, ST_W, GPR, i32>, Requires<[IsLA32]>; 1271let Predicates = [IsLA64] in { 1272defm : StPat<truncstorei32, ST_W, GPR, i64>; 1273defm : StPat<store, ST_D, GPR, i64>; 1274} // Predicates = [IsLA64] 1275 1276let Predicates = [IsLA64] in { 1277def : Pat<(i64 (sextloadi32 (AddLike BaseAddr:$rj, simm14_lsl2:$imm14))), 1278 (LDPTR_W BaseAddr:$rj, simm14_lsl2:$imm14)>; 1279def : Pat<(i64 (load (AddLike BaseAddr:$rj, simm14_lsl2:$imm14))), 1280 (LDPTR_D BaseAddr:$rj, simm14_lsl2:$imm14)>; 1281def : Pat<(truncstorei32 (i64 GPR:$rd), 1282 (AddLike BaseAddr:$rj, simm14_lsl2:$imm14)), 1283 (STPTR_W GPR:$rd, BaseAddr:$rj, simm14_lsl2:$imm14)>; 1284def : Pat<(store (i64 GPR:$rd), (AddLike BaseAddr:$rj, simm14_lsl2:$imm14)), 1285 (STPTR_D GPR:$rd, BaseAddr:$rj, simm14_lsl2:$imm14)>; 1286} // Predicates = [IsLA64] 1287 1288// LA64 register-register-addressed stores 1289let Predicates = [IsLA64] in { 1290class RegRegStPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy, 1291 ValueType vt> 1292 : Pat<(StoreOp (vt StTy:$rd), (add NonFIBaseAddr:$rj, GPR:$rk)), 1293 (Inst StTy:$rd, NonFIBaseAddr:$rj, GPR:$rk)>; 1294 1295def : RegRegStPat<truncstorei8, STX_B, GPR, i64>; 1296def : RegRegStPat<truncstorei16, STX_H, GPR, i64>; 1297def : RegRegStPat<truncstorei32, STX_W, GPR, i64>; 1298def : RegRegStPat<store, STX_D, GPR, i64>; 1299} // Predicates = [IsLA64] 1300 1301/// Atomic loads and stores 1302 1303def : Pat<(atomic_fence timm, timm), (DBAR 0)>; 1304 1305defm : LdPat<atomic_load_8, LD_B>; 1306defm : LdPat<atomic_load_16, LD_H>; 1307defm : LdPat<atomic_load_32, LD_W>; 1308 1309class release_seqcst_store<PatFrag base> 1310 : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val), [{ 1311 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getSuccessOrdering(); 1312 return isReleaseOrStronger(Ordering); 1313}]>; 1314 1315class unordered_monotonic_store<PatFrag base> 1316 : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val), [{ 1317 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getSuccessOrdering(); 1318 return !isReleaseOrStronger(Ordering); 1319}]>; 1320 1321def atomic_store_release_seqcst_32 : release_seqcst_store<atomic_store_32>; 1322def atomic_store_release_seqcst_64 : release_seqcst_store<atomic_store_64>; 1323def atomic_store_unordered_monotonic_32 1324 : unordered_monotonic_store<atomic_store_32>; 1325def atomic_store_unordered_monotonic_64 1326 : unordered_monotonic_store<atomic_store_64>; 1327 1328/// AtomicStores 1329 1330multiclass AtomicStPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy, 1331 ValueType vt> { 1332 def : Pat<(StoreOp BaseAddr:$ptr, (vt StTy:$val)), 1333 (Inst StTy:$val, BaseAddr:$ptr, 0)>; 1334 def : Pat<(StoreOp (AddLike BaseAddr:$ptr, simm12:$imm12), (vt StTy:$val)), 1335 (Inst StTy:$val, BaseAddr:$ptr, simm12:$imm12)>; 1336} 1337 1338defm : AtomicStPat<atomic_store_8, ST_B, GPR, GRLenVT>; 1339defm : AtomicStPat<atomic_store_16, ST_H, GPR, GRLenVT>; 1340defm : AtomicStPat<atomic_store_unordered_monotonic_32, ST_W, GPR, i32>, 1341 Requires<[IsLA32]>; 1342 1343def PseudoAtomicStoreW 1344 : Pseudo<(outs GPR:$dst), (ins GPR:$rj, GPR:$rk)>, 1345 PseudoInstExpansion<(AMSWAP_DB_W R0, GPR:$rk, GPRMemAtomic:$rj)>; 1346 1347def : Pat<(atomic_store_release_seqcst_32 GPR:$rj, GPR:$rk), 1348 (PseudoAtomicStoreW GPR:$rj, GPR:$rk)>; 1349 1350let Predicates = [IsLA64] in { 1351def PseudoAtomicStoreD 1352 : Pseudo<(outs GPR:$dst), (ins GPR:$rj, GPR:$rk)>, 1353 PseudoInstExpansion<(AMSWAP_DB_D R0, GPR:$rk, GPRMemAtomic:$rj)>; 1354 1355def : Pat<(atomic_store_release_seqcst_64 GPR:$rj, GPR:$rk), 1356 (PseudoAtomicStoreD GPR:$rj, GPR:$rk)>; 1357 1358defm : LdPat<atomic_load_64, LD_D>; 1359defm : AtomicStPat<atomic_store_unordered_monotonic_32, ST_W, GPR, i64>; 1360defm : AtomicStPat<atomic_store_unordered_monotonic_64, ST_D, GPR, i64>; 1361} // Predicates = [IsLA64] 1362 1363/// Atomic Ops 1364 1365class PseudoMaskedAM 1366 : Pseudo<(outs GPR:$res, GPR:$scratch), 1367 (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$ordering)> { 1368 let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; 1369 let mayLoad = 1; 1370 let mayStore = 1; 1371 let hasSideEffects = 0; 1372 let Size = 36; 1373} 1374 1375def PseudoMaskedAtomicSwap32 : PseudoMaskedAM; 1376def PseudoMaskedAtomicLoadAdd32 : PseudoMaskedAM; 1377def PseudoMaskedAtomicLoadSub32 : PseudoMaskedAM; 1378def PseudoMaskedAtomicLoadNand32 : PseudoMaskedAM; 1379 1380class PseudoAM : Pseudo<(outs GPR:$res, GPR:$scratch), 1381 (ins GPR:$addr, GPR:$incr, grlenimm:$ordering)> { 1382 let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; 1383 let mayLoad = 1; 1384 let mayStore = 1; 1385 let hasSideEffects = 0; 1386 let Size = 24; 1387} 1388 1389def PseudoAtomicSwap32 : PseudoAM; 1390def PseudoAtomicLoadNand32 : PseudoAM; 1391def PseudoAtomicLoadNand64 : PseudoAM; 1392def PseudoAtomicLoadAdd32 : PseudoAM; 1393def PseudoAtomicLoadSub32 : PseudoAM; 1394def PseudoAtomicLoadAnd32 : PseudoAM; 1395def PseudoAtomicLoadOr32 : PseudoAM; 1396def PseudoAtomicLoadXor32 : PseudoAM; 1397 1398multiclass PseudoBinPat<string Op, Pseudo BinInst> { 1399 def : Pat<(!cast<PatFrag>(Op#"_monotonic") GPR:$addr, GPR:$incr), 1400 (BinInst GPR:$addr, GPR:$incr, 2)>; 1401 def : Pat<(!cast<PatFrag>(Op#"_acquire") GPR:$addr, GPR:$incr), 1402 (BinInst GPR:$addr, GPR:$incr, 4)>; 1403 def : Pat<(!cast<PatFrag>(Op#"_release") GPR:$addr, GPR:$incr), 1404 (BinInst GPR:$addr, GPR:$incr, 5)>; 1405 def : Pat<(!cast<PatFrag>(Op#"_acq_rel") GPR:$addr, GPR:$incr), 1406 (BinInst GPR:$addr, GPR:$incr, 6)>; 1407 def : Pat<(!cast<PatFrag>(Op#"_seq_cst") GPR:$addr, GPR:$incr), 1408 (BinInst GPR:$addr, GPR:$incr, 7)>; 1409} 1410 1411class PseudoMaskedAMUMinUMax 1412 : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2), 1413 (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$ordering)> { 1414 let Constraints = "@earlyclobber $res,@earlyclobber $scratch1," 1415 "@earlyclobber $scratch2"; 1416 let mayLoad = 1; 1417 let mayStore = 1; 1418 let hasSideEffects = 0; 1419 let Size = 48; 1420} 1421 1422def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMUMinUMax; 1423def PseudoMaskedAtomicLoadUMin32 : PseudoMaskedAMUMinUMax; 1424 1425class PseudoMaskedAMMinMax 1426 : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2), 1427 (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$sextshamt, 1428 grlenimm:$ordering)> { 1429 let Constraints = "@earlyclobber $res,@earlyclobber $scratch1," 1430 "@earlyclobber $scratch2"; 1431 let mayLoad = 1; 1432 let mayStore = 1; 1433 let hasSideEffects = 0; 1434 let Size = 56; 1435} 1436 1437def PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMMinMax; 1438def PseudoMaskedAtomicLoadMin32 : PseudoMaskedAMMinMax; 1439 1440/// Compare and exchange 1441 1442class PseudoCmpXchg 1443 : Pseudo<(outs GPR:$res, GPR:$scratch), 1444 (ins GPR:$addr, GPR:$cmpval, GPR:$newval)> { 1445 let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; 1446 let mayLoad = 1; 1447 let mayStore = 1; 1448 let hasSideEffects = 0; 1449 let Size = 36; 1450} 1451 1452def PseudoCmpXchg32 : PseudoCmpXchg; 1453def PseudoCmpXchg64 : PseudoCmpXchg; 1454 1455def PseudoMaskedCmpXchg32 1456 : Pseudo<(outs GPR:$res, GPR:$scratch), 1457 (ins GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, 1458 grlenimm:$ordering)> { 1459 let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; 1460 let mayLoad = 1; 1461 let mayStore = 1; 1462 let hasSideEffects = 0; 1463 let Size = 44; 1464} 1465 1466class PseudoMaskedAMMinMaxPat<Intrinsic intrin, Pseudo AMInst> 1467 : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt, 1468 timm:$ordering), 1469 (AMInst GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt, 1470 timm:$ordering)>; 1471 1472class AtomicPat<Intrinsic intrin, Pseudo AMInst> 1473 : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering), 1474 (AMInst GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering)>; 1475 1476let Predicates = [IsLA64] in { 1477def : AtomicPat<int_loongarch_masked_atomicrmw_xchg_i64, 1478 PseudoMaskedAtomicSwap32>; 1479def : Pat<(atomic_swap_32 GPR:$addr, GPR:$incr), 1480 (AMSWAP_DB_W GPR:$incr, GPR:$addr)>; 1481def : Pat<(atomic_swap_64 GPR:$addr, GPR:$incr), 1482 (AMSWAP_DB_D GPR:$incr, GPR:$addr)>; 1483def : Pat<(atomic_load_add_64 GPR:$rj, GPR:$rk), 1484 (AMADD_DB_D GPR:$rk, GPR:$rj)>; 1485def : AtomicPat<int_loongarch_masked_atomicrmw_add_i64, 1486 PseudoMaskedAtomicLoadAdd32>; 1487def : Pat<(atomic_load_sub_32 GPR:$rj, GPR:$rk), 1488 (AMADD_DB_W (SUB_W R0, GPR:$rk), GPR:$rj)>; 1489def : Pat<(atomic_load_sub_64 GPR:$rj, GPR:$rk), 1490 (AMADD_DB_D (SUB_D R0, GPR:$rk), GPR:$rj)>; 1491def : AtomicPat<int_loongarch_masked_atomicrmw_sub_i64, 1492 PseudoMaskedAtomicLoadSub32>; 1493defm : PseudoBinPat<"atomic_load_nand_64", PseudoAtomicLoadNand64>; 1494def : AtomicPat<int_loongarch_masked_atomicrmw_nand_i64, 1495 PseudoMaskedAtomicLoadNand32>; 1496def : Pat<(atomic_load_add_32 GPR:$rj, GPR:$rk), 1497 (AMADD_DB_W GPR:$rk, GPR:$rj)>; 1498def : Pat<(atomic_load_and_32 GPR:$rj, GPR:$rk), 1499 (AMAND_DB_W GPR:$rk, GPR:$rj)>; 1500def : Pat<(atomic_load_and_64 GPR:$rj, GPR:$rk), 1501 (AMAND_DB_D GPR:$rk, GPR:$rj)>; 1502def : Pat<(atomic_load_or_32 GPR:$rj, GPR:$rk), 1503 (AMOR_DB_W GPR:$rk, GPR:$rj)>; 1504def : Pat<(atomic_load_or_64 GPR:$rj, GPR:$rk), 1505 (AMOR_DB_D GPR:$rk, GPR:$rj)>; 1506def : Pat<(atomic_load_xor_32 GPR:$rj, GPR:$rk), 1507 (AMXOR_DB_W GPR:$rk, GPR:$rj)>; 1508def : Pat<(atomic_load_xor_64 GPR:$rj, GPR:$rk), 1509 (AMXOR_DB_D GPR:$rk, GPR:$rj)>; 1510 1511def : Pat<(atomic_load_umin_32 GPR:$rj, GPR:$rk), 1512 (AMMIN_DB_WU GPR:$rk, GPR:$rj)>; 1513def : Pat<(atomic_load_umin_64 GPR:$rj, GPR:$rk), 1514 (AMMIN_DB_DU GPR:$rk, GPR:$rj)>; 1515def : Pat<(atomic_load_umax_32 GPR:$rj, GPR:$rk), 1516 (AMMAX_DB_WU GPR:$rk, GPR:$rj)>; 1517def : Pat<(atomic_load_umax_64 GPR:$rj, GPR:$rk), 1518 (AMMAX_DB_DU GPR:$rk, GPR:$rj)>; 1519 1520def : Pat<(atomic_load_min_32 GPR:$rj, GPR:$rk), 1521 (AMMIN_DB_W GPR:$rk, GPR:$rj)>; 1522def : Pat<(atomic_load_min_64 GPR:$rj, GPR:$rk), 1523 (AMMIN_DB_D GPR:$rk, GPR:$rj)>; 1524def : Pat<(atomic_load_max_32 GPR:$rj, GPR:$rk), 1525 (AMMAX_DB_W GPR:$rk, GPR:$rj)>; 1526def : Pat<(atomic_load_max_64 GPR:$rj, GPR:$rk), 1527 (AMMAX_DB_D GPR:$rk, GPR:$rj)>; 1528 1529def : AtomicPat<int_loongarch_masked_atomicrmw_umax_i64, 1530 PseudoMaskedAtomicLoadUMax32>; 1531def : AtomicPat<int_loongarch_masked_atomicrmw_umin_i64, 1532 PseudoMaskedAtomicLoadUMin32>; 1533 1534def : Pat<(atomic_cmp_swap_64 GPR:$addr, GPR:$cmp, GPR:$new), 1535 (PseudoCmpXchg64 GPR:$addr, GPR:$cmp, GPR:$new)>; 1536def : Pat<(int_loongarch_masked_cmpxchg_i64 1537 GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering), 1538 (PseudoMaskedCmpXchg32 1539 GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>; 1540def : Pat<(atomic_cmp_swap_32 GPR:$addr, GPR:$cmp, GPR:$new), 1541 (PseudoCmpXchg32 GPR:$addr, GPR:$cmp, GPR:$new)>; 1542 1543def : PseudoMaskedAMMinMaxPat<int_loongarch_masked_atomicrmw_max_i64, 1544 PseudoMaskedAtomicLoadMax32>; 1545def : PseudoMaskedAMMinMaxPat<int_loongarch_masked_atomicrmw_min_i64, 1546 PseudoMaskedAtomicLoadMin32>; 1547} // Predicates = [IsLA64] 1548 1549defm : PseudoBinPat<"atomic_load_nand_32", PseudoAtomicLoadNand32>; 1550 1551let Predicates = [IsLA32] in { 1552def : AtomicPat<int_loongarch_masked_atomicrmw_xchg_i32, 1553 PseudoMaskedAtomicSwap32>; 1554defm : PseudoBinPat<"atomic_swap_32", PseudoAtomicSwap32>; 1555def : AtomicPat<int_loongarch_masked_atomicrmw_add_i32, 1556 PseudoMaskedAtomicLoadAdd32>; 1557def : AtomicPat<int_loongarch_masked_atomicrmw_sub_i32, 1558 PseudoMaskedAtomicLoadSub32>; 1559def : AtomicPat<int_loongarch_masked_atomicrmw_nand_i32, 1560 PseudoMaskedAtomicLoadNand32>; 1561defm : PseudoBinPat<"atomic_load_add_32", PseudoAtomicLoadAdd32>; 1562defm : PseudoBinPat<"atomic_load_sub_32", PseudoAtomicLoadSub32>; 1563defm : PseudoBinPat<"atomic_load_and_32", PseudoAtomicLoadAnd32>; 1564defm : PseudoBinPat<"atomic_load_or_32", PseudoAtomicLoadOr32>; 1565defm : PseudoBinPat<"atomic_load_xor_32", PseudoAtomicLoadXor32>; 1566} // Predicates = [IsLA32] 1567 1568/// Intrinsics 1569 1570def : Pat<(int_loongarch_cacop_d timm:$op, i64:$rj, timm:$imm12), 1571 (CACOP uimm5:$op, GPR:$rj, simm12:$imm12)>; 1572def : Pat<(int_loongarch_cacop_w i32:$op, i32:$rj, i32:$imm12), 1573 (CACOP uimm5:$op, GPR:$rj, simm12:$imm12)>; 1574def : Pat<(loongarch_dbar uimm15:$imm15), (DBAR uimm15:$imm15)>; 1575def : Pat<(loongarch_ibar uimm15:$imm15), (IBAR uimm15:$imm15)>; 1576def : Pat<(loongarch_break uimm15:$imm15), (BREAK uimm15:$imm15)>; 1577def : Pat<(loongarch_syscall uimm15:$imm15), (SYSCALL uimm15:$imm15)>; 1578 1579let Predicates = [IsLA64] in { 1580// CRC Check Instructions 1581def : PatGprGpr<loongarch_crc_w_b_w, CRC_W_B_W>; 1582def : PatGprGpr<loongarch_crc_w_h_w, CRC_W_H_W>; 1583def : PatGprGpr<loongarch_crc_w_w_w, CRC_W_W_W>; 1584def : PatGprGpr<loongarch_crc_w_d_w, CRC_W_D_W>; 1585def : PatGprGpr<loongarch_crcc_w_b_w, CRCC_W_B_W>; 1586def : PatGprGpr<loongarch_crcc_w_h_w, CRCC_W_H_W>; 1587def : PatGprGpr<loongarch_crcc_w_w_w, CRCC_W_W_W>; 1588def : PatGprGpr<loongarch_crcc_w_d_w, CRCC_W_D_W>; 1589} // Predicates = [IsLA64] 1590 1591/// Other pseudo-instructions 1592 1593// Pessimistically assume the stack pointer will be clobbered 1594let Defs = [R3], Uses = [R3] in { 1595def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 1596 [(callseq_start timm:$amt1, timm:$amt2)]>; 1597def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 1598 [(callseq_end timm:$amt1, timm:$amt2)]>; 1599} // Defs = [R3], Uses = [R3] 1600 1601//===----------------------------------------------------------------------===// 1602// Assembler Pseudo Instructions 1603//===----------------------------------------------------------------------===// 1604 1605def : InstAlias<"nop", (ANDI R0, R0, 0)>; 1606def : InstAlias<"move $dst, $src", (OR GPR:$dst, GPR:$src, R0)>; 1607// `ret` is supported since binutils commit 20f2e2686c79a5ac (version 2.40 and 1608// later). 1609def : InstAlias<"ret", (JIRL R0, R1, 0)>; 1610def : InstAlias<"jr $rj", (JIRL R0, GPR:$rj, 0)>; 1611 1612// Branches implemented with alias. 1613// Always output the canonical mnemonic for the pseudo branch instructions. 1614// The GNU tools emit the canonical mnemonic for the branch pseudo instructions 1615// as well (e.g. "bgt" will be recognised by the assembler but never printed by 1616// objdump). Match this behaviour by setting a zero weight. 1617def : InstAlias<"bgt $rj, $rd, $imm16", 1618 (BLT GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 1619def : InstAlias<"bgtu $rj, $rd, $imm16", 1620 (BLTU GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 1621def : InstAlias<"ble $rj, $rd, $imm16", 1622 (BGE GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 1623def : InstAlias<"bleu $rj, $rd, $imm16", 1624 (BGEU GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 1625def : InstAlias<"bltz $rd, $imm16", 1626 (BLT GPR:$rd, R0, simm16_lsl2_br:$imm16), 0>; 1627def : InstAlias<"bgtz $rj, $imm16", 1628 (BLT R0, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 1629def : InstAlias<"blez $rj, $imm16", 1630 (BGE R0, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 1631def : InstAlias<"bgez $rd, $imm16", 1632 (BGE GPR:$rd, R0, simm16_lsl2_br:$imm16), 0>; 1633 1634// Load immediate. 1635let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0, 1636 isAsmParserOnly = 1 in { 1637def PseudoLI_W : Pseudo<(outs GPR:$rd), (ins imm32:$imm), [], 1638 "li.w", "$rd, $imm">; 1639def PseudoLI_D : Pseudo<(outs GPR:$rd), (ins grlenimm:$imm), [], 1640 "li.d", "$rd, $imm">, Requires<[IsLA64]>; 1641} 1642 1643//===----------------------------------------------------------------------===// 1644// Basic Floating-Point Instructions 1645//===----------------------------------------------------------------------===// 1646 1647include "LoongArchFloat32InstrInfo.td" 1648include "LoongArchFloat64InstrInfo.td" 1649 1650let Predicates = [HasBasicF], usesCustomInserter = 1 in { 1651 def WRFCSR : Pseudo<(outs), (ins uimm2:$fcsr, GPR:$src), 1652 [(loongarch_movgr2fcsr uimm2:$fcsr, GRLenVT:$src)]>; 1653 def RDFCSR : Pseudo<(outs GPR:$rd), (ins uimm2:$fcsr), 1654 [(set GPR:$rd, (loongarch_movfcsr2gr uimm2:$fcsr))]>; 1655} 1656 1657//===----------------------------------------------------------------------===// 1658// Privilege Instructions 1659//===----------------------------------------------------------------------===// 1660 1661// CSR Access Instructions 1662def CSRRD : FmtCSR<0b0000010000000, (outs GPR:$rd), (ins uimm14:$csr_num), 1663 "csrrd", "$rd, $csr_num">; 1664let Constraints = "$rd = $dst" in { 1665def CSRWR : FmtCSR<0b0000010000001, (outs GPR:$dst), 1666 (ins GPR:$rd, uimm14:$csr_num), "csrwr", "$rd, $csr_num">; 1667def CSRXCHG : FmtCSRXCHG<0b00000100, (outs GPR:$dst), 1668 (ins GPR:$rd, GPR:$rj, uimm14:$csr_num), 1669 "csrxchg", "$rd, $rj, $csr_num">; 1670} // Constraints = "$rd = $dst" 1671 1672// IOCSR Access Instructions 1673def IOCSRRD_B : IOCSRRD<0b0000011001001000000000, "iocsrrd.b">; 1674def IOCSRRD_H : IOCSRRD<0b0000011001001000000001, "iocsrrd.h">; 1675def IOCSRRD_W : IOCSRRD<0b0000011001001000000010, "iocsrrd.w">; 1676def IOCSRWR_B : IOCSRWR<0b0000011001001000000100, "iocsrwr.b">; 1677def IOCSRWR_H : IOCSRWR<0b0000011001001000000101, "iocsrwr.h">; 1678def IOCSRWR_W : IOCSRWR<0b0000011001001000000110, "iocsrwr.w">; 1679let Predicates = [IsLA64] in { 1680def IOCSRRD_D : IOCSRRD<0b0000011001001000000011, "iocsrrd.d">; 1681def IOCSRWR_D : IOCSRWR<0b0000011001001000000111, "iocsrwr.d">; 1682} // Predicates = [IsLA64] 1683 1684// TLB Maintenance Instructions 1685def TLBSRCH : FmtI32<0b00000110010010000010100000000000, "tlbsrch">; 1686def TLBRD : FmtI32<0b00000110010010000010110000000000, "tlbrd">; 1687def TLBWR : FmtI32<0b00000110010010000011000000000000, "tlbwr">; 1688def TLBFILL : FmtI32<0b00000110010010000011010000000000, "tlbfill">; 1689def TLBCLR : FmtI32<0b00000110010010000010000000000000, "tlbclr">; 1690def TLBFLUSH : FmtI32<0b00000110010010000010010000000000, "tlbflush">; 1691def INVTLB : FmtINVTLB<(outs), (ins GPR:$rk, GPR:$rj, uimm5:$op), "invtlb", 1692 "$op, $rj, $rk">; 1693 1694// Software Page Walking Instructions 1695def LDDIR : Fmt2RI8<0b00000110010000, (outs GPR:$rd), 1696 (ins GPR:$rj, uimm8:$imm8), "lddir", "$rd, $rj, $imm8">; 1697def LDPTE : FmtLDPTE<(outs), (ins GPR:$rj, uimm8:$seq), "ldpte", "$rj, $seq">; 1698 1699 1700// Other Miscellaneous Instructions 1701def ERTN : FmtI32<0b00000110010010000011100000000000, "ertn">; 1702def DBCL : MISC_I15<0b00000000001010101, "dbcl">; 1703def IDLE : MISC_I15<0b00000110010010001, "idle">; 1704 1705//===----------------------------------------------------------------------===// 1706// Privilege Intrinsics 1707//===----------------------------------------------------------------------===// 1708 1709def : Pat<(loongarch_csrrd uimm14:$imm14), (CSRRD uimm14:$imm14)>; 1710def : Pat<(loongarch_csrwr GPR:$rd, uimm14:$imm14), 1711 (CSRWR GPR:$rd, uimm14:$imm14)>; 1712def : Pat<(loongarch_csrxchg GPR:$rd, GPR:$rj, uimm14:$imm14), 1713 (CSRXCHG GPR:$rd, GPR:$rj, uimm14:$imm14)>; 1714 1715def : Pat<(loongarch_iocsrrd_b GPR:$rj), (IOCSRRD_B GPR:$rj)>; 1716def : Pat<(loongarch_iocsrrd_h GPR:$rj), (IOCSRRD_H GPR:$rj)>; 1717def : Pat<(loongarch_iocsrrd_w GPR:$rj), (IOCSRRD_W GPR:$rj)>; 1718 1719def : Pat<(loongarch_iocsrwr_b GPR:$rd, GPR:$rj), (IOCSRWR_B GPR:$rd, GPR:$rj)>; 1720def : Pat<(loongarch_iocsrwr_h GPR:$rd, GPR:$rj), (IOCSRWR_H GPR:$rd, GPR:$rj)>; 1721def : Pat<(loongarch_iocsrwr_w GPR:$rd, GPR:$rj), (IOCSRWR_W GPR:$rd, GPR:$rj)>; 1722 1723def : Pat<(loongarch_cpucfg GPR:$rj), (CPUCFG GPR:$rj)>; 1724 1725let Predicates = [IsLA64] in { 1726def : Pat<(loongarch_iocsrrd_d GPR:$rj), (IOCSRRD_D GPR:$rj)>; 1727def : Pat<(loongarch_iocsrwr_d GPR:$rd, GPR:$rj), (IOCSRWR_D GPR:$rd, GPR:$rj)>; 1728def : Pat<(int_loongarch_asrtle_d GPR:$rj, GPR:$rk), 1729 (ASRTLE_D GPR:$rj, GPR:$rk)>; 1730def : Pat<(int_loongarch_asrtgt_d GPR:$rj, GPR:$rk), 1731 (ASRTGT_D GPR:$rj, GPR:$rk)>; 1732def : Pat<(int_loongarch_lddir_d GPR:$rj, timm:$imm8), 1733 (LDDIR GPR:$rj, uimm8:$imm8)>; 1734def : Pat<(int_loongarch_ldpte_d GPR:$rj, timm:$imm8), 1735 (LDPTE GPR:$rj, uimm8:$imm8)>; 1736} // Predicates = [IsLA64] 1737