1//===-- LanaiInstrInfo.td - Target Description for Lanai Target -----------===// 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 Lanai instructions in TableGen format. 10// 11//===----------------------------------------------------------------------===// 12 13//===----------------------------------------------------------------------===// 14// Instruction format superclass 15//===----------------------------------------------------------------------===// 16 17include "LanaiInstrFormats.td" 18 19// -------------------------------------------------- // 20// Instruction Operands and Patterns 21// -------------------------------------------------- // 22 23// These are target-independent nodes, but have target-specific formats. 24def SDT_LanaiCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, 25 SDTCisVT<1, i32>]>; 26def SDT_LanaiCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, 27 SDTCisVT<1, i32>]>; 28def SDT_LanaiCall : SDTypeProfile<0, -1, [SDTCisVT<0, i32>]>; 29def SDT_LanaiSetFlag : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>; 30def SDT_LanaiSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, 31 SDTCisSameAs<1, 2>]>; 32def SDT_LanaiSetCC : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, 33 SDTCisVT<1, i32>]>; 34def SDT_LanaiBrCC : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, 35 SDTCisVT<1, i32>]>; 36def SDT_LanaiAdjDynAlloc : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, 37 SDTCisVT<1, i32>]>; 38 39def Call : SDNode<"LanaiISD::CALL", SDT_LanaiCall, 40 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 41 SDNPVariadic]>; 42def RetFlag : SDNode<"LanaiISD::RET_FLAG", SDTNone, 43 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; 44def CallSeqStart : SDNode<"ISD::CALLSEQ_START", SDT_LanaiCallSeqStart, 45 [SDNPHasChain, SDNPOutGlue]>; 46def CallSeqEnd : SDNode<"ISD::CALLSEQ_END", SDT_LanaiCallSeqEnd, 47 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; 48def LanaiSetFlag : SDNode<"LanaiISD::SET_FLAG", SDT_LanaiSetFlag, 49 [SDNPOutGlue]>; 50def LanaiSubbF : SDNode<"LanaiISD::SUBBF", SDT_LanaiSetFlag, 51 [SDNPOutGlue, SDNPInGlue]>; 52def LanaiBrCC : SDNode<"LanaiISD::BR_CC", SDT_LanaiBrCC, 53 [SDNPHasChain, SDNPInGlue]>; 54def LanaiSelectCC : SDNode<"LanaiISD::SELECT_CC", SDT_LanaiSelectCC, 55 [SDNPInGlue]>; 56def LanaiSetCC : SDNode<"LanaiISD::SETCC", SDT_LanaiSetCC, 57 [SDNPInGlue]>; 58def LanaiHi : SDNode<"LanaiISD::HI", SDTIntUnaryOp>; 59def LanaiLo : SDNode<"LanaiISD::LO", SDTIntUnaryOp>; 60def LanaiSmall : SDNode<"LanaiISD::SMALL", SDTIntUnaryOp>; 61def LanaiAdjDynAlloc : SDNode<"LanaiISD::ADJDYNALLOC", SDT_LanaiAdjDynAlloc>; 62 63// Extract bits 0-15 (low-end) of an immediate value. 64def LO16 : SDNodeXForm<imm, [{ 65 return CurDAG->getTargetConstant((uint64_t)N->getZExtValue() & 0xffff, 66 SDLoc(N), MVT::i32); 67}]>; 68 69// Extract bits 16-31 (high-end) of an immediate value. 70// Transformation function: shift the immediate value down into the low bits. 71def HI16 : SDNodeXForm<imm, [{ 72 return CurDAG->getTargetConstant((uint64_t)N->getZExtValue() >> 16, SDLoc(N), 73 MVT::i32); 74}]>; 75 76def NEG : SDNodeXForm<imm, [{ 77 return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N), MVT::i32); 78}]>; 79 80def LO21 : SDNodeXForm<imm, [{ 81 return CurDAG->getTargetConstant((uint64_t)N->getZExtValue() & 0x1fffff, 82 SDLoc(N), MVT::i32); 83}]>; 84 85// Branch targets 86def BrTargetAsmOperand : AsmOperandClass { 87 let Name = "BrTarget"; 88} 89def BrTarget : Operand<OtherVT> { 90 let ParserMatchClass = BrTargetAsmOperand; 91 let EncoderMethod = "getBranchTargetOpValue"; 92 let DecoderMethod = "decodeBranch"; 93} 94 95def CallTargetAsmOperand : AsmOperandClass { 96 let Name = "CallTarget"; 97} 98def CallTarget : Operand<i32> { 99 let ParserMatchClass = CallTargetAsmOperand; 100 let EncoderMethod = "getBranchTargetOpValue"; 101 let DecoderMethod = "decodeBranch"; 102} 103 104def ImmShiftAsmOperand : AsmOperandClass { let Name = "ImmShift"; } 105def immShift : Operand<i32>, PatLeaf<(imm), [{ 106 int Imm = N->getSExtValue(); 107 return Imm >= -31 && Imm <= 31;}]> { 108 let ParserMatchClass = ImmShiftAsmOperand; 109 let DecoderMethod = "decodeShiftImm"; 110} 111 112def Imm10AsmOperand : AsmOperandClass { let Name = "Imm10"; } 113def imm10 : Operand<i32>, PatLeaf<(imm), [{ 114 return isInt<10>(N->getSExtValue()); }]> { 115 let ParserMatchClass = Imm10AsmOperand; 116} 117 118def LoImm16AsmOperand : AsmOperandClass { let Name = "LoImm16"; } 119def i32lo16z : Operand<i32>, PatLeaf<(i32 imm), [{ 120 // i32lo16 predicate - true if the 32-bit immediate has only rightmost 16 121 // bits set. 122 return ((N->getZExtValue() & 0xFFFFUL) == N->getZExtValue());}], LO16> { 123 let ParserMatchClass = LoImm16AsmOperand; 124} 125def i32neg16 : Operand<i32>, PatLeaf<(i32 imm), [{ 126 // i32neg16 predicate - true if the 32-bit immediate is negative and can 127 // be represented by a 16 bit integer. 128 int Imm = N->getSExtValue(); 129 return (Imm < 0) && (isInt<16>(Imm));}], LO16> { 130 let ParserMatchClass = LoImm16AsmOperand; 131} 132def i32lo16s : Operand<i32>, PatLeaf<(i32 imm), [{ 133 // i32lo16 predicate - true if the 32-bit immediate has only rightmost 16 134 // bits set. 135 return ((int64_t)(N->getSExtValue() & 0xFFFFUL) == N->getSExtValue());}], LO16> { 136 let ParserMatchClass = LoImm16AsmOperand; 137} 138 139def LoImm16AndAsmOperand : AsmOperandClass { let Name = "LoImm16And"; } 140def i32lo16and : Operand<i32>, PatLeaf<(i32 imm), [{ 141 // i32lo16 predicate - true if the 32-bit immediate has the rightmost 16 142 // bits set and the leftmost 16 bits 1's. 143 return (N->getZExtValue() >= 0xFFFF0000UL);}], LO16> { 144 let ParserMatchClass = LoImm16AndAsmOperand; 145 let PrintMethod = "printLo16AndImmOperand"; 146} 147 148def HiImm16AsmOperand : AsmOperandClass { let Name = "HiImm16"; } 149def i32hi16 : Operand<i32>, PatLeaf<(i32 imm), [{ 150 // i32hi16 predicate - true if the 32-bit immediate has only leftmost 16 151 // bits set. 152 return ((N->getZExtValue() & 0xFFFF0000UL) == N->getZExtValue());}], HI16> { 153 let ParserMatchClass = HiImm16AsmOperand; 154 let PrintMethod = "printHi16ImmOperand"; 155} 156 157def HiImm16AndAsmOperand : AsmOperandClass { let Name = "HiImm16And"; } 158def i32hi16and : Operand<i32>, PatLeaf<(i32 imm), [{ 159 // i32lo16 predicate - true if the 32-bit immediate has the leftmost 16 160 // bits set and the rightmost 16 bits 1's. 161 return ((N->getZExtValue() & 0xFFFFUL) == 0xFFFFUL);}], HI16> { 162 let ParserMatchClass = HiImm16AndAsmOperand; 163 let PrintMethod = "printHi16AndImmOperand"; 164} 165 166def LoImm21AsmOperand : AsmOperandClass { let Name = "LoImm21"; } 167def i32lo21 : Operand<i32>, PatLeaf<(i32 imm), [{ 168 // i32lo21 predicate - true if the 32-bit immediate has only rightmost 21 169 // bits set. 170 return ((N->getZExtValue() & 0x1FFFFFUL) == N->getZExtValue());}], LO21> { 171 let ParserMatchClass = LoImm21AsmOperand; 172} 173 174def AluOp : Operand<i32> { 175 let PrintMethod = "printAluOperand"; 176} 177 178// Addressing modes. 179def ADDRrr : ComplexPattern<i32, 3, "selectAddrRr", [], []>; 180def ADDRri : ComplexPattern<i32, 3, "selectAddrRi", [frameindex], []>; 181def ADDRsls : ComplexPattern<i32, 1, "selectAddrSls", [frameindex], []>; 182def ADDRspls : ComplexPattern<i32, 3, "selectAddrSpls", [frameindex], []>; 183 184// Address operands 185def MemRegImmAsmOperand : AsmOperandClass { 186 let Name = "MemRegImm"; 187 let ParserMethod = "parseMemoryOperand"; 188} 189def MEMri : Operand<i32> { 190 let DecoderMethod = "decodeRiMemoryValue"; 191 let EncoderMethod = "getRiMemoryOpValue"; 192 let MIOperandInfo = (ops GPR:$base, i32lo16s:$offset, AluOp:$Opcode); 193 let ParserMatchClass = MemRegImmAsmOperand; 194 let PrintMethod = "printMemRiOperand"; 195} 196 197def MemRegRegAsmOperand : AsmOperandClass { 198 let Name = "MemRegReg"; 199 let ParserMethod = "parseMemoryOperand"; 200} 201def MEMrr : Operand<i32> { 202 let DecoderMethod = "decodeRrMemoryValue"; 203 let EncoderMethod = "getRrMemoryOpValue"; 204 let MIOperandInfo = (ops GPR:$Op1, GPR:$Op2, AluOp:$Opcode); 205 let ParserMatchClass = MemRegRegAsmOperand; 206 let PrintMethod = "printMemRrOperand"; 207} 208 209def MemImmAsmOperand : AsmOperandClass { 210 let Name = "MemImm"; 211 let ParserMethod = "parseMemoryOperand"; 212} 213def MEMi : Operand<i32> { 214 let MIOperandInfo = (ops i32lo21:$offset); 215 let ParserMatchClass = MemImmAsmOperand; 216 let PrintMethod = "printMemImmOperand"; 217} 218 219def MemSplsAsmOperand : AsmOperandClass { 220 let Name = "MemSpls"; 221 let ParserMethod = "parseMemoryOperand"; 222} 223def MEMspls : Operand<i32> { 224 let DecoderMethod = "decodeSplsValue"; 225 let EncoderMethod = "getSplsOpValue"; 226 let MIOperandInfo = (ops GPR:$base, imm10:$offset, AluOp:$Opcode); 227 let ParserMatchClass = MemSplsAsmOperand; 228 let PrintMethod = "printMemSplsOperand"; 229} 230 231def CCOp : Operand<i32> { 232 let PrintMethod = "printCCOperand"; 233} 234 235// Predicate operand. Default to 0 = true. 236def CondCodeOperand : AsmOperandClass { let Name = "CondCode"; } 237 238def pred : PredicateOperand<i32, (ops i32imm), (ops (i32 0))> { 239 let PrintMethod = "printPredicateOperand"; 240 let ParserMatchClass = CondCodeOperand; 241 let DecoderMethod = "decodePredicateOperand"; 242} 243 244let hasSideEffects = 0, Inst = 0x00000001 in 245 def NOP : InstLanai<(outs), (ins), "nop", []>; 246 247// Special NOPs to change logging level in vlanai. 248let hasSideEffects = 0, Inst = 0x00000002 in 249 def LOG0 : InstLanai<(outs), (ins), "log_0", []>; 250let hasSideEffects = 0, Inst = 0x00000003 in 251 def LOG1 : InstLanai<(outs), (ins), "log_1", []>; 252let hasSideEffects = 0, Inst = 0x00000004 in 253 def LOG2 : InstLanai<(outs), (ins), "log_2", []>; 254let hasSideEffects = 0, Inst = 0x00000005 in 255 def LOG3 : InstLanai<(outs), (ins), "log_3", []>; 256let hasSideEffects = 0, Inst = 0x00000006 in 257 def LOG4 : InstLanai<(outs), (ins), "log_4", []>; 258 259// Map an SPLS instruction onto itself. All other instructions will be mapped 260// onto -1. Used to identify SPLS instructions. 261def splsIdempotent : InstrMapping { 262 let FilterClass = "InstSPLS"; 263 let RowFields = ["AsmString"]; 264 let ColFields = ["PostEncoderMethod"]; 265 let KeyCol = ["adjustPqBitsSpls"]; 266 let ValueCols = [["adjustPqBitsSpls"]]; 267} 268 269// -------------------------------------------------- // 270// ALU instructions 271// -------------------------------------------------- // 272multiclass ALUbase<bits<3> subOp, string AsmStr, SDNode OpNode, 273 PatLeaf LoExt, PatLeaf HiExt, 274 list<dag> loPattern, list<dag> hiPattern> { 275 // Register Immediate 276 let H = 0 in 277 def LO : InstRI<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, LoExt:$imm16), 278 !strconcat(AsmStr, "\t$Rs1, $imm16, $Rd"), 279 loPattern>; 280 let H = 1 in 281 def HI : InstRI<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, HiExt:$imm16), 282 !strconcat(AsmStr, "\t$Rs1, $imm16, $Rd"), 283 hiPattern>; 284 285} 286 287multiclass ALUarith<bits<3> subOp, string AsmStr, SDNode OpNode, 288 PatLeaf LoExt, PatLeaf HiExt> { 289 defm I_ : ALUbase<subOp, AsmStr, OpNode, LoExt, HiExt, [], []>; 290 291 // Register Register 292 let JJJJJ = 0 in 293 def R : InstRR<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, GPR:$Rs2, pred:$DDDI), 294 !strconcat(AsmStr, "$DDDI\t$Rs1, $Rs2, $Rd"), 295 [(set GPR:$Rd, (OpNode GPR:$Rs1, GPR:$Rs2))]>; 296} 297 298multiclass ALUlogic<bits<3> subOp, string AsmStr, SDNode OpNode, 299 PatLeaf LoExt, PatLeaf HiExt> { 300 defm I_ : ALUbase<subOp, AsmStr, OpNode, LoExt, HiExt, 301 [(set GPR:$Rd, (OpNode GPR:$Rs1, LoExt:$imm16))], 302 [(set GPR:$Rd, (OpNode GPR:$Rs1, HiExt:$imm16))]>; 303 304 // Register Register 305 let JJJJJ = 0 in 306 def R : InstRR<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, GPR:$Rs2, pred:$DDDI), 307 !strconcat(AsmStr, "$DDDI\t$Rs1, $Rs2, $Rd"), 308 [(set GPR:$Rd, (OpNode GPR:$Rs1, GPR:$Rs2))]>; 309} 310 311// Non flag setting ALU operations 312let isAsCheapAsAMove = 1, F = 0 in { 313 let isCommutable = 1 in { 314 defm ADD_ : ALUarith<0b000, "add", add, i32lo16z, i32hi16>; 315 } 316 defm SUB_ : ALUarith<0b010, "sub", sub, i32lo16z, i32hi16>; 317 let isCommutable = 1 in { 318 defm AND_ : ALUlogic<0b100, "and", and, i32lo16and, i32hi16and>; 319 defm OR_ : ALUlogic<0b101, "or", or, i32lo16z, i32hi16>; 320 defm XOR_ : ALUlogic<0b110, "xor", xor, i32lo16z, i32hi16>; 321 } 322} 323 324def : Pat<(add GPR:$Rs1, i32lo16z:$imm), 325 (ADD_I_LO GPR:$Rs1, i32lo16z:$imm)>; 326 327def : Pat<(sub GPR:$Rs1, i32lo16z:$imm), 328 (SUB_I_LO GPR:$Rs1, i32lo16z:$imm)>; 329 330def : Pat<(add GPR:$Rs1, i32hi16:$imm), 331 (ADD_I_HI GPR:$Rs1, i32hi16:$imm)>; 332 333def : Pat<(sub GPR:$Rs1, i32hi16:$imm), 334 (SUB_I_HI GPR:$Rs1, i32hi16:$imm)>; 335 336def : Pat<(i32 i32lo16and:$imm), (AND_I_LO (i32 R1), i32lo16and:$imm)>; 337def : Pat<(i32 i32hi16and:$imm), (AND_I_HI (i32 R1), i32hi16and:$imm)>; 338 339// Change add/sub with negative number to sub/add 340def : Pat<(add GPR:$Rs1, i32neg16:$imm), 341 (SUB_I_LO GPR:$Rs1, (NEG $imm))>; 342def : Pat<(sub GPR:$Rs1, i32neg16:$imm), 343 (ADD_I_LO GPR:$Rs1, (NEG $imm))>; 344 345// Flag (incl. carry) setting addition and subtraction 346let F = 1, Defs = [SR] in { 347 defm ADD_F_ : ALUarith<0b000, "add.f", addc, i32lo16z, i32hi16>; 348 defm SUB_F_ : ALUarith<0b010, "sub.f", subc, i32lo16z, i32hi16>; 349} 350 351def : Pat<(addc GPR:$Rs1, i32lo16z:$imm), 352 (ADD_F_I_LO GPR:$Rs1, i32lo16z:$imm)>; 353 354def : Pat<(subc GPR:$Rs1, i32lo16z:$imm), 355 (SUB_F_I_LO GPR:$Rs1, i32lo16z:$imm)>; 356 357def : Pat<(addc GPR:$Rs1, i32hi16:$imm), 358 (ADD_F_I_HI GPR:$Rs1, i32hi16:$imm)>; 359 360def : Pat<(subc GPR:$Rs1, i32hi16:$imm), 361 (SUB_F_I_HI GPR:$Rs1, i32hi16:$imm)>; 362 363// Carry using addition and subtraction 364let F = 0, Uses = [SR] in { 365 defm ADDC_ : ALUarith<0b001, "addc", adde, i32lo16z, i32hi16>; 366 defm SUBB_ : ALUarith<0b011, "subb", sube, i32lo16z, i32hi16>; 367} 368 369def : Pat<(adde GPR:$Rs1, i32lo16z:$imm), 370 (ADDC_I_LO GPR:$Rs1, i32lo16z:$imm)>; 371 372def : Pat<(sube GPR:$Rs1, i32lo16z:$imm), 373 (SUBB_I_LO GPR:$Rs1, i32lo16z:$imm)>; 374 375def : Pat<(adde GPR:$Rs1, i32hi16:$imm), 376 (ADDC_I_HI GPR:$Rs1, i32hi16:$imm)>; 377 378def : Pat<(sube GPR:$Rs1, i32hi16:$imm), 379 (SUBB_I_HI GPR:$Rs1, i32hi16:$imm)>; 380 381// Flag setting ALU operations 382let isAsCheapAsAMove = 1, F = 1, Defs = [SR] in { 383 let isCommutable = 1 in { 384 defm AND_F_ : ALUlogic<0b100, "and.f", and, i32lo16and, i32hi16and>; 385 defm OR_F_ : ALUlogic<0b101, "or.f", or, i32lo16z, i32hi16>; 386 defm XOR_F_ : ALUlogic<0b110, "xor.f", xor, i32lo16z, i32hi16>; 387 } 388} 389 390let isAsCheapAsAMove = 1, F = 1, Defs = [SR], Uses = [SR] in { 391 defm ADDC_F_ : ALUarith<0b001, "addc.f", adde, i32lo16z, i32hi16>; 392 defm SUBB_F_ : ALUarith<0b011, "subb.f", sube, i32lo16z, i32hi16>; 393} 394 395def : Pat<(LanaiSubbF GPR:$Rs1, GPR:$Rs2), 396 (SUBB_F_R GPR:$Rs1, GPR:$Rs2)>; 397 398def : Pat<(LanaiSubbF GPR:$Rs1, i32lo16z:$imm), 399 (SUBB_F_I_LO GPR:$Rs1, i32lo16z:$imm)>; 400 401def : Pat<(LanaiSubbF GPR:$Rs1, i32hi16:$imm), 402 (SUBB_F_I_HI GPR:$Rs1, i32hi16:$imm)>; 403 404def : InstAlias<"mov $src, $dst", (ADD_R GPR:$dst, GPR:$src, R0, 0)>; 405 406let isAsCheapAsAMove = 1, Rs1 = R0.Num, isCodeGenOnly = 1, H = 1, F = 0, 407 isReMaterializable = 1 in 408 def MOVHI : InstRI<0b000, (outs GPR:$Rd), (ins i32hi16:$imm16), 409 "mov\t$imm16, $Rd", 410 [(set GPR:$Rd, i32hi16:$imm16)]>; 411 412def : InstAlias<"mov $imm16, $dst", (ADD_I_LO GPR:$dst, R0, i32lo16z:$imm16)>; 413def : InstAlias<"mov $imm16, $dst", (ADD_I_HI GPR:$dst, R0, i32hi16:$imm16)>; 414def : InstAlias<"mov $imm16, $dst", 415 (AND_I_LO GPR:$dst, R1, i32lo16and:$imm16)>; 416def : InstAlias<"mov $imm16, $dst", 417 (AND_I_HI GPR:$dst, R1, i32hi16and:$imm16)>; 418 419// Shift instructions 420class ShiftRI<string AsmStr, list<dag> Pattern> 421 : InstRI<0b111, (outs GPR:$Rd), (ins GPR:$Rs1, immShift:$imm16), 422 !strconcat(AsmStr, "\t$Rs1, $imm16, $Rd"), Pattern> { 423 let isReMaterializable = 1; 424} 425 426let F = 0 in { 427 let H = 0 in 428 def SL_I : ShiftRI<"sh", [(set GPR:$Rd, (shl GPR:$Rs1, immShift:$imm16))]>; 429 let H = 1 in 430 def SA_I : ShiftRI<"sha", []>; 431} 432def : Pat<(srl GPR:$Rs1, immShift:$imm), (SL_I GPR:$Rs1, (NEG $imm))>; 433def : Pat<(sra GPR:$Rs1, immShift:$imm), (SA_I GPR:$Rs1, (NEG $imm))>; 434 435let F = 1, Defs = [SR] in { 436 let H = 0 in 437 def SL_F_I : ShiftRI<"sh.f", []>; 438 let H = 1 in 439 def SA_F_I : ShiftRI<"sha.f", []>; 440} 441 442class ShiftRR<string AsmStr, list<dag> Pattern> 443 : InstRR<0b111, (outs GPR:$Rd), (ins GPR:$Rs1, GPR:$Rs2, pred:$DDDI), AsmStr, 444 Pattern>; 445 446let F = 0 in { 447 let JJJJJ = 0b10000 in 448 def SHL_R : ShiftRR<"sh$DDDI\t$Rs1, $Rs2, $Rd", 449 [(set GPR:$Rd, (shl GPR:$Rs1, GPR:$Rs2))]>; 450 let isCodeGenOnly = 1 in { 451 let JJJJJ = 0b10000 in 452 def SRL_R : ShiftRR<"sh$DDDI\t$Rs1, $Rs2, $Rd", []>; 453 } 454 let JJJJJ = 0b11000 in 455 def SRA_R : ShiftRR<"sha$DDDI\t$Rs1, $Rs2, $Rd", []>; 456} 457 458let F = 1, Defs = [SR] in { 459 let JJJJJ = 0b10000 in 460 def SHL_F_R : ShiftRR<"sh.f$DDDI\t$Rs1, $Rs2, $Rd", []>; 461 let isCodeGenOnly = 1 in { 462 let JJJJJ = 0b10000 in 463 def SRL_F_R : ShiftRR<"sh.f$DDDI\t$Rs1, $Rs2, $Rd", []>; 464 } 465 let JJJJJ = 0b11000 in 466 def SRA_F_R : ShiftRR<"sha.f$DDDI\t$Rs1, $Rs2, $Rd", []>; 467} 468 469// Expand shift-right operations 470def : Pat<(srl GPR:$Rs1, GPR:$Rs2), 471 (SRL_R GPR:$Rs1, (SUB_R R0, GPR:$Rs2))>; 472def : Pat<(sra GPR:$Rs1, GPR:$Rs2), 473 (SRA_R GPR:$Rs1, (SUB_R R0, GPR:$Rs2))>; 474 475// -------------------------------------------------- // 476// LOAD instructions 477// -------------------------------------------------- // 478 479class LoadRR<string OpcString, PatFrag OpNode, ValueType Ty> 480 : InstRRM<0b0, (outs GPR:$Rd), (ins MEMrr:$src), 481 !strconcat(OpcString, "\t$src, $Rd"), 482 [(set (Ty GPR:$Rd), (OpNode ADDRrr:$src))]>, 483 Sched<[WriteLD]> { 484 bits<20> src; 485 486 let Rs1 = src{19-15}; 487 let Rs2 = src{14-10}; 488 let P = src{9}; 489 let Q = src{8}; 490 let BBB = src{7-5}; 491 let JJJJJ = src{4-0}; 492 let mayLoad = 1; 493} 494 495class LoadRI<string OpcString, PatFrag OpNode, ValueType Ty> 496 : InstRM<0b0, (outs GPR:$Rd), (ins MEMri:$src), 497 !strconcat(OpcString, "\t$src, $Rd"), 498 [(set (Ty GPR:$Rd), (OpNode ADDRri:$src))]>, 499 Sched<[WriteLD]> { 500 bits<23> src; 501 502 let Itinerary = IIC_LD; 503 let Rs1 = src{22-18}; 504 let P = src{17}; 505 let Q = src{16}; 506 let imm16 = src{15-0}; 507 let isReMaterializable = 1; 508 let mayLoad = 1; 509} 510 511let E = 0 in { 512 let YL = 0b01 in { 513 // uld is used here and ld in the alias as the alias is printed out first if 514 // an alias exist 515 def LDW_RI : LoadRI<"uld", load, i32>; 516 def LDW_RR : LoadRR<"ld", load, i32>; 517 } 518} 519 520def : InstAlias<"ld $src, $dst", (LDW_RI GPR:$dst, MEMri:$src)>; 521 522let E = 1 in { 523 let YL = 0b01 in { 524 def LDWz_RR : LoadRR<"uld", zextloadi32, i32>; 525 } 526} 527 528let E = 1 in { 529 let YL = 0b00 in 530 def LDHz_RR : LoadRR<"uld.h", zextloadi16, i32>; 531 let YL = 0b10 in 532 def LDBz_RR : LoadRR<"uld.b", zextloadi8, i32>; 533} 534 535let E = 0 in { 536 let YL = 0b00 in 537 def LDHs_RR : LoadRR<"ld.h", sextloadi16, i32>; 538 let YL = 0b10 in 539 def LDBs_RR : LoadRR<"ld.b", sextloadi8, i32>; 540} 541 542def LDADDR : InstSLS<0x0, (outs GPR:$Rd), (ins MEMi:$src), 543 "ld\t$src, $Rd", 544 [(set (i32 GPR:$Rd), (load ADDRsls:$src))]>, 545 Sched<[WriteLD]> { 546 bits<21> src; 547 548 let Itinerary = IIC_LD; 549 let msb = src{20-16}; 550 let lsb = src{15-0}; 551 let isReMaterializable = 1; 552 let mayLoad = 1; 553} 554 555class LoadSPLS<string asmstring, PatFrag opNode> 556 : InstSPLS<(outs GPR:$Rd), (ins MEMspls:$src), 557 !strconcat(asmstring, "\t$src, $Rd"), 558 [(set (i32 GPR:$Rd), (opNode ADDRspls:$src))]>, 559 Sched<[WriteLDSW]> { 560 bits<17> src; 561 let Itinerary = IIC_LDSW; 562 let Rs1 = src{16-12}; 563 let P = src{11}; 564 let Q = src{10}; 565 let imm10 = src{9-0}; 566 let mayLoad = 1; 567 let isReMaterializable = 1; 568} 569 570let Y = 0, S = 0, E = 1 in 571 def LDHz_RI : LoadSPLS<"uld.h", zextloadi16>; 572 573let Y = 0, S = 0, E = 0 in 574 def LDHs_RI : LoadSPLS<"ld.h", sextloadi16>; 575 576let Y = 1, S = 0, E = 1 in 577 def LDBz_RI : LoadSPLS<"uld.b", zextloadi8>; 578 579let Y = 1, S = 0, E = 0 in 580 def LDBs_RI : LoadSPLS<"ld.b", sextloadi8>; 581 582def SLI : InstSLI<(outs GPR:$Rd), (ins i32lo21:$imm), 583 "mov\t$imm, $Rd", 584 [(set GPR:$Rd, i32lo21:$imm)]> { 585 bits<21> imm; 586 587 let msb = imm{20-16}; 588 let lsb = imm{15-0}; 589 let isReMaterializable = 1; 590 let isAsCheapAsAMove = 1; 591} 592 593// -------------------------------------------------- // 594// STORE instructions 595// -------------------------------------------------- // 596 597class StoreRR<string OpcString, PatFrag OpNode, ValueType Ty> 598 : InstRRM<0b1, (outs), (ins GPR:$Rd, MEMrr:$dst), 599 !strconcat(OpcString, "\t$Rd, $dst"), 600 [(OpNode (Ty GPR:$Rd), ADDRrr:$dst)]>, 601 Sched<[WriteST]> { 602 bits<20> dst; 603 604 let Itinerary = IIC_ST; 605 let Rs1 = dst{19-15}; 606 let Rs2 = dst{14-10}; 607 let P = dst{9}; 608 let Q = dst{8}; 609 let BBB = dst{7-5}; 610 let JJJJJ = dst{4-0}; 611 let mayStore = 1; 612} 613 614class StoreRI<string OpcString, PatFrag OpNode, ValueType Ty> 615 : InstRM<0b1, (outs), (ins GPR:$Rd, MEMri:$dst), 616 !strconcat(OpcString, "\t$Rd, $dst"), 617 [(OpNode (Ty GPR:$Rd), ADDRri:$dst)]>, 618 Sched<[WriteST]> { 619 bits<23> dst; 620 621 let Itinerary = IIC_ST; 622 let Rs1 = dst{22-18}; 623 let P = dst{17}; 624 let Q = dst{16}; 625 let imm16 = dst{15-0}; 626 let mayStore = 1; 627} 628 629let YL = 0b01, E = 0 in { 630 def SW_RR : StoreRR<"st", store, i32>; 631 def SW_RI : StoreRI<"st", store, i32>; 632} 633 634let E = 0 in { 635 let YL = 0b00 in 636 def STH_RR : StoreRR<"st.h", truncstorei16, i32>; 637 let YL = 0b10 in 638 def STB_RR : StoreRR<"st.b", truncstorei8, i32>; 639} 640 641def STADDR : InstSLS<0x1, (outs), (ins GPR:$Rd, MEMi:$dst), 642 "st\t$Rd, $dst", 643 [(store (i32 GPR:$Rd), ADDRsls:$dst)]>, 644 Sched<[WriteST]> { 645 bits<21> dst; 646 647 let Itinerary = IIC_ST; 648 let msb = dst{20-16}; 649 let lsb = dst{15-0}; 650 let mayStore = 1; 651} 652 653class StoreSPLS<string asmstring, PatFrag opNode> 654 : InstSPLS<(outs), (ins GPR:$Rd, MEMspls:$dst), 655 !strconcat(asmstring, "\t$Rd, $dst"), 656 [(opNode (i32 GPR:$Rd), ADDRspls:$dst)]>, 657 Sched<[WriteSTSW]> { 658 bits<17> dst; 659 660 let Itinerary = IIC_STSW; 661 let Rs1 = dst{16-12}; 662 let P = dst{11}; 663 let Q = dst{10}; 664 let imm10 = dst{9-0}; 665 let mayStore = 1; 666} 667 668let Y = 0, S = 1, E = 0 in 669 def STH_RI : StoreSPLS<"st.h", truncstorei16>; 670 671let Y = 1, S = 1, E = 0 in 672 def STB_RI : StoreSPLS<"st.b", truncstorei8>; 673 674// -------------------------------------------------- // 675// BRANCH instructions 676// -------------------------------------------------- // 677 678let isBranch = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1 in { 679 def BT : InstBR<(outs), (ins BrTarget:$addr), 680 "bt\t$addr", 681 [(br bb:$addr)]> { 682 let DDDI = 0b0000; 683 } 684 let Uses = [SR] in 685 def BRCC : InstBR<(outs), (ins BrTarget:$addr, CCOp:$DDDI), 686 "b$DDDI\t$addr", 687 [(LanaiBrCC bb:$addr, imm:$DDDI)]>; 688 689 let isIndirectBranch = 1 in { 690 def JR : InstRR<0b101, (outs), (ins GPR:$Rs2), "bt\t$Rs2", 691 [(brind GPR:$Rs2)]> { 692 let Rs1 = R0.Num; 693 let Rd = R2.Num; 694 let F = 0; 695 let JJJJJ = 0; 696 let DDDI = 0; 697 } 698 } 699} 700 701// -------------------------------------------------- // 702// Condition/SF instructions 703// -------------------------------------------------- // 704 705// Instructions to set flags used in lowering comparisons. 706multiclass SF<bits<3> op2Val, string AsmStr> { 707 let F = 1, Rd = R0.Num, JJJJJ = 0, Defs = [SR], DDDI = 0 in 708 def _RR : InstRR<op2Val, (outs), (ins GPR:$Rs1, GPR:$Rs2), 709 !strconcat(AsmStr, "\t$Rs1, $Rs2, %r0"), 710 [(LanaiSetFlag (i32 GPR:$Rs1), (i32 GPR:$Rs2))]>; 711 let F = 1, Rd = R0.Num, H = 0, Defs = [SR] in 712 def _RI_LO : InstRI<op2Val, (outs), (ins GPR:$Rs1, i32lo16z:$imm16), 713 !strconcat(AsmStr, "\t$Rs1, $imm16, %r0"), 714 [(LanaiSetFlag (i32 GPR:$Rs1), i32lo16z:$imm16)]>; 715 let F = 1, Rd = R0.Num, H = 1, Defs = [SR] in 716 def _RI_HI : InstRI<op2Val, (outs), (ins GPR:$Rs1, i32hi16:$imm16), 717 !strconcat(AsmStr, "\t$Rs1, $imm16, %r0"), 718 [(LanaiSetFlag (i32 GPR:$Rs1), i32hi16:$imm16)]>; 719} 720let isCodeGenOnly = 1, isCompare = 1 in { 721 defm SFSUB_F : SF<0b010, "sub.f">; 722} 723 724// Jump and link 725let isCall = 1, hasDelaySlot = 1, isCodeGenOnly = 1, Uses = [SP], 726 Defs = [RCA] in { 727 def CALL : Pseudo<(outs), (ins CallTarget:$addr), "", []>; 728 def CALLR : Pseudo<(outs), (ins GPR:$Rs1), "", [(Call GPR:$Rs1)]>; 729} 730 731let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1, 732 Uses = [RCA] in { 733 def RET : InstRM<0b0, (outs), (ins), 734 "ld\t-4[%fp], %pc ! return", 735 [(RetFlag)]> { 736 let Rd = PC.Num; 737 let Rs1 = FP.Num; 738 let P = 1; 739 let Q = 0; 740 let imm16 = -4; 741 742 // Post encoding is not needed for RET. 743 let PostEncoderMethod = ""; 744 } 745} 746 747// ADJCALLSTACKDOWN/UP implicitly use/def SP because they may be expanded into 748// a stack adjustment and the codegen must know that they may modify the stack 749// pointer before prolog-epilog rewriting occurs. 750// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become 751// sub / add which can clobber SP. 752let Defs = [SP], Uses = [SP] in { 753 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 754 "#ADJCALLSTACKDOWN $amt1 $amt2", 755 [(CallSeqStart timm:$amt1, timm:$amt2)]>; 756 def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 757 "#ADJCALLSTACKUP $amt1 $amt2", 758 [(CallSeqEnd timm:$amt1, timm:$amt2)]>; 759} 760 761let Defs = [SP], Uses = [SP] in { 762 def ADJDYNALLOC : Pseudo<(outs GPR:$dst), (ins GPR:$src), 763 "#ADJDYNALLOC $dst $src", 764 [(set GPR:$dst, (LanaiAdjDynAlloc GPR:$src))]>; 765} 766 767let Uses = [SR] in { 768 def SCC : InstSCC<(outs GPR:$Rs1), (ins CCOp:$DDDI), 769 "s$DDDI\t$Rs1", 770 [(set (i32 GPR:$Rs1), (LanaiSetCC imm:$DDDI))]>; 771} 772 773// Select with hardware support 774let Uses = [SR], isSelect = 1 in { 775 def SELECT : InstRR<0b111, (outs GPR:$Rd), 776 (ins GPR:$Rs1, GPR:$Rs2, CCOp:$DDDI), 777 "sel.$DDDI $Rs1, $Rs2, $Rd", 778 [(set (i32 GPR:$Rd), 779 (LanaiSelectCC (i32 GPR:$Rs1), (i32 GPR:$Rs2), 780 (imm:$DDDI)))]> { 781 let JJJJJ = 0; 782 let F = 0; 783 } 784} 785 786let isBranch = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1, 787 isIndirectBranch = 1, Uses = [SR] in { 788 def BRIND_CC : InstRR<0b101, (outs), (ins GPR:$Rs1, CCOp:$DDDI), 789 "b$DDDI\t$Rs1", []> { 790 let F = 0; 791 let JJJJJ = 0; 792 let Rd = PC.Num; 793 let Rs2 = R0.Num; 794 } 795 796 def BRIND_CCA : InstRR<0b101, (outs), (ins GPR:$Rs1, GPR:$Rs2, CCOp:$DDDI), 797 "b${DDDI}\t$Rs1 add $Rs2", []> { 798 let F = 0; 799 let Rd = PC.Num; 800 let JJJJJ = 0; 801 } 802} 803 804// TODO: This only considers the case where BROFF is an immediate and not where 805// it is a register. Add support for register relative branching. 806let isBranch = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1, Rs1 = 0, 807 Uses = [SR] in 808 def BRR : InstBRR<(outs), (ins i16imm:$imm16, CCOp:$DDDI), 809 "b${DDDI}.r\t$imm16", []>; 810 811let F = 0 in { 812// Population Count (POPC) 813def POPC: InstSpecial<0b001, (outs GPR:$Rd), (ins GPR:$Rs1), 814 "popc\t$Rs1, $Rd", 815 [(set GPR:$Rd, (ctpop GPR:$Rs1))]>; 816 817// Count Leading Zeros (LEADZ) 818def LEADZ: InstSpecial<0b010, (outs GPR:$Rd), (ins GPR:$Rs1), 819 "leadz\t$Rs1, $Rd", [(set GPR:$Rd, (ctlz GPR:$Rs1))]>; 820 821// Count Trailing Zeros (TRAILZ) 822def TRAILZ : InstSpecial<0b011, (outs GPR:$Rd), (ins GPR:$Rs1), 823 "trailz\t$Rs1, $Rd", 824 [(set GPR:$Rd, (cttz GPR:$Rs1))]>; 825} 826 827//===----------------------------------------------------------------------===// 828// Non-Instruction Patterns 829//===----------------------------------------------------------------------===// 830 831// unsigned 16-bit immediate 832def : Pat<(i32 i32lo16z:$imm), (OR_I_LO (i32 R0), imm:$imm)>; 833 834// arbitrary immediate 835def : Pat<(i32 imm:$imm), (OR_I_LO (MOVHI (HI16 imm:$imm)), (LO16 imm:$imm))>; 836 837// Calls 838def : Pat<(Call tglobaladdr:$dst), (CALL tglobaladdr:$dst)>; 839def : Pat<(Call texternalsym:$dst), (CALL texternalsym:$dst)>; 840 841// Loads 842def : Pat<(extloadi8 ADDRspls:$src), (i32 (LDBz_RI ADDRspls:$src))>; 843def : Pat<(extloadi16 ADDRspls:$src), (i32 (LDHz_RI ADDRspls:$src))>; 844// Loads up to 32-bits are already atomic. 845// TODO: This is a workaround for a particular failing case and should be 846// handled more generally. 847def : Pat<(atomic_load_8 ADDRspls:$src), (i32 (LDBz_RI ADDRspls:$src))>; 848 849// GlobalAddress, ExternalSymbol, Jumptable, ConstantPool 850def : Pat<(LanaiHi tglobaladdr:$dst), (MOVHI tglobaladdr:$dst)>; 851def : Pat<(LanaiLo tglobaladdr:$dst), (OR_I_LO (i32 R0), tglobaladdr:$dst)>; 852def : Pat<(LanaiSmall tglobaladdr:$dst), (SLI tglobaladdr:$dst)>; 853def : Pat<(LanaiHi texternalsym:$dst), (MOVHI texternalsym:$dst)>; 854def : Pat<(LanaiLo texternalsym:$dst), (OR_I_LO (i32 R0), texternalsym:$dst)>; 855def : Pat<(LanaiSmall texternalsym:$dst), (SLI texternalsym:$dst)>; 856def : Pat<(LanaiHi tblockaddress:$dst), (MOVHI tblockaddress:$dst)>; 857def : Pat<(LanaiLo tblockaddress:$dst), (OR_I_LO (i32 R0), tblockaddress:$dst)>; 858def : Pat<(LanaiSmall tblockaddress:$dst), (SLI tblockaddress:$dst)>; 859def : Pat<(LanaiHi tjumptable:$dst), (MOVHI tjumptable:$dst)>; 860def : Pat<(LanaiLo tjumptable:$dst), (OR_I_LO (i32 R0), tjumptable:$dst)>; 861def : Pat<(LanaiSmall tjumptable:$dst), (SLI tjumptable:$dst)>; 862def : Pat<(LanaiHi tconstpool:$dst), (MOVHI tconstpool:$dst)>; 863def : Pat<(LanaiLo tconstpool:$dst), (OR_I_LO (i32 R0), tconstpool:$dst)>; 864def : Pat<(LanaiSmall tconstpool:$dst), (SLI tconstpool:$dst)>; 865 866def : Pat<(or GPR:$hi, (LanaiLo tglobaladdr:$lo)), 867 (OR_I_LO GPR:$hi, tglobaladdr:$lo)>; 868def : Pat<(or R0, (LanaiSmall tglobaladdr:$small)), 869 (SLI tglobaladdr:$small)>; 870def : Pat<(or GPR:$hi, (LanaiLo texternalsym:$lo)), 871 (OR_I_LO GPR:$hi, texternalsym:$lo)>; 872def : Pat<(or R0, (LanaiSmall texternalsym:$small)), 873 (SLI texternalsym:$small)>; 874def : Pat<(or GPR:$hi, (LanaiLo tblockaddress:$lo)), 875 (OR_I_LO GPR:$hi, tblockaddress:$lo)>; 876def : Pat<(or R0, (LanaiSmall tblockaddress:$small)), 877 (SLI tblockaddress:$small)>; 878def : Pat<(or GPR:$hi, (LanaiLo tjumptable:$lo)), 879 (OR_I_LO GPR:$hi, tjumptable:$lo)>; 880def : Pat<(or R0, (LanaiSmall tjumptable:$small)), 881 (SLI tjumptable:$small)>; 882def : Pat<(or GPR:$hi, (LanaiLo tconstpool:$lo)), 883 (OR_I_LO GPR:$hi, tconstpool:$lo)>; 884def : Pat<(or R0, (LanaiSmall tconstpool:$small)), 885 (SLI tconstpool:$small)>; 886