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