1//===-- AVRInstrInfo.td - AVR Instruction defs -------------*- tablegen -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file describes the AVR instructions in TableGen format. 11// 12//===----------------------------------------------------------------------===// 13 14include "AVRInstrFormats.td" 15 16//===----------------------------------------------------------------------===// 17// AVR Type Profiles 18//===----------------------------------------------------------------------===// 19 20def SDT_AVRCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i16>]>; 21def SDT_AVRCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i16>, SDTCisVT<1, i16>]>; 22def SDT_AVRCall : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; 23def SDT_AVRWrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; 24def SDT_AVRBrcond : SDTypeProfile<0, 2, 25 [SDTCisVT<0, OtherVT>, SDTCisVT<1, i8>]>; 26def SDT_AVRCmp : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>; 27def SDT_AVRTst : SDTypeProfile<0, 1, [SDTCisInt<0>]>; 28def SDT_AVRSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, 29 SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>; 30 31//===----------------------------------------------------------------------===// 32// AVR Specific Node Definitions 33//===----------------------------------------------------------------------===// 34 35def AVRretflag : SDNode<"AVRISD::RET_FLAG", SDTNone, 36 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; 37def AVRretiflag : SDNode<"AVRISD::RETI_FLAG", SDTNone, 38 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; 39 40def AVRcallseq_start : SDNode<"ISD::CALLSEQ_START", SDT_AVRCallSeqStart, 41 [SDNPHasChain, SDNPOutGlue]>; 42def AVRcallseq_end : SDNode<"ISD::CALLSEQ_END", SDT_AVRCallSeqEnd, 43 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; 44 45def AVRcall : SDNode<"AVRISD::CALL", SDT_AVRCall, 46 [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, SDNPVariadic]>; 47 48def AVRWrapper : SDNode<"AVRISD::WRAPPER", SDT_AVRWrapper>; 49 50def AVRbrcond : SDNode<"AVRISD::BRCOND", SDT_AVRBrcond, 51 [SDNPHasChain, SDNPInGlue]>; 52def AVRcmp : SDNode<"AVRISD::CMP", SDT_AVRCmp, [SDNPOutGlue]>; 53def AVRcmpc : SDNode<"AVRISD::CMPC", SDT_AVRCmp, [SDNPInGlue, SDNPOutGlue]>; 54def AVRtst : SDNode<"AVRISD::TST", SDT_AVRTst, [SDNPOutGlue]>; 55def AVRselectcc: SDNode<"AVRISD::SELECT_CC", SDT_AVRSelectCC, [SDNPInGlue]>; 56 57// Shift nodes. 58def AVRlsl : SDNode<"AVRISD::LSL", SDTIntUnaryOp>; 59def AVRlsr : SDNode<"AVRISD::LSR", SDTIntUnaryOp>; 60def AVRrol : SDNode<"AVRISD::ROL", SDTIntUnaryOp>; 61def AVRror : SDNode<"AVRISD::ROR", SDTIntUnaryOp>; 62def AVRasr : SDNode<"AVRISD::ASR", SDTIntUnaryOp>; 63 64// Pseudo shift nodes for non-constant shift amounts. 65def AVRlslLoop : SDNode<"AVRISD::LSLLOOP", SDTIntShiftOp>; 66def AVRlsrLoop : SDNode<"AVRISD::LSRLOOP", SDTIntShiftOp>; 67def AVRasrLoop : SDNode<"AVRISD::ASRLOOP", SDTIntShiftOp>; 68 69//===----------------------------------------------------------------------===// 70// AVR Operands, Complex Patterns and Transformations Definitions. 71//===----------------------------------------------------------------------===// 72 73def imm8_neg_XFORM : SDNodeXForm<imm, 74[{ 75 return CurDAG->getTargetConstant(-N->getAPIntValue(), SDLoc(N), MVT::i8); 76}]>; 77 78def imm16_neg_XFORM : SDNodeXForm<imm, 79[{ 80 return CurDAG->getTargetConstant(-N->getAPIntValue(), SDLoc(N), MVT::i16); 81}]>; 82 83def imm0_63_neg : PatLeaf<(imm), 84[{ 85 int64_t val = -N->getSExtValue(); 86 return val >= 0 && val < 64; 87}], imm16_neg_XFORM>; 88 89def uimm6 : PatLeaf<(imm), [{ return isUInt<6>(N->getZExtValue()); }]>; 90 91def ioaddr_XFORM : SDNodeXForm<imm, 92[{ 93 return CurDAG->getTargetConstant(uint8_t(N->getZExtValue()) - 0x20, SDLoc(N), MVT::i8); 94}]>; 95 96def iobitpos8_XFORM : SDNodeXForm<imm, 97[{ 98 return CurDAG->getTargetConstant(Log2_32(uint8_t(N->getZExtValue())), 99 SDLoc(N), MVT::i8); 100}]>; 101 102def iobitposn8_XFORM : SDNodeXForm<imm, 103[{ 104 return CurDAG->getTargetConstant(Log2_32(uint8_t(~N->getZExtValue())), 105 SDLoc(N), MVT::i8); 106}]>; 107 108def ioaddr8 : PatLeaf<(imm), 109[{ 110 uint64_t val = N->getZExtValue(); 111 return val >= 0x20 && val < 0x60; 112}], ioaddr_XFORM>; 113 114def lowioaddr8 : PatLeaf<(imm), 115[{ 116 uint64_t val = N->getZExtValue(); 117 return val >= 0x20 && val < 0x40; 118}], ioaddr_XFORM>; 119 120def ioaddr16 : PatLeaf<(imm), 121[{ 122 uint64_t val = N->getZExtValue(); 123 return val >= 0x20 && val < 0x5f; 124}], ioaddr_XFORM>; 125 126def iobitpos8 : PatLeaf<(imm), 127[{ 128 return isPowerOf2_32(uint8_t(N->getZExtValue())); 129}], iobitpos8_XFORM>; 130 131def iobitposn8 : PatLeaf<(imm), 132[{ 133 return isPowerOf2_32(uint8_t(~N->getZExtValue())); 134}], iobitposn8_XFORM>; 135 136def MemriAsmOperand : AsmOperandClass { 137 let Name = "Memri"; 138 let ParserMethod = "parseMemriOperand"; 139} 140 141/// Address operand for `reg+imm` used by STD and LDD. 142def memri : Operand<iPTR> 143{ 144 let MIOperandInfo = (ops PTRDISPREGS, i16imm); 145 146 let PrintMethod = "printMemri"; 147 let EncoderMethod = "encodeMemri"; 148 149 let ParserMatchClass = MemriAsmOperand; 150} 151 152// Address operand for `SP+imm` used by STD{W}SPQRr 153def memspi : Operand<iPTR> 154{ 155 let MIOperandInfo = (ops GPRSP, i16imm); 156} 157 158def i8imm_com : Operand<i8> 159{ 160 let EncoderMethod = "encodeComplement"; 161 162 let MIOperandInfo = (ops i8imm); 163} 164 165def relbrtarget_7 : Operand<OtherVT> 166{ 167 let PrintMethod = "printPCRelImm"; 168 let EncoderMethod = "encodeRelCondBrTarget<AVR::fixup_7_pcrel>"; 169} 170 171def brtarget_13 : Operand<OtherVT> 172{ 173 let PrintMethod = "printPCRelImm"; 174 let EncoderMethod = "encodeRelCondBrTarget<AVR::fixup_13_pcrel>"; 175} 176 177// The target of a 22 or 16-bit call/jmp instruction. 178def call_target : Operand<iPTR> 179{ 180 let EncoderMethod = "encodeCallTarget"; 181} 182 183// Addressing mode pattern reg+imm6 184def addr : ComplexPattern<iPTR, 2, "SelectAddr", [], [SDNPWantRoot]>; 185 186// AsmOperand class for a pointer register. 187// Used with the LD/ST family of instructions. 188// See FSTLD in AVRInstrFormats.td 189def PtrRegAsmOperand : AsmOperandClass 190{ 191 let Name = "Reg"; 192} 193 194// A special operand type for the LD/ST instructions. 195// It converts the pointer register number into a two-bit field used in the 196// instruction. 197def LDSTPtrReg : Operand<i16> 198{ 199 let MIOperandInfo = (ops PTRREGS); 200 let EncoderMethod = "encodeLDSTPtrReg"; 201 202 let ParserMatchClass = PtrRegAsmOperand; 203} 204 205// A special operand type for the LDD/STD instructions. 206// It behaves identically to the LD/ST version, except restricts 207// the pointer registers to Y and Z. 208def LDDSTDPtrReg : Operand<i16> 209{ 210 let MIOperandInfo = (ops PTRDISPREGS); 211 let EncoderMethod = "encodeLDSTPtrReg"; 212 213 let ParserMatchClass = PtrRegAsmOperand; 214} 215 216//===----------------------------------------------------------------------===// 217// AVR predicates for subtarget features 218//===----------------------------------------------------------------------===// 219 220def HasSRAM : Predicate<"Subtarget->hasSRAM()">, 221 AssemblerPredicate<"FeatureSRAM">; 222 223def HasJMPCALL : Predicate<"Subtarget->hasJMPCALL()">, 224 AssemblerPredicate<"FeatureJMPCALL">; 225 226def HasIJMPCALL : Predicate<"Subtarget->hasIJMPCALL()">, 227 AssemblerPredicate<"FeatureIJMPCALL">; 228 229def HasEIJMPCALL : Predicate<"Subtarget->hasEIJMPCALL()">, 230 AssemblerPredicate<"FeatureEIJMPCALL">; 231 232def HasADDSUBIW : Predicate<"Subtarget->hasADDSUBIW()">, 233 AssemblerPredicate<"FeatureADDSUBIW">; 234 235def HasSmallStack : Predicate<"Subtarget->HasSmallStack()">, 236 AssemblerPredicate<"FeatureSmallStack">; 237 238def HasMOVW : Predicate<"Subtarget->hasMOVW()">, 239 AssemblerPredicate<"FeatureMOVW">; 240 241def HasLPM : Predicate<"Subtarget->hasLPM()">, 242 AssemblerPredicate<"FeatureLPM">; 243 244def HasLPMX : Predicate<"Subtarget->hasLPMX()">, 245 AssemblerPredicate<"FeatureLPMX">; 246 247def HasELPM : Predicate<"Subtarget->hasELPM()">, 248 AssemblerPredicate<"FeatureELPM">; 249 250def HasELPMX : Predicate<"Subtarget->hasELPMX()">, 251 AssemblerPredicate<"FeatureELPMX">; 252 253def HasSPM : Predicate<"Subtarget->hasSPM()">, 254 AssemblerPredicate<"FeatureSPM">; 255 256def HasSPMX : Predicate<"Subtarget->hasSPMX()">, 257 AssemblerPredicate<"FeatureSPMX">; 258 259def HasDES : Predicate<"Subtarget->hasDES()">, 260 AssemblerPredicate<"FeatureDES">; 261 262def SupportsRMW : Predicate<"Subtarget->supportsRMW()">, 263 AssemblerPredicate<"FeatureRMW">; 264 265def SupportsMultiplication : Predicate<"Subtarget->supportsMultiplication()">, 266 AssemblerPredicate<"FeatureMultiplication">; 267 268def HasBREAK : Predicate<"Subtarget->hasBREAK()">, 269 AssemblerPredicate<"FeatureBREAK">; 270 271def HasTinyEncoding : Predicate<"Subtarget->hasTinyEncoding()">, 272 AssemblerPredicate<"FeatureTinyEncoding">; 273 274 275// AVR specific condition code. These correspond to AVR_*_COND in 276// AVRInstrInfo.td. They must be kept in synch. 277def AVR_COND_EQ : PatLeaf<(i8 0)>; 278def AVR_COND_NE : PatLeaf<(i8 1)>; 279def AVR_COND_GE : PatLeaf<(i8 2)>; 280def AVR_COND_LT : PatLeaf<(i8 3)>; 281def AVR_COND_SH : PatLeaf<(i8 4)>; 282def AVR_COND_LO : PatLeaf<(i8 5)>; 283def AVR_COND_MI : PatLeaf<(i8 6)>; 284def AVR_COND_PL : PatLeaf<(i8 7)>; 285 286 287//===----------------------------------------------------------------------===// 288//===----------------------------------------------------------------------===// 289// AVR Instruction list 290//===----------------------------------------------------------------------===// 291//===----------------------------------------------------------------------===// 292 293// ADJCALLSTACKDOWN/UP implicitly use/def SP because they may be expanded into 294// a stack adjustment and the codegen must know that they may modify the stack 295// pointer before prolog-epilog rewriting occurs. 296// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become 297// sub / add which can clobber SREG. 298let Defs = [SP, SREG], 299Uses = [SP] in 300{ 301 def ADJCALLSTACKDOWN : Pseudo<(outs), 302 (ins i16imm:$amt), 303 "#ADJCALLSTACKDOWN", 304 [(AVRcallseq_start timm:$amt)]>; 305 306 // R31R30 is used to update SP, since it is a scratch reg and this instruction 307 // is placed after the function call then R31R30 should be always free. 308 //let Defs = [R31R30], 309 //Uses = [R31R30] in 310 //:TODO: if we enable this, the pseudo is killed because it looks dead 311 def ADJCALLSTACKUP : Pseudo<(outs), 312 (ins i16imm:$amt1, i16imm:$amt2), 313 "#ADJCALLSTACKUP", 314 [(AVRcallseq_end timm:$amt1, timm:$amt2)]>; 315} 316 317//===----------------------------------------------------------------------===// 318// Addition 319//===----------------------------------------------------------------------===// 320let isCommutable = 1, 321Constraints = "$src = $rd", 322Defs = [SREG] in 323{ 324 // ADD Rd, Rr 325 // Adds two 8-bit registers. 326 def ADDRdRr : FRdRr<0b0000, 327 0b11, 328 (outs GPR8:$rd), 329 (ins GPR8:$src, GPR8:$rr), 330 "add\t$rd, $rr", 331 [(set i8:$rd, (add i8:$src, i8:$rr)), 332 (implicit SREG)]>; 333 334 // ADDW Rd+1:Rd, Rr+1:Rr 335 // Pseudo instruction to add four 8-bit registers as two 16-bit values. 336 // 337 // Expands to: 338 // add Rd, Rr 339 // adc Rd+1, Rr+1 340 def ADDWRdRr : Pseudo<(outs DREGS:$rd), 341 (ins DREGS:$src, DREGS:$rr), 342 "addw\t$rd, $rr", 343 [(set i16:$rd, (add i16:$src, i16:$rr)), 344 (implicit SREG)]>; 345 346 // ADC Rd, Rr 347 // Adds two 8-bit registers with carry. 348 let Uses = [SREG] in 349 def ADCRdRr : FRdRr<0b0001, 350 0b11, 351 (outs GPR8:$rd), 352 (ins GPR8:$src, GPR8:$rr), 353 "adc\t$rd, $rr", 354 [(set i8:$rd, (adde i8:$src, i8:$rr)), 355 (implicit SREG)]>; 356 357 // ADCW Rd+1:Rd, Rr+1:Rr 358 // Pseudo instruction to add four 8-bit registers as two 16-bit values with 359 // carry. 360 // 361 // Expands to: 362 // adc Rd, Rr 363 // adc Rd+1, Rr+1 364 let Uses = [SREG] in 365 def ADCWRdRr : Pseudo<(outs DREGS:$rd), 366 (ins DREGS:$src, DREGS:$rr), 367 "adcw\t$rd, $rr", 368 [(set i16:$rd, (adde i16:$src, i16:$rr)), 369 (implicit SREG)]>; 370 371 // AIDW Rd, k 372 // Adds an immediate 6-bit value K to Rd, placing the result in Rd. 373 def ADIWRdK : FWRdK<0b0, 374 (outs IWREGS:$rd), 375 (ins IWREGS:$src, i16imm:$k), 376 "adiw\t$rd, $k", 377 [(set i16:$rd, (add i16:$src, uimm6:$k)), 378 (implicit SREG)]>, 379 Requires<[HasADDSUBIW]>; 380} 381 382//===----------------------------------------------------------------------===// 383// Subtraction 384//===----------------------------------------------------------------------===// 385let Constraints = "$src = $rd", 386Defs = [SREG] in 387{ 388 // SUB Rd, Rr 389 // Subtracts the 8-bit value of Rr from Rd and places the value in Rd. 390 def SUBRdRr : FRdRr<0b0001, 391 0b10, 392 (outs GPR8:$rd), 393 (ins GPR8:$src, GPR8:$rr), 394 "sub\t$rd, $rr", 395 [(set i8:$rd, (sub i8:$src, i8:$rr)), 396 (implicit SREG)]>; 397 398 // SUBW Rd+1:Rd, Rr+1:Rr 399 // Subtracts two 16-bit values and places the result into Rd. 400 // 401 // Expands to: 402 // sub Rd, Rr 403 // sbc Rd+1, Rr+1 404 def SUBWRdRr : Pseudo<(outs DREGS:$rd), 405 (ins DREGS:$src, DREGS:$rr), 406 "subw\t$rd, $rr", 407 [(set i16:$rd, (sub i16:$src, i16:$rr)), 408 (implicit SREG)]>; 409 410 def SUBIRdK : FRdK<0b0101, 411 (outs LD8:$rd), 412 (ins LD8:$src, i8imm:$k), 413 "subi\t$rd, $k", 414 [(set i8:$rd, (sub i8:$src, imm:$k)), 415 (implicit SREG)]>; 416 417 // SUBIW Rd+1:Rd, K+1:K 418 // 419 // Expands to: 420 // subi Rd, K 421 // sbci Rd+1, K+1 422 def SUBIWRdK : Pseudo<(outs DLDREGS:$rd), 423 (ins DLDREGS:$src, i16imm:$rr), 424 "subiw\t$rd, $rr", 425 [(set i16:$rd, (sub i16:$src, imm:$rr)), 426 (implicit SREG)]>; 427 428 def SBIWRdK : FWRdK<0b1, 429 (outs IWREGS:$rd), 430 (ins IWREGS:$src, i16imm:$k), 431 "sbiw\t$rd, $k", 432 [(set i16:$rd, (sub i16:$src, uimm6:$k)), 433 (implicit SREG)]>, 434 Requires<[HasADDSUBIW]>; 435 436 // Subtract with carry operations which must read the carry flag in SREG. 437 let Uses = [SREG] in 438 { 439 def SBCRdRr : FRdRr<0b0000, 440 0b10, 441 (outs GPR8:$rd), 442 (ins GPR8:$src, GPR8:$rr), 443 "sbc\t$rd, $rr", 444 [(set i8:$rd, (sube i8:$src, i8:$rr)), 445 (implicit SREG)]>; 446 447 // SBCW Rd+1:Rd, Rr+1:Rr 448 // 449 // Expands to: 450 // sbc Rd, Rr 451 // sbc Rd+1, Rr+1 452 def SBCWRdRr : Pseudo<(outs DREGS:$rd), 453 (ins DREGS:$src, DREGS:$rr), 454 "sbcw\t$rd, $rr", 455 [(set i16:$rd, (sube i16:$src, i16:$rr)), 456 (implicit SREG)]>; 457 458 def SBCIRdK : FRdK<0b0100, 459 (outs LD8:$rd), 460 (ins LD8:$src, i8imm:$k), 461 "sbci\t$rd, $k", 462 [(set i8:$rd, (sube i8:$src, imm:$k)), 463 (implicit SREG)]>; 464 465 // SBCIW Rd+1:Rd, K+1:K 466 // sbci Rd, K 467 // sbci Rd+1, K+1 468 def SBCIWRdK : Pseudo<(outs DLDREGS:$rd), 469 (ins DLDREGS:$src, i16imm:$rr), 470 "sbciw\t$rd, $rr", 471 [(set i16:$rd, (sube i16:$src, imm:$rr)), 472 (implicit SREG)]>; 473 } 474} 475 476//===----------------------------------------------------------------------===// 477// Increment and Decrement 478//===----------------------------------------------------------------------===// 479let Constraints = "$src = $rd", 480Defs = [SREG] in 481{ 482 def INCRd : FRd<0b1001, 483 0b0100011, 484 (outs GPR8:$rd), 485 (ins GPR8:$src), 486 "inc\t$rd", 487 [(set i8:$rd, (add i8:$src, 1)), (implicit SREG)]>; 488 489 def DECRd : FRd<0b1001, 490 0b0101010, 491 (outs GPR8:$rd), 492 (ins GPR8:$src), 493 "dec\t$rd", 494 [(set i8:$rd, (add i8:$src, -1)), (implicit SREG)]>; 495} 496 497//===----------------------------------------------------------------------===// 498// Multiplication 499//===----------------------------------------------------------------------===// 500 501let isCommutable = 1, 502Defs = [R1, R0, SREG] in 503{ 504 // MUL Rd, Rr 505 // Multiplies Rd by Rr and places the result into R1:R0. 506 let usesCustomInserter = 1 in { 507 def MULRdRr : FRdRr<0b1001, 0b11, 508 (outs), 509 (ins GPR8:$lhs, GPR8:$rhs), 510 "mul\t$lhs, $rhs", 511 [/*(set R1, R0, (smullohi i8:$lhs, i8:$rhs))*/]>, 512 Requires<[SupportsMultiplication]>; 513 514 def MULSRdRr : FMUL2RdRr<0, 515 (outs), 516 (ins GPR8:$lhs, GPR8:$rhs), 517 "muls\t$lhs, $rhs", 518 []>, 519 Requires<[SupportsMultiplication]>; 520 } 521 522 def MULSURdRr : FMUL2RdRr<1, 523 (outs), 524 (ins GPR8:$lhs, GPR8:$rhs), 525 "mulsu\t$lhs, $rhs", 526 []>, 527 Requires<[SupportsMultiplication]>; 528 529 def FMUL : FFMULRdRr<0b01, 530 (outs), 531 (ins GPR8:$lhs, GPR8:$rhs), 532 "fmul\t$lhs, $rhs", 533 []>, 534 Requires<[SupportsMultiplication]>; 535 536 def FMULS : FFMULRdRr<0b10, 537 (outs), 538 (ins GPR8:$lhs, GPR8:$rhs), 539 "fmuls\t$lhs, $rhs", 540 []>, 541 Requires<[SupportsMultiplication]>; 542 543 def FMULSU : FFMULRdRr<0b11, 544 (outs), 545 (ins GPR8:$lhs, GPR8:$rhs), 546 "fmulsu\t$lhs, $rhs", 547 []>, 548 Requires<[SupportsMultiplication]>; 549} 550 551let Defs = [R15, R14, R13, R12, R11, R10, R9, 552 R8, R7, R6, R5, R4, R3, R2, R1, R0] in 553def DESK : FDES<(outs), 554 (ins i8imm:$k), 555 "des\t$k", 556 []>, 557 Requires<[HasDES]>; 558 559//===----------------------------------------------------------------------===// 560// Logic 561//===----------------------------------------------------------------------===// 562let Constraints = "$src = $rd", 563Defs = [SREG] in 564{ 565 // Register-Register logic instructions (which have the 566 // property of commutativity). 567 let isCommutable = 1 in 568 { 569 def ANDRdRr : FRdRr<0b0010, 570 0b00, 571 (outs GPR8:$rd), 572 (ins GPR8:$src, GPR8:$rr), 573 "and\t$rd, $rr", 574 [(set i8:$rd, (and i8:$src, i8:$rr)), 575 (implicit SREG)]>; 576 577 // ANDW Rd+1:Rd, Rr+1:Rr 578 // 579 // Expands to: 580 // and Rd, Rr 581 // and Rd+1, Rr+1 582 def ANDWRdRr : Pseudo<(outs DREGS:$rd), 583 (ins DREGS:$src, DREGS:$rr), 584 "andw\t$rd, $rr", 585 [(set i16:$rd, (and i16:$src, i16:$rr)), 586 (implicit SREG)]>; 587 588 def ORRdRr : FRdRr<0b0010, 589 0b10, 590 (outs GPR8:$rd), 591 (ins GPR8:$src, GPR8:$rr), 592 "or\t$rd, $rr", 593 [(set i8:$rd, (or i8:$src, i8:$rr)), 594 (implicit SREG)]>; 595 596 // ORW Rd+1:Rd, Rr+1:Rr 597 // 598 // Expands to: 599 // or Rd, Rr 600 // or Rd+1, Rr+1 601 def ORWRdRr : Pseudo<(outs DREGS:$rd), 602 (ins DREGS:$src, DREGS:$rr), 603 "orw\t$rd, $rr", 604 [(set i16:$rd, (or i16:$src, i16:$rr)), 605 (implicit SREG)]>; 606 607 def EORRdRr : FRdRr<0b0010, 608 0b01, 609 (outs GPR8:$rd), 610 (ins GPR8:$src, GPR8:$rr), 611 "eor\t$rd, $rr", 612 [(set i8:$rd, (xor i8:$src, i8:$rr)), 613 (implicit SREG)]>; 614 615 // EORW Rd+1:Rd, Rr+1:Rr 616 // 617 // Expands to: 618 // eor Rd, Rr 619 // eor Rd+1, Rr+1 620 def EORWRdRr : Pseudo<(outs DREGS:$rd), 621 (ins DREGS:$src, DREGS:$rr), 622 "eorw\t$rd, $rr", 623 [(set i16:$rd, (xor i16:$src, i16:$rr)), 624 (implicit SREG)]>; 625 } 626 627 def ANDIRdK : FRdK<0b0111, 628 (outs LD8:$rd), 629 (ins LD8:$src, i8imm:$k), 630 "andi\t$rd, $k", 631 [(set i8:$rd, (and i8:$src, imm:$k)), 632 (implicit SREG)]>; 633 634 // ANDI Rd+1:Rd, K+1:K 635 // 636 // Expands to: 637 // andi Rd, K 638 // andi Rd+1, K+1 639 def ANDIWRdK : Pseudo<(outs DLDREGS:$rd), 640 (ins DLDREGS:$src, i16imm:$k), 641 "andiw\t$rd, $k", 642 [(set i16:$rd, (and i16:$src, imm:$k)), 643 (implicit SREG)]>; 644 645 def ORIRdK : FRdK<0b0110, 646 (outs LD8:$rd), 647 (ins LD8:$src, i8imm:$k), 648 "ori\t$rd, $k", 649 [(set i8:$rd, (or i8:$src, imm:$k)), 650 (implicit SREG)]>; 651 652 // ORIW Rd+1:Rd, K+1,K 653 // 654 // Expands to: 655 // ori Rd, K 656 // ori Rd+1, K+1 657 def ORIWRdK : Pseudo<(outs DLDREGS:$rd), 658 (ins DLDREGS:$src, i16imm:$rr), 659 "oriw\t$rd, $rr", 660 [(set i16:$rd, (or i16:$src, imm:$rr)), 661 (implicit SREG)]>; 662} 663 664//===----------------------------------------------------------------------===// 665// One's/Two's Compliment 666//===----------------------------------------------------------------------===// 667let Constraints = "$src = $rd", 668Defs = [SREG] in 669{ 670 def COMRd : FRd<0b1001, 671 0b0100000, 672 (outs GPR8:$rd), 673 (ins GPR8:$src), 674 "com\t$rd", 675 [(set i8:$rd, (not i8:$src)), (implicit SREG)]>; 676 677 // COMW Rd+1:Rd 678 // 679 // Expands to: 680 // com Rd 681 // com Rd+1 682 def COMWRd : Pseudo<(outs DREGS:$rd), 683 (ins DREGS:$src), 684 "comw\t$rd", 685 [(set i16:$rd, (not i16:$src)), (implicit SREG)]>; 686 687 //:TODO: optimize NEG for wider types 688 def NEGRd : FRd<0b1001, 689 0b0100001, 690 (outs GPR8:$rd), 691 (ins GPR8:$src), 692 "neg\t$rd", 693 [(set i8:$rd, (ineg i8:$src)), (implicit SREG)]>; 694} 695 696// TST Rd 697// Test for zero of minus. 698// This operation is identical to a `Rd AND Rd`. 699//def : InstAlias<"tst\t$rd", (ANDRdRr GPR8:$rd, GPR8:$rd), 1>; 700 701let Defs = [SREG] in 702def TSTRd : FTST<0b0010, 703 0b00, 704 (outs), 705 (ins GPR8:$rd), 706 "tst\t$rd", 707 [(AVRtst i8:$rd)]>; 708 709//===----------------------------------------------------------------------===// 710// Jump instructions 711//===----------------------------------------------------------------------===// 712let isBarrier = 1, 713isBranch = 1, 714isTerminator = 1 in 715{ 716 def RJMPk : FBRk<0, 717 (outs), 718 (ins brtarget_13:$target), 719 "rjmp\t$target", 720 [(br bb:$target)]>; 721 722 let isIndirectBranch = 1, 723 Uses = [R31R30] in 724 def IJMP : F16<0b1001010000001001, 725 (outs), 726 (ins), 727 "ijmp", 728 []>, 729 Requires<[HasIJMPCALL]>; 730 731 let isIndirectBranch = 1, 732 Uses = [R31R30] in 733 def EIJMP : F16<0b1001010000011001, 734 (outs), 735 (ins), 736 "eijmp", 737 []>, 738 Requires<[HasEIJMPCALL]>; 739 740 def JMPk : F32BRk<0b110, 741 (outs), 742 (ins call_target:$k), 743 "jmp\t$k", 744 []>, 745 Requires<[HasJMPCALL]>; 746} 747 748//===----------------------------------------------------------------------===// 749// Call instructions 750//===----------------------------------------------------------------------===// 751let isCall = 1 in 752{ 753 // SP is marked as a use to prevent stack-pointer assignments that appear 754 // immediately before calls from potentially appearing dead. 755 let Uses = [SP] in 756 def RCALLk : FBRk<1, 757 (outs), 758 (ins brtarget_13:$target), 759 "rcall\t$target", 760 []>; 761 762 // SP is marked as a use to prevent stack-pointer assignments that appear 763 // immediately before calls from potentially appearing dead. 764 let Uses = [SP, R31R30] in 765 def ICALL : F16<0b1001010100001001, 766 (outs), 767 (ins variable_ops), 768 "icall", 769 []>, 770 Requires<[HasIJMPCALL]>; 771 772 // SP is marked as a use to prevent stack-pointer assignments that appear 773 // immediately before calls from potentially appearing dead. 774 let Uses = [SP, R31R30] in 775 def EICALL : F16<0b1001010100011001, 776 (outs), 777 (ins variable_ops), 778 "eicall", 779 []>, 780 Requires<[HasEIJMPCALL]>; 781 782 // SP is marked as a use to prevent stack-pointer assignments that appear 783 // immediately before calls from potentially appearing dead. 784 // 785 //:TODO: the imm field can be either 16 or 22 bits in devices with more 786 // than 64k of ROM, fix it once we support the largest devices. 787 let Uses = [SP] in 788 def CALLk : F32BRk<0b111, 789 (outs), 790 (ins call_target:$k), 791 "call\t$k", 792 [(AVRcall imm:$k)]>, 793 Requires<[HasJMPCALL]>; 794} 795 796//===----------------------------------------------------------------------===// 797// Return instructions. 798//===----------------------------------------------------------------------===// 799let isTerminator = 1, 800isReturn = 1, 801isBarrier = 1 in 802{ 803 def RET : F16<0b1001010100001000, 804 (outs), 805 (ins), 806 "ret", 807 [(AVRretflag)]>; 808 809 def RETI : F16<0b1001010100011000, 810 (outs), 811 (ins), 812 "reti", 813 [(AVRretiflag)]>; 814} 815 816//===----------------------------------------------------------------------===// 817// Compare operations. 818//===----------------------------------------------------------------------===// 819let Defs = [SREG] in 820{ 821 // CPSE Rd, Rr 822 // Compare Rd and Rr, skipping the next instruction if they are equal. 823 let isBarrier = 1, 824 isBranch = 1, 825 isTerminator = 1 in 826 def CPSE : FRdRr<0b0001, 827 0b00, 828 (outs), 829 (ins GPR8:$rd, GPR8:$rr), 830 "cpse\t$rd, $rr", 831 []>; 832 833 def CPRdRr : FRdRr<0b0001, 834 0b01, 835 (outs), 836 (ins GPR8:$rd, GPR8:$rr), 837 "cp\t$rd, $rr", 838 [(AVRcmp i8:$rd, i8:$rr), (implicit SREG)]>; 839 840 // CPW Rd+1:Rd, Rr+1:Rr 841 // 842 // Expands to: 843 // cp Rd, Rr 844 // cpc Rd+1, Rr+1 845 def CPWRdRr : Pseudo<(outs), 846 (ins DREGS:$src, DREGS:$src2), 847 "cpw\t$src, $src2", 848 [(AVRcmp i16:$src, i16:$src2), (implicit SREG)]>; 849 850 let Uses = [SREG] in 851 def CPCRdRr : FRdRr<0b0000, 852 0b01, 853 (outs), 854 (ins GPR8:$rd, GPR8:$rr), 855 "cpc\t$rd, $rr", 856 [(AVRcmpc i8:$rd, i8:$rr), (implicit SREG)]>; 857 858 // CPCW Rd+1:Rd. Rr+1:Rr 859 // 860 // Expands to: 861 // cpc Rd, Rr 862 // cpc Rd+1, Rr+1 863 let Uses = [SREG] in 864 def CPCWRdRr : Pseudo<(outs), 865 (ins DREGS:$src, DREGS:$src2), 866 "cpcw\t$src, $src2", 867 [(AVRcmpc i16:$src, i16:$src2), (implicit SREG)]>; 868 869 // CPI Rd, K 870 // Compares a register with an 8 bit immediate. 871 let Uses = [SREG] in 872 def CPIRdK : FRdK<0b0011, 873 (outs), 874 (ins GPR8:$rd, i8imm:$k), 875 "cpi\t$rd, $k", 876 [(AVRcmp i8:$rd, imm:$k), (implicit SREG)]>; 877} 878 879//===----------------------------------------------------------------------===// 880// Register conditional skipping/branching operations. 881//===----------------------------------------------------------------------===// 882let isBranch = 1, 883isTerminator = 1 in 884{ 885 // Conditional skipping on GPR register bits, and 886 // conditional skipping on IO register bits. 887 let isBarrier = 1 in 888 { 889 def SBRCRrB : FRdB<0b10, 890 (outs), 891 (ins GPR8:$rr, i8imm:$b), 892 "sbrc\t$rr, $b", 893 []>; 894 895 def SBRSRrB : FRdB<0b11, 896 (outs), 897 (ins GPR8:$rr, i8imm:$b), 898 "sbrs\t$rr, $b", 899 []>; 900 901 def SBICAb : FIOBIT<0b01, 902 (outs), 903 (ins i16imm:$a, i8imm:$b), 904 "sbic\t$a, $b", 905 []>; 906 907 def SBISAb : FIOBIT<0b11, 908 (outs), 909 (ins i16imm:$a, i8imm:$b), 910 "sbis\t$a, $b", 911 []>; 912 } 913 914 // Relative branches on status flag bits. 915 let Uses = [SREG] in 916 { 917 // BRBS s, k 918 // Branch if `s` flag in status register is set. 919 def BRBSsk : FSK<0, 920 (outs), 921 (ins i8imm:$s, relbrtarget_7:$k), 922 "brbs\t$s, $k", 923 []>; 924 925 // BRBC s, k 926 // Branch if `s` flag in status register is clear. 927 def BRBCsk : FSK<1, 928 (outs), 929 (ins i8imm:$s, relbrtarget_7:$k), 930 "brbc\t$s, $k", 931 []>; 932 } 933} 934 935 936// BRCS k 937// Branch if carry flag is set 938def : InstAlias<"brcs\t$k", (BRBSsk 0, relbrtarget_7:$k)>; 939 940// BRCC k 941// Branch if carry flag is clear 942def : InstAlias<"brcc\t$k", (BRBCsk 0, relbrtarget_7:$k)>; 943 944// BRHS k 945// Branch if half carry flag is set 946def : InstAlias<"brhs\t$k", (BRBSsk 5, relbrtarget_7:$k)>; 947 948// BRHC k 949// Branch if half carry flag is clear 950def : InstAlias<"brhc\t$k", (BRBCsk 5, relbrtarget_7:$k)>; 951 952// BRTS k 953// Branch if the T flag is set 954def : InstAlias<"brts\t$k", (BRBSsk 6, relbrtarget_7:$k)>; 955 956// BRTC k 957// Branch if the T flag is clear 958def : InstAlias<"brtc\t$k", (BRBCsk 6, relbrtarget_7:$k)>; 959 960// BRVS k 961// Branch if the overflow flag is set 962def : InstAlias<"brvs\t$k", (BRBSsk 3, relbrtarget_7:$k)>; 963 964// BRVC k 965// Branch if the overflow flag is clear 966def : InstAlias<"brvc\t$k", (BRBCsk 3, relbrtarget_7:$k)>; 967 968// BRIE k 969// Branch if the global interrupt flag is enabled 970def : InstAlias<"brie\t$k", (BRBSsk 7, relbrtarget_7:$k)>; 971 972// BRID k 973// Branch if the global interrupt flag is disabled 974def : InstAlias<"brid\t$k", (BRBCsk 7, relbrtarget_7:$k)>; 975 976//===----------------------------------------------------------------------===// 977// PC-relative conditional branches 978//===----------------------------------------------------------------------===// 979// Based on status register. We cannot simplify these into instruction aliases 980// because we also need to be able to specify a pattern to match for ISel. 981let isBranch = 1, 982isTerminator = 1, 983Uses = [SREG] in 984{ 985 def BREQk : FBRsk<0, 986 0b001, 987 (outs), 988 (ins relbrtarget_7:$target), 989 "breq\t$target", 990 [(AVRbrcond bb:$target, AVR_COND_EQ)]>; 991 992 def BRNEk : FBRsk<1, 993 0b001, 994 (outs), 995 (ins relbrtarget_7:$target), 996 "brne\t$target", 997 [(AVRbrcond bb:$target, AVR_COND_NE)]>; 998 999 1000 def BRSHk : FBRsk<1, 1001 0b000, 1002 (outs), 1003 (ins relbrtarget_7:$target), 1004 "brsh\t$target", 1005 [(AVRbrcond bb:$target, AVR_COND_SH)]>; 1006 1007 def BRLOk : FBRsk<0, 1008 0b000, 1009 (outs), 1010 (ins relbrtarget_7:$target), 1011 "brlo\t$target", 1012 [(AVRbrcond bb:$target, AVR_COND_LO)]>; 1013 1014 def BRMIk : FBRsk<0, 1015 0b010, 1016 (outs), 1017 (ins relbrtarget_7:$target), 1018 "brmi\t$target", 1019 [(AVRbrcond bb:$target, AVR_COND_MI)]>; 1020 1021 def BRPLk : FBRsk<1, 1022 0b010, 1023 (outs), 1024 (ins relbrtarget_7:$target), 1025 "brpl\t$target", 1026 [(AVRbrcond bb:$target, AVR_COND_PL)]>; 1027 1028 def BRGEk : FBRsk<1, 1029 0b100, 1030 (outs), 1031 (ins relbrtarget_7:$target), 1032 "brge\t$target", 1033 [(AVRbrcond bb:$target, AVR_COND_GE)]>; 1034 1035 def BRLTk : FBRsk<0, 1036 0b100, 1037 (outs), 1038 (ins relbrtarget_7:$target), 1039 "brlt\t$target", 1040 [(AVRbrcond bb:$target, AVR_COND_LT)]>; 1041} 1042 1043//===----------------------------------------------------------------------===// 1044// Data transfer instructions 1045//===----------------------------------------------------------------------===// 1046// 8 and 16-bit register move instructions. 1047let hasSideEffects = 0 in 1048{ 1049 def MOVRdRr : FRdRr<0b0010, 1050 0b11, 1051 (outs GPR8:$rd), 1052 (ins GPR8:$rr), 1053 "mov\t$rd, $rr", 1054 []>; 1055 1056 def MOVWRdRr : FMOVWRdRr<(outs DREGS:$dst), 1057 (ins DREGS:$src), 1058 "movw\t$dst, $src", 1059 []>, 1060 Requires<[HasMOVW]>; 1061} 1062 1063// Load immediate values into registers. 1064let isReMaterializable = 1 in 1065{ 1066 def LDIRdK : FRdK<0b1110, 1067 (outs LD8:$rd), 1068 (ins i8imm:$k), 1069 "ldi\t$rd, $k", 1070 [(set i8:$rd, imm:$k)]>; 1071 1072 // LDIW Rd+1:Rd, K+1:K 1073 // 1074 // Expands to: 1075 // ldi Rd, K 1076 // ldi Rd+1, K+1 1077 def LDIWRdK : Pseudo<(outs DLDREGS:$dst), 1078 (ins i16imm:$src), 1079 "ldiw\t$dst, $src", 1080 [(set i16:$dst, imm:$src)]>; 1081} 1082 1083// Load from data space into register. 1084let canFoldAsLoad = 1, 1085isReMaterializable = 1 in 1086{ 1087 def LDSRdK : F32DM<0b0, 1088 (outs GPR8:$rd), 1089 (ins i16imm:$k), 1090 "lds\t$rd, $k", 1091 [(set i8:$rd, (load imm:$k))]>, 1092 Requires<[HasSRAM]>; 1093 1094 // LDSW Rd+1:Rd, K+1:K 1095 // 1096 // Expands to: 1097 // lds Rd, (K+1:K) 1098 // lds Rd+1 (K+1:K) + 1 1099 def LDSWRdK : Pseudo<(outs DREGS:$dst), 1100 (ins i16imm:$src), 1101 "ldsw\t$dst, $src", 1102 [(set i16:$dst, (load imm:$src))]>, 1103 Requires<[HasSRAM]>; 1104} 1105 1106// Indirect loads. 1107let canFoldAsLoad = 1, 1108isReMaterializable = 1 in 1109{ 1110 def LDRdPtr : FSTLD<0, 1111 0b00, 1112 (outs GPR8:$reg), 1113 (ins LDSTPtrReg:$ptrreg), 1114 "ld\t$reg, $ptrreg", 1115 [(set GPR8:$reg, (load i16:$ptrreg))]>, 1116 Requires<[HasSRAM]>; 1117 1118 // LDW Rd+1:Rd, P 1119 // 1120 // Expands to: 1121 // ld Rd, P+ 1122 // ld Rd+1, P+ 1123 let Constraints = "@earlyclobber $reg" in 1124 def LDWRdPtr : Pseudo<(outs DREGS:$reg), 1125 (ins PTRDISPREGS:$ptrreg), 1126 "ldw\t$reg, $ptrreg", 1127 [(set i16:$reg, (load i16:$ptrreg))]>, 1128 Requires<[HasSRAM]>; 1129} 1130 1131// Indirect loads (with postincrement or predecrement). 1132let mayLoad = 1, 1133hasSideEffects = 0, 1134Constraints = "$ptrreg = $base_wb,@earlyclobber $reg,@earlyclobber $base_wb" in 1135{ 1136 def LDRdPtrPi : FSTLD<0, 1137 0b01, 1138 (outs GPR8:$reg, PTRREGS:$base_wb), 1139 (ins LDSTPtrReg:$ptrreg), 1140 "ld\t$reg, $ptrreg+", 1141 []>, 1142 Requires<[HasSRAM]>; 1143 1144 // LDW Rd+1:Rd, P+ 1145 // Expands to: 1146 // ld Rd, P+ 1147 // ld Rd+1, P+ 1148 def LDWRdPtrPi : Pseudo<(outs DREGS:$reg, PTRREGS:$base_wb), 1149 (ins PTRREGS:$ptrreg), 1150 "ldw\t$reg, $ptrreg+", 1151 []>, 1152 Requires<[HasSRAM]>; 1153 1154 def LDRdPtrPd : FSTLD<0, 1155 0b10, 1156 (outs GPR8:$reg, PTRREGS:$base_wb), 1157 (ins LDSTPtrReg:$ptrreg), 1158 "ld\t$reg, -$ptrreg", 1159 []>, 1160 Requires<[HasSRAM]>; 1161 1162 // LDW Rd+1:Rd, -P 1163 // 1164 // Expands to: 1165 // ld Rd+1, -P 1166 // ld Rd, -P 1167 def LDWRdPtrPd : Pseudo<(outs DREGS:$reg, PTRREGS:$base_wb), 1168 (ins PTRREGS:$ptrreg), 1169 "ldw\t$reg, -$ptrreg", 1170 []>, 1171 Requires<[HasSRAM]>; 1172} 1173 1174// Load indirect with displacement operations. 1175let canFoldAsLoad = 1, 1176isReMaterializable = 1 in 1177{ 1178 def LDDRdPtrQ : FSTDLDD<0, 1179 (outs GPR8:$reg), 1180 (ins memri:$memri), 1181 "ldd\t$reg, $memri", 1182 [(set i8:$reg, (load addr:$memri))]>, 1183 Requires<[HasSRAM]>; 1184 1185 // LDDW Rd+1:Rd, P+q 1186 // 1187 // Expands to: 1188 // ldd Rd, P+q 1189 // ldd Rd+1, P+q+1 1190 let Constraints = "@earlyclobber $dst" in 1191 def LDDWRdPtrQ : Pseudo<(outs DREGS:$dst), 1192 (ins memri:$memri), 1193 "lddw\t$dst, $memri", 1194 [(set i16:$dst, (load addr:$memri))]>, 1195 Requires<[HasSRAM]>; 1196 1197 //:FIXME: remove this once PR13375 gets fixed 1198 // Bug report: https://llvm.org/bugs/show_bug.cgi?id=13375 1199 let mayLoad = 1, 1200 hasSideEffects = 0 in 1201 def LDDWRdYQ : Pseudo<(outs DREGS:$dst), 1202 (ins memri:$memri), 1203 "lddw\t$dst, $memri", 1204 []>, 1205 Requires<[HasSRAM]>; 1206} 1207 1208// Indirect store from register to data space. 1209def STSKRr : F32DM<0b1, 1210 (outs), 1211 (ins i16imm:$k, GPR8:$rd), 1212 "sts\t$k, $rd", 1213 [(store i8:$rd, imm:$k)]>, 1214 Requires<[HasSRAM]>; 1215 1216// STSW K+1:K, Rr+1:Rr 1217// 1218// Expands to: 1219// sts Rr+1, (K+1:K) + 1 1220// sts Rr, (K+1:K) 1221def STSWKRr : Pseudo<(outs), 1222 (ins i16imm:$dst, DREGS:$src), 1223 "stsw\t$dst, $src", 1224 [(store i16:$src, imm:$dst)]>, 1225 Requires<[HasSRAM]>; 1226 1227// Indirect stores. 1228// ST P, Rr 1229// Stores the value of Rr into the location addressed by pointer P. 1230def STPtrRr : FSTLD<1, 1231 0b00, 1232 (outs), 1233 (ins LDSTPtrReg:$ptrreg, GPR8:$reg), 1234 "st\t$ptrreg, $reg", 1235 [(store GPR8:$reg, i16:$ptrreg)]>, 1236 Requires<[HasSRAM]>; 1237 1238// STW P, Rr+1:Rr 1239// Stores the value of Rr into the location addressed by pointer P. 1240// 1241// Expands to: 1242// st P, Rr 1243// std P+1, Rr+1 1244def STWPtrRr : Pseudo<(outs), 1245 (ins PTRDISPREGS:$ptrreg, DREGS:$reg), 1246 "stw\t$ptrreg, $reg", 1247 [(store i16:$reg, i16:$ptrreg)]>, 1248 Requires<[HasSRAM]>; 1249 1250// Indirect stores (with postincrement or predecrement). 1251let Constraints = "$ptrreg = $base_wb,@earlyclobber $base_wb" in 1252{ 1253 1254 // ST P+, Rr 1255 // Stores the value of Rr into the location addressed by pointer P. 1256 // Post increments P. 1257 def STPtrPiRr : FSTLD<1, 1258 0b01, 1259 (outs LDSTPtrReg:$base_wb), 1260 (ins LDSTPtrReg:$ptrreg, GPR8:$reg, i8imm:$offs), 1261 "st\t$ptrreg+, $reg", 1262 [(set i16:$base_wb, 1263 (post_store GPR8:$reg, i16:$ptrreg, imm:$offs))]>, 1264 Requires<[HasSRAM]>; 1265 1266 // STW P+, Rr+1:Rr 1267 // Stores the value of Rr into the location addressed by pointer P. 1268 // Post increments P. 1269 // 1270 // Expands to: 1271 // st P+, Rr 1272 // st P+, Rr+1 1273 def STWPtrPiRr : Pseudo<(outs PTRREGS:$base_wb), 1274 (ins PTRREGS:$ptrreg, DREGS:$trh, i8imm:$offs), 1275 "stw\t$ptrreg+, $trh", 1276 [(set PTRREGS:$base_wb, 1277 (post_store DREGS:$trh, PTRREGS:$ptrreg, imm:$offs))]>, 1278 Requires<[HasSRAM]>; 1279 1280 // ST -P, Rr 1281 // Stores the value of Rr into the location addressed by pointer P. 1282 // Pre decrements P. 1283 def STPtrPdRr : FSTLD<1, 1284 0b10, 1285 (outs LDSTPtrReg:$base_wb), 1286 (ins LDSTPtrReg:$ptrreg, GPR8:$reg, i8imm:$offs), 1287 "st\t-$ptrreg, $reg", 1288 [(set i16:$base_wb, 1289 (pre_store GPR8:$reg, i16:$ptrreg, imm:$offs))]>, 1290 Requires<[HasSRAM]>; 1291 1292 // STW -P, Rr+1:Rr 1293 // Stores the value of Rr into the location addressed by pointer P. 1294 // Pre decrements P. 1295 // 1296 // Expands to: 1297 // st -P, Rr+1 1298 // st -P, Rr 1299 def STWPtrPdRr : Pseudo<(outs PTRREGS:$base_wb), 1300 (ins PTRREGS:$ptrreg, DREGS:$reg, i8imm:$offs), 1301 "stw\t-$ptrreg, $reg", 1302 [(set PTRREGS:$base_wb, 1303 (pre_store i16:$reg, i16:$ptrreg, imm:$offs))]>, 1304 Requires<[HasSRAM]>; 1305} 1306 1307// Store indirect with displacement operations. 1308// STD P+q, Rr 1309// Stores the value of Rr into the location addressed by pointer P with a 1310// displacement of q. Does not modify P. 1311def STDPtrQRr : FSTDLDD<1, 1312 (outs), 1313 (ins memri:$memri, GPR8:$reg), 1314 "std\t$memri, $reg", 1315 [(store i8:$reg, addr:$memri)]>, 1316 Requires<[HasSRAM]>; 1317 1318// STDW P+q, Rr+1:Rr 1319// Stores the value of Rr into the location addressed by pointer P with a 1320// displacement of q. Does not modify P. 1321// 1322// Expands to: 1323// std P+q, Rr 1324// std P+q+1, Rr+1 1325def STDWPtrQRr : Pseudo<(outs), 1326 (ins memri:$memri, DREGS:$src), 1327 "stdw\t$memri, $src", 1328 [(store i16:$src, addr:$memri)]>, 1329 Requires<[HasSRAM]>; 1330 1331 1332// Load program memory operations. 1333let canFoldAsLoad = 1, 1334isReMaterializable = 1, 1335hasSideEffects = 0 in 1336{ 1337 let Defs = [R0], 1338 Uses = [R31R30] in 1339 def LPM : F16<0b1001010111001000, 1340 (outs), 1341 (ins), 1342 "lpm", 1343 []>, 1344 Requires<[HasLPM]>; 1345 1346 def LPMRdZ : FLPMX<0, 1347 0, 1348 (outs GPR8:$dst), 1349 (ins ZREGS:$z), 1350 "lpm\t$dst, $z", 1351 []>, 1352 Requires<[HasLPMX]>; 1353 1354 def LPMWRdZ : Pseudo<(outs DREGS:$dst), 1355 (ins ZREGS:$z), 1356 "lpmw\t$dst, $z", 1357 []>, 1358 Requires<[HasLPMX]>; 1359 1360 // Load program memory, while postincrementing the Z register. 1361 let mayLoad = 1, 1362 Defs = [R31R30] in 1363 { 1364 def LPMRdZPi : FLPMX<0, 1365 1, 1366 (outs GPR8:$dst), 1367 (ins ZREGS:$z), 1368 "lpm\t$dst, $z+", 1369 []>, 1370 Requires<[HasLPMX]>; 1371 1372 def LPMWRdZPi : Pseudo<(outs DREGS:$dst), 1373 (ins ZREGS:$z), 1374 "lpmw\t$dst, $z+", 1375 []>, 1376 Requires<[HasLPMX]>; 1377 } 1378} 1379 1380// Extended load program memory operations. 1381let mayLoad = 1, 1382hasSideEffects = 0 in 1383{ 1384 let Defs = [R0], 1385 Uses = [R31R30] in 1386 def ELPM : F16<0b1001010111011000, 1387 (outs), 1388 (ins), 1389 "elpm", 1390 []>, 1391 Requires<[HasELPM]>; 1392 1393 def ELPMRdZ : FLPMX<1, 1394 0, 1395 (outs GPR8:$dst), 1396 (ins ZREGS:$z), 1397 "elpm\t$dst, $z", 1398 []>, 1399 Requires<[HasELPMX]>; 1400 1401 let Defs = [R31R30] in 1402 def ELPMRdZPi : FLPMX<1, 1403 1, 1404 (outs GPR8:$dst), 1405 (ins ZREGS: $z), 1406 "elpm\t$dst, $z+", 1407 []>, 1408 Requires<[HasELPMX]>; 1409} 1410 1411// Store program memory operations. 1412let Uses = [R1, R0] in 1413{ 1414 let Uses = [R31R30, R1, R0] in 1415 def SPM : F16<0b1001010111101000, 1416 (outs), 1417 (ins), 1418 "spm", 1419 []>, 1420 Requires<[HasSPM]>; 1421 1422 let Defs = [R31R30] in 1423 def SPMZPi : F16<0b1001010111111000, 1424 (outs), 1425 (ins ZREGS:$z), 1426 "spm $z+", 1427 []>, 1428 Requires<[HasSPMX]>; 1429} 1430 1431// Read data from IO location operations. 1432let canFoldAsLoad = 1, 1433isReMaterializable = 1 in 1434{ 1435 def INRdA : FIORdA<(outs GPR8:$dst), 1436 (ins i16imm:$src), 1437 "in\t$dst, $src", 1438 [(set i8:$dst, (load ioaddr8:$src))]>; 1439 1440 def INWRdA : Pseudo<(outs DREGS:$dst), 1441 (ins i16imm:$src), 1442 "inw\t$dst, $src", 1443 [(set i16:$dst, (load ioaddr16:$src))]>; 1444} 1445 1446// Write data to IO location operations. 1447def OUTARr : FIOARr<(outs), 1448 (ins i16imm:$dst, GPR8:$src), 1449 "out\t$dst, $src", 1450 [(store i8:$src, ioaddr8:$dst)]>; 1451 1452def OUTWARr : Pseudo<(outs), 1453 (ins i16imm:$dst, DREGS:$src), 1454 "outw\t$dst, $src", 1455 [(store i16:$src, ioaddr16:$dst)]>; 1456 1457// Stack push/pop operations. 1458let Defs = [SP], 1459Uses = [SP], 1460hasSideEffects = 0 in 1461{ 1462 // Stack push operations. 1463 let mayStore = 1 in 1464 { 1465 def PUSHRr : FRd<0b1001, 1466 0b0011111, 1467 (outs), 1468 (ins GPR8:$reg), 1469 "push\t$reg", 1470 []>, 1471 Requires<[HasSRAM]>; 1472 1473 def PUSHWRr : Pseudo<(outs), 1474 (ins DREGS:$reg), 1475 "pushw\t$reg", 1476 []>, 1477 Requires<[HasSRAM]>; 1478 } 1479 1480 // Stack pop operations. 1481 let mayLoad = 1 in 1482 { 1483 def POPRd : FRd<0b1001, 1484 0b0001111, 1485 (outs GPR8:$reg), 1486 (ins), 1487 "pop\t$reg", 1488 []>, 1489 Requires<[HasSRAM]>; 1490 1491 def POPWRd : Pseudo<(outs DREGS:$reg), 1492 (ins), 1493 "popw\t$reg", 1494 []>, 1495 Requires<[HasSRAM]>; 1496 } 1497} 1498 1499// Read-Write-Modify (RMW) instructions. 1500def XCHZRd : FZRd<0b100, 1501 (outs GPR8:$rd), 1502 (ins ZREGS:$z), 1503 "xch\t$z, $rd", 1504 []>, 1505 Requires<[SupportsRMW]>; 1506 1507def LASZRd : FZRd<0b101, 1508 (outs GPR8:$rd), 1509 (ins ZREGS:$z), 1510 "las\t$z, $rd", 1511 []>, 1512 Requires<[SupportsRMW]>; 1513 1514def LACZRd : FZRd<0b110, 1515 (outs GPR8:$rd), 1516 (ins ZREGS:$z), 1517 "lac\t$z, $rd", 1518 []>, 1519 Requires<[SupportsRMW]>; 1520 1521def LATZRd : FZRd<0b111, 1522 (outs GPR8:$rd), 1523 (ins ZREGS:$z), 1524 "lat\t$z, $rd", 1525 []>, 1526 Requires<[SupportsRMW]>; 1527 1528//===----------------------------------------------------------------------===// 1529// Bit and bit-test instructions 1530//===----------------------------------------------------------------------===// 1531 1532// Bit shift/rotate operations. 1533let Constraints = "$src = $rd", 1534Defs = [SREG] in 1535{ 1536 def LSLRd : FRdRr<0b0000, 1537 0b11, 1538 (outs GPR8:$rd), 1539 (ins GPR8:$src), 1540 "lsl\t$rd", 1541 [(set i8:$rd, (AVRlsl i8:$src)), (implicit SREG)]>; 1542 1543 def LSLWRd : Pseudo<(outs DREGS:$rd), 1544 (ins DREGS:$src), 1545 "lslw\t$rd", 1546 [(set i16:$rd, (AVRlsl i16:$src)), (implicit SREG)]>; 1547 1548 def LSRRd : FRd<0b1001, 1549 0b0100110, 1550 (outs GPR8:$rd), 1551 (ins GPR8:$src), 1552 "lsr\t$rd", 1553 [(set i8:$rd, (AVRlsr i8:$src)), (implicit SREG)]>; 1554 1555 def LSRWRd : Pseudo<(outs DREGS:$rd), 1556 (ins DREGS:$src), 1557 "lsrw\t$rd", 1558 [(set i16:$rd, (AVRlsr i16:$src)), (implicit SREG)]>; 1559 1560 def ASRRd : FRd<0b1001, 1561 0b0100101, 1562 (outs GPR8:$rd), 1563 (ins GPR8:$src), 1564 "asr\t$rd", 1565 [(set i8:$rd, (AVRasr i8:$src)), (implicit SREG)]>; 1566 1567 def ASRWRd : Pseudo<(outs DREGS:$rd), 1568 (ins DREGS:$src), 1569 "asrw\t$rd", 1570 [(set i16:$rd, (AVRasr i16:$src)), (implicit SREG)]>; 1571 1572 // Bit rotate operations. 1573 let Uses = [SREG] in 1574 { 1575 def ROLRd : FRdRr<0b0001, 1576 0b11, 1577 (outs GPR8:$rd), 1578 (ins GPR8:$src), 1579 "rol\t$rd", 1580 [(set i8:$rd, (AVRrol i8:$src)), (implicit SREG)]>; 1581 1582 def ROLWRd : Pseudo<(outs DREGS:$rd), 1583 (ins DREGS:$src), 1584 "rolw\t$rd", 1585 [(set i16:$rd, (AVRrol i16:$src)), (implicit SREG)]>; 1586 1587 def RORRd : FRd<0b1001, 1588 0b0100111, 1589 (outs GPR8:$rd), 1590 (ins GPR8:$src), 1591 "ror\t$rd", 1592 [(set i8:$rd, (AVRror i8:$src)), (implicit SREG)]>; 1593 1594 def RORWRd : Pseudo<(outs DREGS:$rd), 1595 (ins DREGS:$src), 1596 "rorw\t$rd", 1597 [(set i16:$rd, (AVRror i16:$src)), (implicit SREG)]>; 1598 } 1599} 1600 1601// SWAP Rd 1602// Swaps the high and low nibbles in a register. 1603let Constraints = "$src = $rd" in 1604def SWAPRd : FRd<0b1001, 1605 0b0100010, 1606 (outs GPR8:$rd), 1607 (ins GPR8:$src), 1608 "swap\t$rd", 1609 [(set i8:$rd, (bswap i8:$src))]>; 1610 1611// IO register bit set/clear operations. 1612//:TODO: add patterns when popcount(imm)==2 to be expanded with 2 sbi/cbi 1613// instead of in+ori+out which requires one more instr. 1614def SBIAb : FIOBIT<0b10, 1615 (outs), 1616 (ins i16imm:$addr, i8imm:$bit), 1617 "sbi\t$addr, $bit", 1618 [(store (or (i8 (load lowioaddr8:$addr)), iobitpos8:$bit), 1619 lowioaddr8:$addr)]>; 1620 1621def CBIAb : FIOBIT<0b00, 1622 (outs), 1623 (ins i16imm:$addr, i8imm:$bit), 1624 "cbi\t$addr, $bit", 1625 [(store (and (i8 (load lowioaddr8:$addr)), iobitposn8:$bit), 1626 lowioaddr8:$addr)]>; 1627 1628// Status register bit load/store operations. 1629let Defs = [SREG] in 1630def BST : FRdB<0b01, 1631 (outs), 1632 (ins GPR8:$rd, i8imm:$b), 1633 "bst\t$rd, $b", 1634 []>; 1635 1636let Uses = [SREG] in 1637def BLD : FRdB<0b00, 1638 (outs), 1639 (ins GPR8:$rd, i8imm:$b), 1640 "bld\t$rd, $b", 1641 []>; 1642 1643// Set/clear bit in register operations. 1644let Constraints = "$src = $rd", 1645Defs = [SREG] in 1646{ 1647 // SBR Rd, K 1648 // Alias for ORI Rd, K 1649 def SBRRdK : FRdK<0b0110, 1650 (outs LD8:$rd), 1651 (ins LD8:$src, i8imm:$k), 1652 "sbr\t$rd, $k", 1653 [(set i8:$rd, (or i8:$src, imm:$k)), 1654 (implicit SREG)]>; 1655 1656 // CBR Rd, K 1657 // Alias for `ANDI Rd, COM(K)` where COM(K) is the compliment of K. 1658 def CBRRdK : FRdK<0b0111, 1659 (outs LD8:$rd), 1660 (ins LD8:$src, i8imm_com:$k), 1661 "cbr\t$rd, $k", 1662 []>; 1663} 1664 1665// CLR Rd 1666// Alias for EOR Rd, Rd 1667// ------------- 1668// Clears all bits in a register. 1669def CLR : InstAlias<"clr\t$rd", (EORRdRr GPR8:$rd, GPR8:$rd)>; 1670 1671// SER Rd 1672// Alias for LDI Rd, 0xff 1673// --------- 1674// Sets all bits in a register. 1675def : InstAlias<"ser\t$rd", (LDIRdK LD8:$rd, 0xff), 0>; 1676 1677let Defs = [SREG] in 1678def BSETs : FS<0, 1679 (outs), 1680 (ins i8imm:$s), 1681 "bset\t$s", 1682 []>; 1683 1684let Defs = [SREG] in 1685def BCLRs : FS<1, 1686 (outs), 1687 (ins i8imm:$s), 1688 "bclr\t$s", 1689 []>; 1690 1691// Set/clear aliases for the carry (C) status flag (bit 0). 1692def : InstAlias<"sec", (BSETs 0)>; 1693def : InstAlias<"clc", (BCLRs 0)>; 1694 1695// Set/clear aliases for the zero (Z) status flag (bit 1). 1696def : InstAlias<"sez", (BSETs 1)>; 1697def : InstAlias<"clz", (BCLRs 1)>; 1698 1699// Set/clear aliases for the negative (N) status flag (bit 2). 1700def : InstAlias<"sen", (BSETs 2)>; 1701def : InstAlias<"cln", (BCLRs 2)>; 1702 1703// Set/clear aliases for the overflow (V) status flag (bit 3). 1704def : InstAlias<"sev", (BSETs 3)>; 1705def : InstAlias<"clv", (BCLRs 3)>; 1706 1707// Set/clear aliases for the signed (S) status flag (bit 4). 1708def : InstAlias<"ses", (BSETs 4)>; 1709def : InstAlias<"cls", (BCLRs 4)>; 1710 1711// Set/clear aliases for the half-carry (H) status flag (bit 5). 1712def : InstAlias<"seh", (BSETs 5)>; 1713def : InstAlias<"clh", (BCLRs 5)>; 1714 1715// Set/clear aliases for the T status flag (bit 6). 1716def : InstAlias<"set", (BSETs 6)>; 1717def : InstAlias<"clt", (BCLRs 6)>; 1718 1719// Set/clear aliases for the interrupt (I) status flag (bit 7). 1720def : InstAlias<"sei", (BSETs 7)>; 1721def : InstAlias<"cli", (BCLRs 7)>; 1722 1723//===----------------------------------------------------------------------===// 1724// Special/Control instructions 1725//===----------------------------------------------------------------------===// 1726 1727// BREAK 1728// Breakpoint instruction 1729// --------- 1730// <|1001|0101|1001|1000> 1731def BREAK : F16<0b1001010110011000, 1732 (outs), 1733 (ins), 1734 "break", 1735 []>, 1736 Requires<[HasBREAK]>; 1737 1738// NOP 1739// No-operation instruction 1740// --------- 1741// <|0000|0000|0000|0000> 1742def NOP : F16<0b0000000000000000, 1743 (outs), 1744 (ins), 1745 "nop", 1746 []>; 1747 1748// SLEEP 1749// Sleep instruction 1750// --------- 1751// <|1001|0101|1000|1000> 1752def SLEEP : F16<0b1001010110001000, 1753 (outs), 1754 (ins), 1755 "sleep", 1756 []>; 1757 1758// WDR 1759// Watchdog reset 1760// --------- 1761// <|1001|0101|1010|1000> 1762def WDR : F16<0b1001010110101000, 1763 (outs), 1764 (ins), 1765 "wdr", 1766 []>; 1767 1768//===----------------------------------------------------------------------===// 1769// Pseudo instructions for later expansion 1770//===----------------------------------------------------------------------===// 1771 1772//:TODO: Optimize this for wider types AND optimize the following code 1773// compile int foo(char a, char b, char c, char d) {return d+b;} 1774// looks like a missed sext_inreg opportunity. 1775def SEXT : ExtensionPseudo< 1776 (outs DREGS:$dst), 1777 (ins GPR8:$src), 1778 "sext\t$dst, $src", 1779 [(set i16:$dst, (sext i8:$src)), (implicit SREG)] 1780>; 1781 1782def ZEXT : ExtensionPseudo< 1783 (outs DREGS:$dst), 1784 (ins GPR8:$src), 1785 "zext\t$dst, $src", 1786 [(set i16:$dst, (zext i8:$src)), (implicit SREG)] 1787>; 1788 1789// This pseudo gets expanded into a movw+adiw thus it clobbers SREG. 1790let Defs = [SREG], 1791 hasSideEffects = 0 in 1792def FRMIDX : Pseudo<(outs DLDREGS:$dst), 1793 (ins DLDREGS:$src, i16imm:$src2), 1794 "frmidx\t$dst, $src, $src2", 1795 []>; 1796 1797// This pseudo is either converted to a regular store or a push which clobbers 1798// SP. 1799def STDSPQRr : StorePseudo< 1800 (outs), 1801 (ins memspi:$dst, GPR8:$src), 1802 "stdstk\t$dst, $src", 1803 [(store i8:$src, addr:$dst)] 1804>; 1805 1806// This pseudo is either converted to a regular store or a push which clobbers 1807// SP. 1808def STDWSPQRr : StorePseudo< 1809 (outs), 1810 (ins memspi:$dst, DREGS:$src), 1811 "stdwstk\t$dst, $src", 1812 [(store i16:$src, addr:$dst)] 1813>; 1814 1815// SP read/write pseudos. 1816let hasSideEffects = 0 in 1817{ 1818 let Uses = [SP] in 1819 def SPREAD : Pseudo< 1820 (outs DREGS:$dst), 1821 (ins GPRSP:$src), 1822 "spread\t$dst, $src", 1823 [] 1824 >; 1825 1826 let Defs = [SP] in 1827 def SPWRITE : Pseudo< 1828 (outs GPRSP:$dst), 1829 (ins DREGS:$src), 1830 "spwrite\t$dst, $src", 1831 []>; 1832} 1833 1834def Select8 : SelectPseudo< 1835 (outs GPR8:$dst), 1836 (ins GPR8:$src, GPR8:$src2, i8imm:$cc), 1837 "# Select8 PSEUDO", 1838 [(set i8:$dst, (AVRselectcc i8:$src, i8:$src2, imm:$cc))] 1839>; 1840 1841def Select16 : SelectPseudo< 1842 (outs DREGS:$dst), 1843 (ins DREGS:$src, DREGS:$src2, i8imm:$cc), 1844 "# Select16 PSEUDO", 1845 [(set i16:$dst, (AVRselectcc i16:$src, i16:$src2, imm:$cc))] 1846>; 1847 1848def Lsl8 : ShiftPseudo< 1849 (outs GPR8:$dst), 1850 (ins GPR8:$src, GPR8:$cnt), 1851 "# Lsl8 PSEUDO", 1852 [(set i8:$dst, (AVRlslLoop i8:$src, i8:$cnt))] 1853>; 1854 1855def Lsl16 : ShiftPseudo< 1856 (outs DREGS:$dst), 1857 (ins DREGS:$src, GPR8:$cnt), 1858 "# Lsl16 PSEUDO", 1859 [(set i16:$dst, (AVRlslLoop i16:$src, i8:$cnt))] 1860>; 1861 1862def Lsr8 : ShiftPseudo< 1863 (outs GPR8:$dst), 1864 (ins GPR8:$src, GPR8:$cnt), 1865 "# Lsr8 PSEUDO", 1866 [(set i8:$dst, (AVRlsrLoop i8:$src, i8:$cnt))] 1867>; 1868 1869 1870def Lsr16 : ShiftPseudo< 1871 (outs DREGS:$dst), 1872 (ins DREGS:$src, GPR8:$cnt), 1873 "# Lsr16 PSEUDO", 1874 [(set i16:$dst, (AVRlsrLoop i16:$src, i8:$cnt))] 1875>; 1876 1877def Asr8 : ShiftPseudo< 1878 (outs GPR8:$dst), 1879 (ins GPR8:$src, GPR8:$cnt), 1880 "# Asr8 PSEUDO", 1881 [(set i8:$dst, (AVRasrLoop i8:$src, i8:$cnt))] 1882>; 1883 1884def Asr16 : ShiftPseudo< 1885 (outs DREGS:$dst), 1886 (ins DREGS:$src, GPR8:$cnt), 1887 "# Asr16 PSEUDO", 1888 [(set i16:$dst, (AVRasrLoop i16:$src, i8:$cnt))] 1889>; 1890 1891 1892//===----------------------------------------------------------------------===// 1893// Non-Instruction Patterns 1894//===----------------------------------------------------------------------===// 1895 1896//:TODO: look in x86InstrCompiler.td for odd encoding trick related to 1897// add x, 128 -> sub x, -128. Clang is emitting an eor for this (ldi+eor) 1898 1899// the add instruction always writes the carry flag 1900def : Pat<(addc i8:$src, i8:$src2), 1901 (ADDRdRr i8:$src, i8:$src2)>; 1902def : Pat<(addc DREGS:$src, DREGS:$src2), 1903 (ADDWRdRr DREGS:$src, DREGS:$src2)>; 1904 1905// all sub instruction variants always writes the carry flag 1906def : Pat<(subc i8:$src, i8:$src2), 1907 (SUBRdRr i8:$src, i8:$src2)>; 1908def : Pat<(subc i16:$src, i16:$src2), 1909 (SUBWRdRr i16:$src, i16:$src2)>; 1910def : Pat<(subc i8:$src, imm:$src2), 1911 (SUBIRdK i8:$src, imm:$src2)>; 1912def : Pat<(subc i16:$src, imm:$src2), 1913 (SUBIWRdK i16:$src, imm:$src2)>; 1914 1915// These patterns convert add (x, -imm) to sub (x, imm) since we dont have 1916// any add with imm instructions. Also take care of the adiw/sbiw instructions. 1917def : Pat<(add i16:$src1, imm0_63_neg:$src2), 1918 (SBIWRdK i16:$src1, (imm0_63_neg:$src2))>; 1919def : Pat<(add i16:$src1, imm:$src2), 1920 (SUBIWRdK i16:$src1, (imm16_neg_XFORM imm:$src2))>; 1921def : Pat<(addc i16:$src1, imm:$src2), 1922 (SUBIWRdK i16:$src1, (imm16_neg_XFORM imm:$src2))>; 1923def : Pat<(adde i16:$src1, imm:$src2), 1924 (SBCIWRdK i16:$src1, (imm16_neg_XFORM imm:$src2))>; 1925 1926def : Pat<(add i8:$src1, imm:$src2), 1927 (SUBIRdK i8:$src1, (imm8_neg_XFORM imm:$src2))>; 1928def : Pat<(addc i8:$src1, imm:$src2), 1929 (SUBIRdK i8:$src1, (imm8_neg_XFORM imm:$src2))>; 1930def : Pat<(adde i8:$src1, imm:$src2), 1931 (SBCIRdK i8:$src1, (imm8_neg_XFORM imm:$src2))>; 1932 1933// Calls. 1934def : Pat<(AVRcall (i16 tglobaladdr:$dst)), 1935 (CALLk tglobaladdr:$dst)>; 1936def : Pat<(AVRcall (i16 texternalsym:$dst)), 1937 (CALLk texternalsym:$dst)>; 1938 1939// `anyext` 1940def : Pat<(i16 (anyext i8:$src)), 1941 (INSERT_SUBREG (i16 (IMPLICIT_DEF)), i8:$src, sub_lo)>; 1942 1943// `trunc` 1944def : Pat<(i8 (trunc i16:$src)), 1945 (EXTRACT_SUBREG i16:$src, sub_lo)>; 1946 1947// sext_inreg 1948def : Pat<(sext_inreg i16:$src, i8), 1949 (SEXT (i8 (EXTRACT_SUBREG i16:$src, sub_lo)))>; 1950 1951// GlobalAddress 1952def : Pat<(i16 (AVRWrapper tglobaladdr:$dst)), 1953 (LDIWRdK tglobaladdr:$dst)>; 1954def : Pat<(add i16:$src, (AVRWrapper tglobaladdr:$src2)), 1955 (SUBIWRdK i16:$src, tglobaladdr:$src2)>; 1956def : Pat<(i8 (load (AVRWrapper tglobaladdr:$dst))), 1957 (LDSRdK tglobaladdr:$dst)>; 1958def : Pat<(i16 (load (AVRWrapper tglobaladdr:$dst))), 1959 (LDSWRdK tglobaladdr:$dst)>; 1960def : Pat<(store i8:$src, (i16 (AVRWrapper tglobaladdr:$dst))), 1961 (STSKRr tglobaladdr:$dst, i8:$src)>; 1962def : Pat<(store i16:$src, (i16 (AVRWrapper tglobaladdr:$dst))), 1963 (STSWKRr tglobaladdr:$dst, i16:$src)>; 1964 1965// BlockAddress 1966def : Pat<(i16 (AVRWrapper tblockaddress:$dst)), 1967 (LDIWRdK tblockaddress:$dst)>; 1968 1969// hi-reg truncation : trunc(int16 >> 8) 1970//:FIXME: i think it's better to emit an extract subreg node in the DAG than 1971// all this mess once we get optimal shift code 1972// lol... I think so, too. [@agnat] 1973def : Pat<(i8 (trunc (AVRlsr (AVRlsr (AVRlsr (AVRlsr (AVRlsr (AVRlsr (AVRlsr 1974 (AVRlsr DREGS:$src)))))))))), 1975 (EXTRACT_SUBREG DREGS:$src, sub_hi)>; 1976 1977// :FIXME: DAGCombiner produces an shl node after legalization from these seq: 1978// BR_JT -> (mul x, 2) -> (shl x, 1) 1979def : Pat<(shl i16:$src1, (i8 1)), 1980 (LSLWRd i16:$src1)>; 1981 1982