[AVR] Support 16-bit LDS/STS on AVRTiny.
[llvm-project.git] / llvm / lib / Target / AVR / AVRInstrInfo.td
blob4a4e2062f91dbae03df2d0bd30b57843574c597d
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.
11 //===----------------------------------------------------------------------===//
13 include "AVRInstrFormats.td"
15 //===----------------------------------------------------------------------===//
16 // AVR Type Profiles
17 //===----------------------------------------------------------------------===//
19 def SDT_AVRCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i16>, SDTCisVT<1, i16>]>;
20 def SDT_AVRCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i16>, SDTCisVT<1, i16>]>;
21 def SDT_AVRCall : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
22 def SDT_AVRWrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>;
23 def SDT_AVRBrcond
24     : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisVT<1, i8>]>;
25 def SDT_AVRCmp : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
26 def SDT_AVRTst : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
27 def SDT_AVRSelectCC
28     : SDTypeProfile<1, 3,
29                     [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>;
31 //===----------------------------------------------------------------------===//
32 // AVR Specific Node Definitions
33 //===----------------------------------------------------------------------===//
35 def AVRretflag : SDNode<"AVRISD::RET_FLAG", SDTNone,
36                         [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
37 def AVRretiflag : SDNode<"AVRISD::RETI_FLAG", SDTNone,
38                          [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
40 def AVRcallseq_start : SDNode<"ISD::CALLSEQ_START", SDT_AVRCallSeqStart,
41                               [SDNPHasChain, SDNPOutGlue]>;
42 def AVRcallseq_end : SDNode<"ISD::CALLSEQ_END", SDT_AVRCallSeqEnd,
43                             [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
45 def AVRcall : SDNode<"AVRISD::CALL", SDT_AVRCall,
46                      [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, SDNPVariadic]>;
48 def AVRWrapper : SDNode<"AVRISD::WRAPPER", SDT_AVRWrapper>;
50 def AVRbrcond
51     : SDNode<"AVRISD::BRCOND", SDT_AVRBrcond, [SDNPHasChain, SDNPInGlue]>;
52 def AVRcmp : SDNode<"AVRISD::CMP", SDT_AVRCmp, [SDNPOutGlue]>;
53 def AVRcmpc : SDNode<"AVRISD::CMPC", SDT_AVRCmp, [SDNPInGlue, SDNPOutGlue]>;
54 def AVRtst : SDNode<"AVRISD::TST", SDT_AVRTst, [SDNPOutGlue]>;
55 def AVRselectcc : SDNode<"AVRISD::SELECT_CC", SDT_AVRSelectCC, [SDNPInGlue]>;
57 // Shift nodes.
58 def AVRlsl : SDNode<"AVRISD::LSL", SDTIntUnaryOp>;
59 def AVRlsr : SDNode<"AVRISD::LSR", SDTIntUnaryOp>;
60 def AVRrol : SDNode<"AVRISD::ROL", SDTIntUnaryOp>;
61 def AVRror : SDNode<"AVRISD::ROR", SDTIntUnaryOp>;
62 def AVRasr : SDNode<"AVRISD::ASR", SDTIntUnaryOp>;
63 def AVRlslhi : SDNode<"AVRISD::LSLHI", SDTIntUnaryOp>;
64 def AVRlsrlo : SDNode<"AVRISD::LSRLO", SDTIntUnaryOp>;
65 def AVRasrlo : SDNode<"AVRISD::ASRLO", SDTIntUnaryOp>;
66 def AVRlslbn : SDNode<"AVRISD::LSLBN", SDTIntBinOp>;
67 def AVRlsrbn : SDNode<"AVRISD::LSRBN", SDTIntBinOp>;
68 def AVRasrbn : SDNode<"AVRISD::ASRBN", SDTIntBinOp>;
69 def AVRlslwn : SDNode<"AVRISD::LSLWN", SDTIntBinOp>;
70 def AVRlsrwn : SDNode<"AVRISD::LSRWN", SDTIntBinOp>;
71 def AVRasrwn : SDNode<"AVRISD::ASRWN", SDTIntBinOp>;
73 // Pseudo shift nodes for non-constant shift amounts.
74 def AVRlslLoop : SDNode<"AVRISD::LSLLOOP", SDTIntShiftOp>;
75 def AVRlsrLoop : SDNode<"AVRISD::LSRLOOP", SDTIntShiftOp>;
76 def AVRrolLoop : SDNode<"AVRISD::ROLLOOP", SDTIntShiftOp>;
77 def AVRrorLoop : SDNode<"AVRISD::RORLOOP", SDTIntShiftOp>;
78 def AVRasrLoop : SDNode<"AVRISD::ASRLOOP", SDTIntShiftOp>;
80 // SWAP node.
81 def AVRSwap : SDNode<"AVRISD::SWAP", SDTIntUnaryOp>;
83 //===----------------------------------------------------------------------===//
84 // AVR Operands, Complex Patterns and Transformations Definitions.
85 //===----------------------------------------------------------------------===//
87 def imm8_neg_XFORM : SDNodeXForm<imm, [{
88                                    return CurDAG->getTargetConstant(
89                                        -N->getAPIntValue(), SDLoc(N), MVT::i8);
90                                  }]>;
92 def imm16_neg_XFORM
93     : SDNodeXForm<imm, [{
94                     return CurDAG->getTargetConstant(-N->getAPIntValue(),
95                                                      SDLoc(N), MVT::i16);
96                   }]>;
98 def imm0_63_neg : PatLeaf<(imm), [{
99                             int64_t val = -N->getSExtValue();
100                             return val >= 0 && val < 64;
101                           }],
102                           imm16_neg_XFORM>;
104 def uimm6 : PatLeaf<(imm), [{ return isUInt<6>(N->getZExtValue()); }]>;
106 // imm_com8_XFORM - Return the complement of a imm_com8 value
107 def imm_com8_XFORM
108     : SDNodeXForm<imm, [{
109                     return CurDAG->getTargetConstant(
110                         ~((uint8_t) N->getZExtValue()), SDLoc(N), MVT::i8);
111                   }]>;
113 // imm_com8 - Match an immediate that is a complement
114 // of a 8-bit immediate.
115 // Note: this pattern doesn't require an encoder method and such, as it's
116 // only used on aliases (Pat<> and InstAlias<>). The actual encoding
117 // is handled by the destination instructions, which use imm_com8.
118 def imm_com8_asmoperand : AsmOperandClass { let Name = "ImmCom8"; }
119 def imm_com8 : Operand<i8> { let ParserMatchClass = imm_com8_asmoperand; }
121 def ioaddr_XFORM
122     : SDNodeXForm<imm, [{
123                     uint8_t offset = Subtarget->getIORegisterOffset();
124                     return CurDAG->getTargetConstant(
125                         uint8_t(N->getZExtValue()) - offset, SDLoc(N), MVT::i8);
126                   }]>;
128 def iobitpos8_XFORM
129     : SDNodeXForm<imm, [{
130                     return CurDAG->getTargetConstant(
131                         Log2_32(uint8_t(N->getZExtValue())), SDLoc(N), MVT::i8);
132                   }]>;
134 def iobitposn8_XFORM : SDNodeXForm<imm, [{
135                                      return CurDAG->getTargetConstant(
136                                          Log2_32(uint8_t(~N->getZExtValue())),
137                                          SDLoc(N), MVT::i8);
138                                    }]>;
140 def ioaddr8 : PatLeaf<(imm), [{
141                         uint8_t offset = Subtarget->getIORegisterOffset();
142                         uint64_t val = N->getZExtValue() - offset;
143                         return val < 0x40;
144                       }],
145                       ioaddr_XFORM>;
147 def lowioaddr8 : PatLeaf<(imm), [{
148                            uint8_t offset = Subtarget->getIORegisterOffset();
149                            uint64_t val = N->getZExtValue() - offset;
150                            return val < 0x20;
151                          }],
152                          ioaddr_XFORM>;
154 def ioaddr16 : PatLeaf<(imm), [{
155                          uint8_t offset = Subtarget->getIORegisterOffset();
156                          uint64_t val = N->getZExtValue() - offset;
157                          return val < 0x3f;
158                        }],
159                        ioaddr_XFORM>;
161 def iobitpos8
162     : PatLeaf<(imm), [{ return isPowerOf2_32(uint8_t(N->getZExtValue())); }],
163               iobitpos8_XFORM>;
165 def iobitposn8
166     : PatLeaf<(imm), [{ return isPowerOf2_32(uint8_t(~N->getZExtValue())); }],
167               iobitposn8_XFORM>;
169 def MemriAsmOperand : AsmOperandClass {
170   let Name = "Memri";
171   let ParserMethod = "parseMemriOperand";
174 /// Address operand for `reg+imm` used by STD and LDD.
175 def memri : Operand<iPTR> {
176   let MIOperandInfo = (ops PTRDISPREGS, i16imm);
178   let PrintMethod = "printMemri";
179   let EncoderMethod = "encodeMemri";
180   let DecoderMethod = "decodeMemri";
182   let ParserMatchClass = MemriAsmOperand;
185 // Address operand for `SP+imm` used by STD{W}SPQRr
186 def memspi : Operand<iPTR> {
187   let MIOperandInfo = (ops GPRSP, i16imm);
188   let PrintMethod = "printMemspi";
191 def relbrtarget_7 : Operand<OtherVT> {
192   let PrintMethod = "printPCRelImm";
193   let EncoderMethod = "encodeRelCondBrTarget<AVR::fixup_7_pcrel>";
196 def brtarget_13 : Operand<OtherVT> {
197   let PrintMethod = "printPCRelImm";
198   let EncoderMethod = "encodeRelCondBrTarget<AVR::fixup_13_pcrel>";
201 def rcalltarget_13 : Operand<i16> {
202   let PrintMethod = "printPCRelImm";
203   let EncoderMethod = "encodeRelCondBrTarget<AVR::fixup_13_pcrel>";
206 // The target of a 22 or 16-bit call/jmp instruction.
207 def call_target : Operand<iPTR> {
208   let EncoderMethod = "encodeCallTarget";
209   let DecoderMethod = "decodeCallTarget";
212 // A 16-bit address (which can lead to an R_AVR_16 relocation).
213 def imm16 : Operand<i16> { let EncoderMethod = "encodeImm<AVR::fixup_16, 2>"; }
215 // A 7-bit address (which can lead to an R_AVR_LDS_STS_16 relocation).
216 def imm7tiny : Operand<i8> {
217   let EncoderMethod = "encodeImm<AVR::fixup_lds_sts_16, 0>";
220 /// A 6-bit immediate used in the ADIW/SBIW instructions.
221 def imm_arith6 : Operand<i16> {
222   let EncoderMethod = "encodeImm<AVR::fixup_6_adiw, 0>";
225 /// An 8-bit immediate inside an instruction with the same format
226 /// as the `LDI` instruction (the `FRdK` format).
227 def imm_ldi8 : Operand<i8> {
228   let EncoderMethod = "encodeImm<AVR::fixup_ldi, 0>";
231 /// A 5-bit port number used in SBIC and friends (the `FIOBIT` format).
232 def imm_port5 : Operand<i8> {
233   let EncoderMethod = "encodeImm<AVR::fixup_port5, 0>";
236 /// A 6-bit port number used in the `IN` instruction and friends (the
237 /// `FIORdA` format.
238 def imm_port6 : Operand<i8> {
239   let EncoderMethod = "encodeImm<AVR::fixup_port6, 0>";
242 // Addressing mode pattern reg+imm6
243 def addr : ComplexPattern<iPTR, 2, "SelectAddr", [], [SDNPWantRoot]>;
245 // AsmOperand class for a pointer register.
246 // Used with the LD/ST family of instructions.
247 // See FSTLD in AVRInstrFormats.td
248 def PtrRegAsmOperand : AsmOperandClass { let Name = "Reg"; }
250 // A special operand type for the LD/ST instructions.
251 // It converts the pointer register number into a two-bit field used in the
252 // instruction.
253 def LDSTPtrReg : Operand<i16> {
254   let MIOperandInfo = (ops PTRREGS);
255   let EncoderMethod = "encodeLDSTPtrReg";
257   let ParserMatchClass = PtrRegAsmOperand;
260 // A special operand type for the LDD/STD instructions.
261 // It behaves identically to the LD/ST version, except restricts
262 // the pointer registers to Y and Z.
263 def LDDSTDPtrReg : Operand<i16> {
264   let MIOperandInfo = (ops PTRDISPREGS);
265   let EncoderMethod = "encodeLDSTPtrReg";
267   let ParserMatchClass = PtrRegAsmOperand;
270 //===----------------------------------------------------------------------===//
271 // AVR predicates for subtarget features
272 //===----------------------------------------------------------------------===//
274 def HasSRAM : Predicate<"Subtarget->hasSRAM()">,
275               AssemblerPredicate<(all_of FeatureSRAM)>;
277 def HasJMPCALL : Predicate<"Subtarget->hasJMPCALL()">,
278                  AssemblerPredicate<(all_of FeatureJMPCALL)>;
280 def HasIJMPCALL : Predicate<"Subtarget->hasIJMPCALL()">,
281                   AssemblerPredicate<(all_of FeatureIJMPCALL)>;
283 def HasEIJMPCALL : Predicate<"Subtarget->hasEIJMPCALL()">,
284                    AssemblerPredicate<(all_of FeatureEIJMPCALL)>;
286 def HasADDSUBIW : Predicate<"Subtarget->hasADDSUBIW()">,
287                   AssemblerPredicate<(all_of FeatureADDSUBIW)>;
289 def HasSmallStack : Predicate<"Subtarget->HasSmallStack()">,
290                     AssemblerPredicate<(all_of FeatureSmallStack)>;
292 def HasMOVW : Predicate<"Subtarget->hasMOVW()">,
293               AssemblerPredicate<(all_of FeatureMOVW)>;
295 def HasLPM : Predicate<"Subtarget->hasLPM()">,
296              AssemblerPredicate<(all_of FeatureLPM)>;
298 def HasLPMX : Predicate<"Subtarget->hasLPMX()">,
299               AssemblerPredicate<(all_of FeatureLPMX)>;
301 def HasELPM : Predicate<"Subtarget->hasELPM()">,
302               AssemblerPredicate<(all_of FeatureELPM)>;
304 def HasELPMX : Predicate<"Subtarget->hasELPMX()">,
305                AssemblerPredicate<(all_of FeatureELPMX)>;
307 def HasSPM : Predicate<"Subtarget->hasSPM()">,
308              AssemblerPredicate<(all_of FeatureSPM)>;
310 def HasSPMX : Predicate<"Subtarget->hasSPMX()">,
311               AssemblerPredicate<(all_of FeatureSPMX)>;
313 def HasDES : Predicate<"Subtarget->hasDES()">,
314              AssemblerPredicate<(all_of FeatureDES)>;
316 def SupportsRMW : Predicate<"Subtarget->supportsRMW()">,
317                   AssemblerPredicate<(all_of FeatureRMW)>;
319 def SupportsMultiplication : Predicate<"Subtarget->supportsMultiplication()">,
320                              AssemblerPredicate<(all_of FeatureMultiplication)>;
322 def HasBREAK : Predicate<"Subtarget->hasBREAK()">,
323                AssemblerPredicate<(all_of FeatureBREAK)>;
325 def HasTinyEncoding : Predicate<"Subtarget->hasTinyEncoding()">,
326                       AssemblerPredicate<(all_of FeatureTinyEncoding)>;
328 def HasNonTinyEncoding : Predicate<"!Subtarget->hasTinyEncoding()">,
329                          AssemblerPredicate<(any_of (not FeatureTinyEncoding))>;
331 // AVR specific condition code. These correspond to AVR_*_COND in
332 // AVRInstrInfo.td. They must be kept in synch.
333 def AVR_COND_EQ : PatLeaf<(i8 0)>;
334 def AVR_COND_NE : PatLeaf<(i8 1)>;
335 def AVR_COND_GE : PatLeaf<(i8 2)>;
336 def AVR_COND_LT : PatLeaf<(i8 3)>;
337 def AVR_COND_SH : PatLeaf<(i8 4)>;
338 def AVR_COND_LO : PatLeaf<(i8 5)>;
339 def AVR_COND_MI : PatLeaf<(i8 6)>;
340 def AVR_COND_PL : PatLeaf<(i8 7)>;
342 //===----------------------------------------------------------------------===//
343 //===----------------------------------------------------------------------===//
344 // AVR Instruction list
345 //===----------------------------------------------------------------------===//
346 //===----------------------------------------------------------------------===//
348 // ADJCALLSTACKDOWN/UP implicitly use/def SP because they may be expanded into
349 // a stack adjustment and the codegen must know that they may modify the stack
350 // pointer before prolog-epilog rewriting occurs.
351 // Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
352 // sub / add which can clobber SREG.
353 let Defs = [SP, SREG], Uses = [SP] in {
354   def ADJCALLSTACKDOWN : Pseudo<(outs),
355                                 (ins i16imm
356                                  : $amt, i16imm
357                                  : $amt2),
358                                 "#ADJCALLSTACKDOWN", [(AVRcallseq_start timm
359                                                        : $amt, timm
360                                                        : $amt2)]>;
362   // R31R30 is used to update SP. It is normally free because it is a
363   // call-clobbered register but it is necessary to set it as a def as the
364   // register allocator might use it in rare cases (for rematerialization, it
365   // seems). hasSideEffects needs to be set to true so this instruction isn't
366   // considered dead.
367   let Defs = [R31R30], hasSideEffects = 1 in def ADJCALLSTACKUP
368       : Pseudo<(outs),
369                (ins i16imm
370                 : $amt1, i16imm
371                 : $amt2),
372                "#ADJCALLSTACKUP", [(AVRcallseq_end timm
373                                     : $amt1, timm
374                                     : $amt2)]>;
377 //===----------------------------------------------------------------------===//
378 // Addition
379 //===----------------------------------------------------------------------===//
380 let isCommutable = 1, Constraints = "$src = $rd", Defs = [SREG] in {
381   // ADD Rd, Rr
382   // Adds two 8-bit registers.
383   def ADDRdRr
384       : FRdRr<0b0000, 0b11,
385               (outs GPR8
386                : $rd),
387               (ins GPR8
388                : $src, GPR8
389                : $rr),
390               "add\t$rd, $rr",
391               [(set i8
392                 : $rd, (add i8
393                         : $src, i8
394                         : $rr)),
395                (implicit SREG)]>;
397   // ADDW Rd+1:Rd, Rr+1:Rr
398   // Pseudo instruction to add four 8-bit registers as two 16-bit values.
399   //
400   // Expands to:
401   // add Rd,    Rr
402   // adc Rd+1, Rr+1
403   def ADDWRdRr
404       : Pseudo<(outs DREGS
405                 : $rd),
406                (ins DREGS
407                 : $src, DREGS
408                 : $rr),
409                "addw\t$rd, $rr",
410                [(set i16
411                  : $rd, (add i16
412                          : $src, i16
413                          : $rr)),
414                 (implicit SREG)]>;
416   // ADC Rd, Rr
417   // Adds two 8-bit registers with carry.
418   let Uses = [SREG] in def ADCRdRr
419       : FRdRr<0b0001, 0b11,
420               (outs GPR8
421                : $rd),
422               (ins GPR8
423                : $src, GPR8
424                : $rr),
425               "adc\t$rd, $rr",
426               [(set i8
427                 : $rd, (adde i8
428                         : $src, i8
429                         : $rr)),
430                (implicit SREG)]>;
432   // ADCW Rd+1:Rd, Rr+1:Rr
433   // Pseudo instruction to add four 8-bit registers as two 16-bit values with
434   // carry.
435   //
436   // Expands to:
437   // adc Rd,   Rr
438   // adc Rd+1, Rr+1
439   let Uses = [SREG] in def ADCWRdRr : Pseudo<(outs DREGS
440                                               : $rd),
441                                              (ins DREGS
442                                               : $src, DREGS
443                                               : $rr),
444                                              "adcw\t$rd, $rr", [
445                                                (set i16
446                                                 : $rd, (adde i16
447                                                         : $src, i16
448                                                         : $rr)),
449                                                (implicit SREG)
450                                              ]>;
452   // AIDW Rd, k
453   // Adds an immediate 6-bit value K to Rd, placing the result in Rd.
454   def ADIWRdK
455       : FWRdK<0b0,
456               (outs IWREGS
457                : $rd),
458               (ins IWREGS
459                : $src, imm_arith6
460                : $k),
461               "adiw\t$rd, $k",
462               [(set i16
463                 : $rd, (add i16
464                         : $src, uimm6
465                         : $k)),
466                (implicit SREG)]>,
467         Requires<[HasADDSUBIW]>;
470 //===----------------------------------------------------------------------===//
471 // Subtraction
472 //===----------------------------------------------------------------------===//
473 let Constraints = "$src = $rd", Defs = [SREG] in {
474   // SUB Rd, Rr
475   // Subtracts the 8-bit value of Rr from Rd and places the value in Rd.
476   def SUBRdRr
477       : FRdRr<0b0001, 0b10,
478               (outs GPR8
479                : $rd),
480               (ins GPR8
481                : $src, GPR8
482                : $rr),
483               "sub\t$rd, $rr",
484               [(set i8
485                 : $rd, (sub i8
486                         : $src, i8
487                         : $rr)),
488                (implicit SREG)]>;
490   // SUBW Rd+1:Rd, Rr+1:Rr
491   // Subtracts two 16-bit values and places the result into Rd.
492   //
493   // Expands to:
494   // sub Rd,   Rr
495   // sbc Rd+1, Rr+1
496   def SUBWRdRr
497       : Pseudo<(outs DREGS
498                 : $rd),
499                (ins DREGS
500                 : $src, DREGS
501                 : $rr),
502                "subw\t$rd, $rr",
503                [(set i16
504                  : $rd, (sub i16
505                          : $src, i16
506                          : $rr)),
507                 (implicit SREG)]>;
509   def SUBIRdK
510       : FRdK<0b0101,
511              (outs LD8
512               : $rd),
513              (ins LD8
514               : $src, imm_ldi8
515               : $k),
516              "subi\t$rd, $k",
517              [(set i8
518                : $rd, (sub i8
519                        : $src, imm
520                        : $k)),
521               (implicit SREG)]>;
523   // SUBIW Rd+1:Rd, K+1:K
524   //
525   // Expands to:
526   // subi Rd,   K
527   // sbci Rd+1, K+1
528   def SUBIWRdK
529       : Pseudo<(outs DLDREGS
530                 : $rd),
531                (ins DLDREGS
532                 : $src, i16imm
533                 : $rr),
534                "subiw\t$rd, $rr",
535                [(set i16
536                  : $rd, (sub i16
537                          : $src, imm
538                          : $rr)),
539                 (implicit SREG)]>;
541   def SBIWRdK
542       : FWRdK<0b1,
543               (outs IWREGS
544                : $rd),
545               (ins IWREGS
546                : $src, imm_arith6
547                : $k),
548               "sbiw\t$rd, $k",
549               [(set i16
550                 : $rd, (sub i16
551                         : $src, uimm6
552                         : $k)),
553                (implicit SREG)]>,
554         Requires<[HasADDSUBIW]>;
556   // Subtract with carry operations which must read the carry flag in SREG.
557   let Uses = [SREG] in {
558     def SBCRdRr
559         : FRdRr<0b0000, 0b10,
560                 (outs GPR8
561                  : $rd),
562                 (ins GPR8
563                  : $src, GPR8
564                  : $rr),
565                 "sbc\t$rd, $rr",
566                 [(set i8
567                   : $rd, (sube i8
568                           : $src, i8
569                           : $rr)),
570                  (implicit SREG)]>;
572     // SBCW Rd+1:Rd, Rr+1:Rr
573     //
574     // Expands to:
575     // sbc Rd,   Rr
576     // sbc Rd+1, Rr+1
577     def SBCWRdRr : Pseudo<(outs DREGS
578                            : $rd),
579                           (ins DREGS
580                            : $src, DREGS
581                            : $rr),
582                           "sbcw\t$rd, $rr", [
583                             (set i16
584                              : $rd, (sube i16
585                                      : $src, i16
586                                      : $rr)),
587                             (implicit SREG)
588                           ]>;
590     def SBCIRdK
591         : FRdK<0b0100,
592                (outs LD8
593                 : $rd),
594                (ins LD8
595                 : $src, imm_ldi8
596                 : $k),
597                "sbci\t$rd, $k",
598                [(set i8
599                  : $rd, (sube i8
600                          : $src, imm
601                          : $k)),
602                 (implicit SREG)]>;
604     // SBCIW Rd+1:Rd, K+1:K
605     // sbci Rd,   K
606     // sbci Rd+1, K+1
607     def SBCIWRdK : Pseudo<(outs DLDREGS
608                            : $rd),
609                           (ins DLDREGS
610                            : $src, i16imm
611                            : $rr),
612                           "sbciw\t$rd, $rr", [
613                             (set i16
614                              : $rd, (sube i16
615                                      : $src, imm
616                                      : $rr)),
617                             (implicit SREG)
618                           ]>;
619   }
622 //===----------------------------------------------------------------------===//
623 // Increment and Decrement
624 //===----------------------------------------------------------------------===//
625 let Constraints = "$src = $rd", Defs = [SREG] in {
626   def INCRd
627       : FRd<0b1001, 0b0100011,
628             (outs GPR8
629              : $rd),
630             (ins GPR8
631              : $src),
632             "inc\t$rd", [(set i8
633                           : $rd, (add i8
634                                   : $src, 1)),
635                          (implicit SREG)]>;
637   def DECRd
638       : FRd<0b1001, 0b0101010,
639             (outs GPR8
640              : $rd),
641             (ins GPR8
642              : $src),
643             "dec\t$rd", [(set i8
644                           : $rd, (add i8
645                                   : $src, -1)),
646                          (implicit SREG)]>;
649 //===----------------------------------------------------------------------===//
650 // Multiplication
651 //===----------------------------------------------------------------------===//
653 let isCommutable = 1, Defs = [R1, R0, SREG] in {
654   // MUL Rd, Rr
655   // Multiplies Rd by Rr and places the result into R1:R0.
656   let usesCustomInserter = 1 in {
657     def MULRdRr : FRdRr<0b1001, 0b11, (outs),
658                         (ins GPR8
659                          : $rd, GPR8
660                          : $rr),
661                         "mul\t$rd, $rr",
662                         [/*(set R1, R0, (smullohi i8:$rd, i8:$rr))*/]>,
663                   Requires<[SupportsMultiplication]>;
665     def MULSRdRr : FMUL2RdRr<0, (outs),
666                              (ins LD8
667                               : $rd, LD8
668                               : $rr),
669                              "muls\t$rd, $rr", []>,
670                    Requires<[SupportsMultiplication]>;
671   }
673   def MULSURdRr : FMUL2RdRr<1, (outs),
674                             (ins LD8lo
675                              : $rd, LD8lo
676                              : $rr),
677                             "mulsu\t$rd, $rr", []>,
678                   Requires<[SupportsMultiplication]>;
680   def FMUL : FFMULRdRr<0b01, (outs),
681                        (ins LD8lo
682                         : $rd, LD8lo
683                         : $rr),
684                        "fmul\t$rd, $rr", []>,
685              Requires<[SupportsMultiplication]>;
687   def FMULS : FFMULRdRr<0b10, (outs),
688                         (ins LD8lo
689                          : $rd, LD8lo
690                          : $rr),
691                         "fmuls\t$rd, $rr", []>,
692               Requires<[SupportsMultiplication]>;
694   def FMULSU : FFMULRdRr<0b11, (outs),
695                          (ins LD8lo
696                           : $rd, LD8lo
697                           : $rr),
698                          "fmulsu\t$rd, $rr", []>,
699                Requires<[SupportsMultiplication]>;
702 let Defs =
703     [R15, R14, R13, R12, R11, R10, R9, R8, R7, R6, R5, R4, R3, R2, R1,
704      R0] in def DESK : FDES<(outs),
705                             (ins i8imm
706                              : $k),
707                             "des\t$k", []>,
708     Requires<[HasDES]>;
710 //===----------------------------------------------------------------------===//
711 // Logic
712 //===----------------------------------------------------------------------===//
713 let Constraints = "$src = $rd", Defs = [SREG] in {
714   // Register-Register logic instructions (which have the
715   // property of commutativity).
716   let isCommutable = 1 in {
717     def ANDRdRr
718         : FRdRr<0b0010, 0b00,
719                 (outs GPR8
720                  : $rd),
721                 (ins GPR8
722                  : $src, GPR8
723                  : $rr),
724                 "and\t$rd, $rr",
725                 [(set i8
726                   : $rd, (and i8
727                           : $src, i8
728                           : $rr)),
729                  (implicit SREG)]>;
731     // ANDW Rd+1:Rd, Rr+1:Rr
732     //
733     // Expands to:
734     // and Rd,   Rr
735     // and Rd+1, Rr+1
736     def ANDWRdRr : Pseudo<(outs DREGS
737                            : $rd),
738                           (ins DREGS
739                            : $src, DREGS
740                            : $rr),
741                           "andw\t$rd, $rr", [
742                             (set i16
743                              : $rd, (and i16
744                                      : $src, i16
745                                      : $rr)),
746                             (implicit SREG)
747                           ]>;
749     def ORRdRr
750         : FRdRr<0b0010, 0b10,
751                 (outs GPR8
752                  : $rd),
753                 (ins GPR8
754                  : $src, GPR8
755                  : $rr),
756                 "or\t$rd, $rr",
757                 [(set i8
758                   : $rd, (or i8
759                           : $src, i8
760                           : $rr)),
761                  (implicit SREG)]>;
763     // ORW Rd+1:Rd, Rr+1:Rr
764     //
765     // Expands to:
766     // or Rd,   Rr
767     // or Rd+1, Rr+1
768     def ORWRdRr : Pseudo<(outs DREGS
769                           : $rd),
770                          (ins DREGS
771                           : $src, DREGS
772                           : $rr),
773                          "orw\t$rd, $rr", [
774                            (set i16
775                             : $rd, (or i16
776                                     : $src, i16
777                                     : $rr)),
778                            (implicit SREG)
779                          ]>;
781     def EORRdRr
782         : FRdRr<0b0010, 0b01,
783                 (outs GPR8
784                  : $rd),
785                 (ins GPR8
786                  : $src, GPR8
787                  : $rr),
788                 "eor\t$rd, $rr",
789                 [(set i8
790                   : $rd, (xor i8
791                           : $src, i8
792                           : $rr)),
793                  (implicit SREG)]>;
795     // EORW Rd+1:Rd, Rr+1:Rr
796     //
797     // Expands to:
798     // eor Rd,   Rr
799     // eor Rd+1, Rr+1
800     def EORWRdRr : Pseudo<(outs DREGS
801                            : $rd),
802                           (ins DREGS
803                            : $src, DREGS
804                            : $rr),
805                           "eorw\t$rd, $rr", [
806                             (set i16
807                              : $rd, (xor i16
808                                      : $src, i16
809                                      : $rr)),
810                             (implicit SREG)
811                           ]>;
812   }
814   def ANDIRdK
815       : FRdK<0b0111,
816              (outs LD8
817               : $rd),
818              (ins LD8
819               : $src, imm_ldi8
820               : $k),
821              "andi\t$rd, $k",
822              [(set i8
823                : $rd, (and i8
824                        : $src, imm
825                        : $k)),
826               (implicit SREG)]>;
828   // ANDI Rd+1:Rd, K+1:K
829   //
830   // Expands to:
831   // andi Rd,   K
832   // andi Rd+1, K+1
833   def ANDIWRdK
834       : Pseudo<(outs DLDREGS
835                 : $rd),
836                (ins DLDREGS
837                 : $src, i16imm
838                 : $k),
839                "andiw\t$rd, $k",
840                [(set i16
841                  : $rd, (and i16
842                          : $src, imm
843                          : $k)),
844                 (implicit SREG)]>;
846   def ORIRdK
847       : FRdK<0b0110,
848              (outs LD8
849               : $rd),
850              (ins LD8
851               : $src, imm_ldi8
852               : $k),
853              "ori\t$rd, $k",
854              [(set i8
855                : $rd, (or i8
856                        : $src, imm
857                        : $k)),
858               (implicit SREG)]>;
860   // ORIW Rd+1:Rd, K+1,K
861   //
862   // Expands to:
863   // ori Rd,   K
864   // ori Rd+1, K+1
865   def ORIWRdK
866       : Pseudo<(outs DLDREGS
867                 : $rd),
868                (ins DLDREGS
869                 : $src, i16imm
870                 : $rr),
871                "oriw\t$rd, $rr",
872                [(set i16
873                  : $rd, (or i16
874                          : $src, imm
875                          : $rr)),
876                 (implicit SREG)]>;
879 //===----------------------------------------------------------------------===//
880 // One's/Two's Complement
881 //===----------------------------------------------------------------------===//
882 let Constraints = "$src = $rd", Defs = [SREG] in {
883   def COMRd
884       : FRd<0b1001, 0b0100000,
885             (outs GPR8
886              : $rd),
887             (ins GPR8
888              : $src),
889             "com\t$rd", [(set i8
890                           : $rd, (not i8
891                                   : $src)),
892                          (implicit SREG)]>;
894   // COMW Rd+1:Rd
895   //
896   // Expands to:
897   // com Rd
898   // com Rd+1
899   def COMWRd : Pseudo<(outs DREGS
900                        : $rd),
901                       (ins DREGS
902                        : $src),
903                       "comw\t$rd",
904                       [(set i16
905                         : $rd, (not i16
906                                 : $src)),
907                        (implicit SREG)]>;
909   def NEGRd
910       : FRd<0b1001, 0b0100001,
911             (outs GPR8
912              : $rd),
913             (ins GPR8
914              : $src),
915             "neg\t$rd", [(set i8
916                           : $rd, (ineg i8
917                                   : $src)),
918                          (implicit SREG)]>;
920   // NEGW Rd+1:Rd
921   //
922   // Expands to:
923   // neg Rd+1
924   // neg Rd
925   // sbc Rd+1, r1
926   let hasSideEffects=0 in
927   def NEGWRd : Pseudo<(outs DREGS:$rd),
928                       (ins DREGS:$src, GPR8:$zero),
929                       "negw\t$rd",
930                       []>;
933 // TST Rd
934 // Test for zero of minus.
935 // This operation is identical to a `Rd AND Rd`.
936 def : InstAlias<"tst\t$rd", (ANDRdRr GPR8 : $rd, GPR8 : $rd)>;
938 // SBR Rd, K
940 // Mnemonic alias to 'ORI Rd, K'. Same bit pattern, same operands,
941 // same everything.
942 def : InstAlias<"sbr\t$rd, $k",
943                 (ORIRdK LD8
944                  : $rd, imm_ldi8
945                  : $k),
946                 /* Disable display, so we don't override ORI */ 0>;
948 //===----------------------------------------------------------------------===//
949 // Jump instructions
950 //===----------------------------------------------------------------------===//
951 let isBarrier = 1, isBranch = 1, isTerminator = 1 in {
952   def RJMPk : FBRk<0, (outs),
953                    (ins brtarget_13
954                     : $k),
955                    "rjmp\t$k", [(br bb
956                                  : $k)]>;
958   let isIndirectBranch = 1,
959       Uses = [R31R30] in def IJMP
960       : F16<0b1001010000001001, (outs), (ins), "ijmp", []>,
961       Requires<[HasIJMPCALL]>;
963   let isIndirectBranch = 1,
964       Uses = [R31R30] in def EIJMP
965       : F16<0b1001010000011001, (outs), (ins), "eijmp", []>,
966       Requires<[HasEIJMPCALL]>;
968   def JMPk : F32BRk<0b110, (outs),
969                     (ins call_target
970                      : $k),
971                     "jmp\t$k", []>,
972              Requires<[HasJMPCALL]>;
975 //===----------------------------------------------------------------------===//
976 // Call instructions
977 //===----------------------------------------------------------------------===//
978 let isCall = 1 in {
979   // SP is marked as a use to prevent stack-pointer assignments that appear
980   // immediately before calls from potentially appearing dead.
981   let Uses = [SP] in def RCALLk : FBRk<1, (outs), (ins rcalltarget_13:$k),
982                                        "rcall\t$k", [(AVRcall imm:$k)]>;
984   // SP is marked as a use to prevent stack-pointer assignments that appear
985   // immediately before calls from potentially appearing dead.
986   let Uses = [SP, R31R30] in def ICALL
987       : F16<0b1001010100001001, (outs), (ins variable_ops), "icall", []>,
988       Requires<[HasIJMPCALL]>;
990   // SP is marked as a use to prevent stack-pointer assignments that appear
991   // immediately before calls from potentially appearing dead.
992   let Uses = [SP, R31R30] in def EICALL
993       : F16<0b1001010100011001, (outs), (ins variable_ops), "eicall", []>,
994       Requires<[HasEIJMPCALL]>;
996   // SP is marked as a use to prevent stack-pointer assignments that appear
997   // immediately before calls from potentially appearing dead.
998   //
999   // TODO: the imm field can be either 16 or 22 bits in devices with more
1000   // than 64k of ROM, fix it once we support the largest devices.
1001   let Uses = [SP] in def CALLk : F32BRk<0b111, (outs), (ins call_target:$k),
1002                                         "call\t$k", [(AVRcall imm:$k)]>,
1003       Requires<[HasJMPCALL]>;
1006 //===----------------------------------------------------------------------===//
1007 // Return instructions.
1008 //===----------------------------------------------------------------------===//
1009 let isTerminator = 1, isReturn = 1, isBarrier = 1 in {
1010   def RET : F16<0b1001010100001000, (outs), (ins), "ret", [(AVRretflag)]>;
1012   def RETI : F16<0b1001010100011000, (outs), (ins), "reti", [(AVRretiflag)]>;
1015 //===----------------------------------------------------------------------===//
1016 // Compare operations.
1017 //===----------------------------------------------------------------------===//
1018 let Defs = [SREG] in {
1019   // CPSE Rd, Rr
1020   // Compare Rd and Rr, skipping the next instruction if they are equal.
1021   let isBarrier = 1, isBranch = 1,
1022       isTerminator = 1 in def CPSE : FRdRr<0b0001, 0b00, (outs),
1023                                            (ins GPR8
1024                                             : $rd, GPR8
1025                                             : $rr),
1026                                            "cpse\t$rd, $rr", []>;
1028   def CPRdRr
1029       : FRdRr<0b0001, 0b01, (outs),
1030               (ins GPR8
1031                : $rd, GPR8
1032                : $rr),
1033               "cp\t$rd, $rr", [(AVRcmp i8
1034                                 : $rd, i8
1035                                 : $rr),
1036                                (implicit SREG)]>;
1038   // CPW Rd+1:Rd, Rr+1:Rr
1039   //
1040   // Expands to:
1041   // cp  Rd,   Rr
1042   // cpc Rd+1, Rr+1
1043   def CPWRdRr : Pseudo<(outs),
1044                        (ins DREGS
1045                         : $src, DREGS
1046                         : $src2),
1047                        "cpw\t$src, $src2",
1048                        [(AVRcmp i16
1049                          : $src, i16
1050                          : $src2),
1051                         (implicit SREG)]>;
1053   let Uses = [SREG] in def CPCRdRr
1054       : FRdRr<0b0000, 0b01, (outs),
1055               (ins GPR8
1056                : $rd, GPR8
1057                : $rr),
1058               "cpc\t$rd, $rr", [(AVRcmpc i8
1059                                  : $rd, i8
1060                                  : $rr),
1061                                 (implicit SREG)]>;
1063   // CPCW Rd+1:Rd. Rr+1:Rr
1064   //
1065   // Expands to:
1066   // cpc Rd,   Rr
1067   // cpc Rd+1, Rr+1
1068   let Uses = [SREG] in def CPCWRdRr
1069       : Pseudo<(outs),
1070                (ins DREGS
1071                 : $src, DREGS
1072                 : $src2),
1073                "cpcw\t$src, $src2",
1074                [(AVRcmpc i16
1075                  : $src, i16
1076                  : $src2),
1077                 (implicit SREG)]>;
1079   // CPI Rd, K
1080   // Compares a register with an 8 bit immediate.
1081   def CPIRdK
1082       : FRdK<0b0011, (outs),
1083              (ins LD8
1084               : $rd, imm_ldi8
1085               : $k),
1086              "cpi\t$rd, $k", [(AVRcmp i8
1087                                : $rd, imm
1088                                : $k),
1089                               (implicit SREG)]>;
1092 //===----------------------------------------------------------------------===//
1093 // Register conditional skipping/branching operations.
1094 //===----------------------------------------------------------------------===//
1095 let isBranch = 1, isTerminator = 1 in {
1096   // Conditional skipping on GPR register bits, and
1097   // conditional skipping on IO register bits.
1098   let isBarrier = 1 in {
1099     def SBRCRrB : FRdB<0b10, (outs),
1100                        (ins GPR8
1101                         : $rd, i8imm
1102                         : $b),
1103                        "sbrc\t$rd, $b", []>;
1105     def SBRSRrB : FRdB<0b11, (outs),
1106                        (ins GPR8
1107                         : $rd, i8imm
1108                         : $b),
1109                        "sbrs\t$rd, $b", []>;
1111     def SBICAb : FIOBIT<0b01, (outs),
1112                         (ins imm_port5
1113                          : $addr, i8imm
1114                          : $b),
1115                         "sbic\t$addr, $b", []>;
1117     def SBISAb : FIOBIT<0b11, (outs),
1118                         (ins imm_port5
1119                          : $addr, i8imm
1120                          : $b),
1121                         "sbis\t$addr, $b", []>;
1122   }
1124   // Relative branches on status flag bits.
1125   let Uses = [SREG] in {
1126     // BRBS s, k
1127     // Branch if `s` flag in status register is set.
1128     def BRBSsk : FSK<0, (outs),
1129                      (ins i8imm
1130                       : $s, relbrtarget_7
1131                       : $k),
1132                      "brbs\t$s, $k", []>;
1134     // BRBC s, k
1135     // Branch if `s` flag in status register is clear.
1136     def BRBCsk : FSK<1, (outs),
1137                      (ins i8imm
1138                       : $s, relbrtarget_7
1139                       : $k),
1140                      "brbc\t$s, $k", []>;
1141   }
1144 // BRCS k
1145 // Branch if carry flag is set
1146 def : InstAlias<"brcs\t$k", (BRBSsk 0, relbrtarget_7 : $k)>;
1148 // BRCC k
1149 // Branch if carry flag is clear
1150 def : InstAlias<"brcc\t$k", (BRBCsk 0, relbrtarget_7 : $k)>;
1152 // BRHS k
1153 // Branch if half carry flag is set
1154 def : InstAlias<"brhs\t$k", (BRBSsk 5, relbrtarget_7 : $k)>;
1156 // BRHC k
1157 // Branch if half carry flag is clear
1158 def : InstAlias<"brhc\t$k", (BRBCsk 5, relbrtarget_7 : $k)>;
1160 // BRTS k
1161 // Branch if the T flag is set
1162 def : InstAlias<"brts\t$k", (BRBSsk 6, relbrtarget_7 : $k)>;
1164 // BRTC k
1165 // Branch if the T flag is clear
1166 def : InstAlias<"brtc\t$k", (BRBCsk 6, relbrtarget_7 : $k)>;
1168 // BRVS k
1169 // Branch if the overflow flag is set
1170 def : InstAlias<"brvs\t$k", (BRBSsk 3, relbrtarget_7 : $k)>;
1172 // BRVC k
1173 // Branch if the overflow flag is clear
1174 def : InstAlias<"brvc\t$k", (BRBCsk 3, relbrtarget_7 : $k)>;
1176 // BRIE k
1177 // Branch if the global interrupt flag is enabled
1178 def : InstAlias<"brie\t$k", (BRBSsk 7, relbrtarget_7 : $k)>;
1180 // BRID k
1181 // Branch if the global interrupt flag is disabled
1182 def : InstAlias<"brid\t$k", (BRBCsk 7, relbrtarget_7 : $k)>;
1184 //===----------------------------------------------------------------------===//
1185 // PC-relative conditional branches
1186 //===----------------------------------------------------------------------===//
1187 // Based on status register. We cannot simplify these into instruction aliases
1188 // because we also need to be able to specify a pattern to match for ISel.
1189 let isBranch = 1, isTerminator = 1, Uses = [SREG] in {
1190   def BREQk : FBRsk<0, 0b001, (outs),
1191                     (ins relbrtarget_7
1192                      : $k),
1193                     "breq\t$k", [(AVRbrcond bb
1194                                   : $k, AVR_COND_EQ)]>;
1196   def BRNEk : FBRsk<1, 0b001, (outs),
1197                     (ins relbrtarget_7
1198                      : $k),
1199                     "brne\t$k", [(AVRbrcond bb
1200                                  : $k, AVR_COND_NE)]>;
1202   def BRSHk : FBRsk<1, 0b000, (outs),
1203                     (ins relbrtarget_7
1204                      : $k),
1205                     "brsh\t$k", [(AVRbrcond bb
1206                                  : $k, AVR_COND_SH)]>;
1208   def BRLOk : FBRsk<0, 0b000, (outs),
1209                     (ins relbrtarget_7
1210                      : $k),
1211                     "brlo\t$k", [(AVRbrcond bb
1212                                  : $k, AVR_COND_LO)]>;
1214   def BRMIk : FBRsk<0, 0b010, (outs),
1215                     (ins relbrtarget_7
1216                      : $k),
1217                     "brmi\t$k", [(AVRbrcond bb
1218                                  : $k, AVR_COND_MI)]>;
1220   def BRPLk : FBRsk<1, 0b010, (outs),
1221                     (ins relbrtarget_7
1222                      : $k),
1223                     "brpl\t$k", [(AVRbrcond bb
1224                                  : $k, AVR_COND_PL)]>;
1226   def BRGEk : FBRsk<1, 0b100, (outs),
1227                     (ins relbrtarget_7
1228                      : $k),
1229                     "brge\t$k", [(AVRbrcond bb
1230                                  : $k, AVR_COND_GE)]>;
1232   def BRLTk : FBRsk<0, 0b100, (outs),
1233                     (ins relbrtarget_7
1234                      : $k),
1235                     "brlt\t$k", [(AVRbrcond bb
1236                                  : $k, AVR_COND_LT)]>;
1239 //===----------------------------------------------------------------------===//
1240 // Data transfer instructions
1241 //===----------------------------------------------------------------------===//
1242 // 8 and 16-bit register move instructions.
1243 let hasSideEffects = 0 in {
1244   def MOVRdRr : FRdRr<0b0010, 0b11,
1245                       (outs GPR8
1246                        : $rd),
1247                       (ins GPR8
1248                        : $rr),
1249                       "mov\t$rd, $rr", []>;
1251   def MOVWRdRr : FMOVWRdRr<(outs DREGS
1252                             : $rd),
1253                            (ins DREGS
1254                             : $rr),
1255                            "movw\t$rd, $rr", []>,
1256                  Requires<[HasMOVW]>;
1259 // Load immediate values into registers.
1260 let isReMaterializable = 1 in {
1261   def LDIRdK : FRdK<0b1110,
1262                     (outs LD8
1263                      : $rd),
1264                     (ins imm_ldi8
1265                      : $k),
1266                     "ldi\t$rd, $k", [(set i8
1267                                       : $rd, imm
1268                                       : $k)]>;
1270   // LDIW Rd+1:Rd, K+1:K
1271   //
1272   // Expands to:
1273   // ldi Rd,   K
1274   // ldi Rd+1, K+1
1275   def LDIWRdK : Pseudo<(outs DLDREGS
1276                         : $dst),
1277                        (ins i16imm
1278                         : $src),
1279                        "ldiw\t$dst, $src", [(set i16
1280                                              : $dst, imm
1281                                              : $src)]>;
1284 // Load from data space into register.
1285 let canFoldAsLoad = 1, isReMaterializable = 1 in {
1286   def LDSRdK : F32DM<0b0,
1287                      (outs GPR8
1288                       : $rd),
1289                      (ins imm16
1290                       : $k),
1291                      "lds\t$rd, $k", [(set i8
1292                                        : $rd, (load imm
1293                                                : $k))]>,
1294                Requires<[HasSRAM, HasNonTinyEncoding]>;
1296   // Load from data space into register, which is only available on AVRTiny.
1297   def LDSRdKTiny : FLDSSTSTINY<0b0, (outs LD8:$rd), (ins imm7tiny:$k),
1298                                "lds\t$rd, $k", []>,
1299                    Requires<[HasSRAM, HasTinyEncoding]>;
1301   // LDSW Rd+1:Rd, K+1:K
1302   //
1303   // Expands to:
1304   // lds Rd,  (K+1:K)
1305   // lds Rd+1 (K+1:K) + 1
1306   def LDSWRdK : Pseudo<(outs DREGS
1307                         : $dst),
1308                        (ins i16imm
1309                         : $src),
1310                        "ldsw\t$dst, $src", [(set i16
1311                                              : $dst, (load imm
1312                                                       : $src))]>,
1313                 Requires<[HasSRAM, HasNonTinyEncoding]>;
1316 // Indirect loads.
1317 let canFoldAsLoad = 1, isReMaterializable = 1 in {
1318   def LDRdPtr : FSTLD<0, 0b00,
1319                       (outs GPR8
1320                        : $reg),
1321                       (ins LDSTPtrReg
1322                        : $ptrreg),
1323                       "ld\t$reg, $ptrreg", [(set GPR8
1324                                              : $reg, (load i16
1325                                                       : $ptrreg))]>,
1326                 Requires<[HasSRAM]>;
1328   // LDW Rd+1:Rd, P
1329   //
1330   // Expands to:
1331   //   ld  Rd,   P
1332   //   ldd Rd+1, P+1
1333   // On reduced tiny cores, this instruction expands to:
1334   //   ld    Rd,   P+
1335   //   ld    Rd+1, P+
1336   //   subiw P,    2
1337   let Constraints = "@earlyclobber $reg" in def LDWRdPtr
1338       : Pseudo<(outs DREGS
1339                 : $reg),
1340                (ins PTRDISPREGS
1341                 : $ptrreg),
1342                "ldw\t$reg, $ptrreg", [(set i16
1343                                        : $reg, (load i16
1344                                                 : $ptrreg))]>,
1345       Requires<[HasSRAM]>;
1348 // Indirect loads (with postincrement or predecrement).
1349 let mayLoad = 1, hasSideEffects = 0,
1350     Constraints = "$ptrreg = $base_wb,@earlyclobber $reg" in {
1351   def LDRdPtrPi : FSTLD<0, 0b01,
1352                         (outs GPR8
1353                          : $reg, PTRREGS
1354                          : $base_wb),
1355                         (ins LDSTPtrReg
1356                          : $ptrreg),
1357                         "ld\t$reg, $ptrreg+", []>,
1358                   Requires<[HasSRAM]>;
1360   // LDW Rd+1:Rd, P+
1361   // Expands to:
1362   // ld Rd,   P+
1363   // ld Rd+1, P+
1364   def LDWRdPtrPi : Pseudo<(outs DREGS
1365                            : $reg, PTRREGS
1366                            : $base_wb),
1367                           (ins PTRREGS
1368                            : $ptrreg),
1369                           "ldw\t$reg, $ptrreg+", []>,
1370                    Requires<[HasSRAM]>;
1372   def LDRdPtrPd : FSTLD<0, 0b10,
1373                         (outs GPR8
1374                          : $reg, PTRREGS
1375                          : $base_wb),
1376                         (ins LDSTPtrReg
1377                          : $ptrreg),
1378                         "ld\t$reg, -$ptrreg", []>,
1379                   Requires<[HasSRAM]>;
1381   // LDW Rd+1:Rd, -P
1382   //
1383   // Expands to:
1384   // ld Rd+1, -P
1385   // ld Rd,   -P
1386   def LDWRdPtrPd : Pseudo<(outs DREGS
1387                            : $reg, PTRREGS
1388                            : $base_wb),
1389                           (ins PTRREGS
1390                            : $ptrreg),
1391                           "ldw\t$reg, -$ptrreg", []>,
1392                    Requires<[HasSRAM]>;
1395 // Load indirect with displacement operations.
1396 let canFoldAsLoad = 1, isReMaterializable = 1 in {
1397   let Constraints = "@earlyclobber $reg" in def LDDRdPtrQ
1398       : FSTDLDD<0,
1399                 (outs GPR8
1400                  : $reg),
1401                 (ins memri
1402                  : $memri),
1403                 "ldd\t$reg, $memri", [(set i8
1404                                        : $reg, (load addr
1405                                                 : $memri))]>,
1406       Requires<[HasSRAM, HasNonTinyEncoding]>;
1408   // LDDW Rd+1:Rd, P+q
1409   //
1410   // Expands to:
1411   //   ldd Rd,   P+q
1412   //   ldd Rd+1, P+q+1
1413   // On reduced tiny cores, this instruction expands to:
1414   //   subiw P,    -q
1415   //   ld    Rd,   P+
1416   //   ld    Rd+1, P+
1417   //   subiw P,    q+2
1418   let Constraints = "@earlyclobber $dst" in def LDDWRdPtrQ
1419       : Pseudo<(outs DREGS
1420                 : $dst),
1421                (ins memri
1422                 : $memri),
1423                "lddw\t$dst, $memri", [(set i16
1424                                        : $dst, (load addr
1425                                                 : $memri))]>,
1426       Requires<[HasSRAM]>;
1428   // An identical pseudo instruction to LDDWRdPtrQ, expect restricted to the Y
1429   // register and without the @earlyclobber flag.
1430   //
1431   // Used to work around a bug caused by the register allocator not
1432   // being able to handle the expansion of a COPY into an machine instruction
1433   // that has an earlyclobber flag. This is because the register allocator will
1434   // try expand a copy from a register slot into an earlyclobber instruction.
1435   // Instructions that are earlyclobber need to be in a dedicated earlyclobber
1436   // slot.
1437   //
1438   // This pseudo instruction can be used pre-AVR pseudo expansion in order to
1439   // get a frame index load without directly using earlyclobber instructions.
1440   //
1441   // The pseudo expansion pass trivially expands this into LDDWRdPtrQ.
1442   //
1443   // This instruction may be removed once PR13375 is fixed.
1444   let mayLoad = 1,
1445       hasSideEffects = 0 in def LDDWRdYQ : Pseudo<(outs DREGS
1446                                                    : $dst),
1447                                                   (ins memri
1448                                                    : $memri),
1449                                                   "lddw\t$dst, $memri", []>,
1450       Requires<[HasSRAM]>;
1453 class AtomicLoad<PatFrag Op, RegisterClass DRC, RegisterClass PTRRC>
1454     : Pseudo<(outs DRC
1455               : $rd),
1456              (ins PTRRC
1457               : $rr),
1458              "atomic_op", [(set DRC
1459                             : $rd, (Op i16
1460                                     : $rr))]>;
1462 class AtomicStore<PatFrag Op, RegisterClass DRC, RegisterClass PTRRC>
1463     : Pseudo<(outs),
1464              (ins PTRRC
1465               : $rd, DRC
1466               : $rr),
1467              "atomic_op", [(Op i16
1468                             : $rd, DRC
1469                             : $rr)]>;
1471 class AtomicLoadOp<PatFrag Op, RegisterClass DRC, RegisterClass PTRRC>
1472     : Pseudo<(outs DRC:$rd),
1473              (ins PTRRC:$rr, DRC:$operand),
1474              "atomic_op", [(set DRC:$rd, (Op i16:$rr, DRC:$operand))]>;
1476 // Atomic instructions
1477 // ===================
1479 // 8-bit operations can use any pointer register because
1480 // they are expanded directly into an LD/ST instruction.
1482 // 16-bit operations use 16-bit load/store postincrement instructions,
1483 // which require PTRDISPREGS.
1485 def AtomicLoad8 : AtomicLoad<atomic_load_8, GPR8, PTRREGS>;
1486 def AtomicLoad16 : AtomicLoad<atomic_load_16, DREGS, PTRDISPREGS>;
1488 def AtomicStore8 : AtomicStore<atomic_store_8, GPR8, PTRREGS>;
1489 def AtomicStore16 : AtomicStore<atomic_store_16, DREGS, PTRDISPREGS>;
1491 class AtomicLoadOp8<PatFrag Op> : AtomicLoadOp<Op, GPR8, PTRREGS>;
1492 class AtomicLoadOp16<PatFrag Op> : AtomicLoadOp<Op, DREGS, PTRDISPREGS>;
1494 let usesCustomInserter=1 in {
1495   def AtomicLoadAdd8 : AtomicLoadOp8<atomic_load_add_8>;
1496   def AtomicLoadAdd16 : AtomicLoadOp16<atomic_load_add_16>;
1497   def AtomicLoadSub8 : AtomicLoadOp8<atomic_load_sub_8>;
1498   def AtomicLoadSub16 : AtomicLoadOp16<atomic_load_sub_16>;
1499   def AtomicLoadAnd8 : AtomicLoadOp8<atomic_load_and_8>;
1500   def AtomicLoadAnd16 : AtomicLoadOp16<atomic_load_and_16>;
1501   def AtomicLoadOr8 : AtomicLoadOp8<atomic_load_or_8>;
1502   def AtomicLoadOr16 : AtomicLoadOp16<atomic_load_or_16>;
1503   def AtomicLoadXor8 : AtomicLoadOp8<atomic_load_xor_8>;
1504   def AtomicLoadXor16 : AtomicLoadOp16<atomic_load_xor_16>;
1506 def AtomicFence
1507     : Pseudo<(outs), (ins), "atomic_fence", [(atomic_fence timm, timm)]>;
1509 // Indirect store from register to data space.
1510 def STSKRr : F32DM<0b1, (outs),
1511                    (ins imm16
1512                     : $k, GPR8
1513                     : $rd),
1514                    "sts\t$k, $rd", [(store i8
1515                                      : $rd, imm
1516                                      : $k)]>,
1517              Requires<[HasSRAM, HasNonTinyEncoding]>;
1519 // Store from register to data space, which is only available on AVRTiny.
1520 def STSKRrTiny : FLDSSTSTINY<0b1, (outs), (ins imm7tiny:$k, LD8:$rd),
1521                              "sts\t$k, $rd", []>,
1522                  Requires<[HasSRAM, HasTinyEncoding]>;
1524 // STSW K+1:K, Rr+1:Rr
1526 // Expands to:
1527 // sts Rr+1, (K+1:K) + 1
1528 // sts Rr,   (K+1:K)
1529 def STSWKRr : Pseudo<(outs),
1530                      (ins i16imm
1531                       : $dst, DREGS
1532                       : $src),
1533                      "stsw\t$dst, $src", [(store i16
1534                                            : $src, imm
1535                                            : $dst)]>,
1536               Requires<[HasSRAM, HasNonTinyEncoding]>;
1538 // Indirect stores.
1539 // ST P, Rr
1540 // Stores the value of Rr into the location addressed by pointer P.
1541 def STPtrRr : FSTLD<1, 0b00, (outs),
1542                     (ins LDSTPtrReg
1543                      : $ptrreg, GPR8
1544                      : $reg),
1545                     "st\t$ptrreg, $reg", [(store GPR8
1546                                            : $reg, i16
1547                                            : $ptrreg)]>,
1548               Requires<[HasSRAM]>;
1550 // STW P, Rr+1:Rr
1551 // Stores the value of Rr into the location addressed by pointer P.
1553 // Expands to:
1554 //   st P, Rr
1555 //   std P+1, Rr+1
1556 // On reduced tiny cores, this instruction expands to:
1557 //   st    P+, Rr
1558 //   st    P+, Rr+1
1559 //   subiw P,  q+2
1560 def STWPtrRr : Pseudo<(outs),
1561                       (ins PTRDISPREGS
1562                        : $ptrreg, DREGS
1563                        : $reg),
1564                       "stw\t$ptrreg, $reg", [(store i16
1565                                               : $reg, i16
1566                                               : $ptrreg)]>,
1567                Requires<[HasSRAM]>;
1569 // Indirect stores (with postincrement or predecrement).
1570 let Constraints = "$ptrreg = $base_wb,@earlyclobber $base_wb" in {
1572   // ST P+, Rr
1573   // Stores the value of Rr into the location addressed by pointer P.
1574   // Post increments P.
1575   def STPtrPiRr : FSTLD<1, 0b01,
1576                         (outs LDSTPtrReg
1577                          : $base_wb),
1578                         (ins LDSTPtrReg
1579                          : $ptrreg, GPR8
1580                          : $reg, i8imm
1581                          : $offs),
1582                         "st\t$ptrreg+, $reg", [(set i16
1583                                                 : $base_wb, (post_store GPR8
1584                                                              : $reg, i16
1585                                                              : $ptrreg, imm
1586                                                              : $offs))]>,
1587                   Requires<[HasSRAM]>;
1589   // STW P+, Rr+1:Rr
1590   // Stores the value of Rr into the location addressed by pointer P.
1591   // Post increments P.
1592   //
1593   // Expands to:
1594   // st P+, Rr
1595   // st P+, Rr+1
1596   def STWPtrPiRr : Pseudo<(outs PTRREGS
1597                            : $base_wb),
1598                           (ins PTRREGS
1599                            : $ptrreg, DREGS
1600                            : $trh, i8imm
1601                            : $offs),
1602                           "stw\t$ptrreg+, $trh", [(set PTRREGS
1603                                                    : $base_wb, (post_store DREGS
1604                                                                 : $trh, PTRREGS
1605                                                                 : $ptrreg, imm
1606                                                                 : $offs))]>,
1607                    Requires<[HasSRAM]>;
1609   // ST -P, Rr
1610   // Stores the value of Rr into the location addressed by pointer P.
1611   // Pre decrements P.
1612   def STPtrPdRr : FSTLD<1, 0b10,
1613                         (outs LDSTPtrReg
1614                          : $base_wb),
1615                         (ins LDSTPtrReg
1616                          : $ptrreg, GPR8
1617                          : $reg, i8imm
1618                          : $offs),
1619                         "st\t-$ptrreg, $reg", [(set i16
1620                                                 : $base_wb, (pre_store GPR8
1621                                                              : $reg, i16
1622                                                              : $ptrreg, imm
1623                                                              : $offs))]>,
1624                   Requires<[HasSRAM]>;
1626   // STW -P, Rr+1:Rr
1627   // Stores the value of Rr into the location addressed by pointer P.
1628   // Pre decrements P.
1629   //
1630   // Expands to:
1631   // st -P, Rr+1
1632   // st -P, Rr
1633   def STWPtrPdRr : Pseudo<(outs PTRREGS
1634                            : $base_wb),
1635                           (ins PTRREGS
1636                            : $ptrreg, DREGS
1637                            : $reg, i8imm
1638                            : $offs),
1639                           "stw\t-$ptrreg, $reg", [(set PTRREGS
1640                                                    : $base_wb, (pre_store i16
1641                                                                 : $reg, i16
1642                                                                 : $ptrreg, imm
1643                                                                 : $offs))]>,
1644                    Requires<[HasSRAM]>;
1647 // Store indirect with displacement operations.
1648 // STD P+q, Rr
1649 // Stores the value of Rr into the location addressed by pointer P with a
1650 // displacement of q. Does not modify P.
1651 def STDPtrQRr : FSTDLDD<1, (outs),
1652                         (ins memri
1653                          : $memri, GPR8
1654                          : $reg),
1655                         "std\t$memri, $reg", [(store i8
1656                                                : $reg, addr
1657                                                : $memri)]>,
1658                 Requires<[HasSRAM, HasNonTinyEncoding]>;
1660 // STDW P+q, Rr+1:Rr
1661 // Stores the value of Rr into the location addressed by pointer P with a
1662 // displacement of q. Does not modify P.
1664 // Expands to:
1665 //   std P+q,   Rr
1666 //   std P+q+1, Rr+1
1667 // On reduced tiny cores, this instruction expands to:
1668 //   subiw P,  -q
1669 //   st    P+, Rr
1670 //   st    P+, Rr+1
1671 //   subiw P,  q+2
1672 def STDWPtrQRr : Pseudo<(outs),
1673                         (ins memri
1674                          : $memri, DREGS
1675                          : $src),
1676                         "stdw\t$memri, $src", [(store i16
1677                                                 : $src, addr
1678                                                 : $memri)]>,
1679                  Requires<[HasSRAM]>;
1681 // Load program memory operations.
1682 let canFoldAsLoad = 1, isReMaterializable = 1, mayLoad = 1,
1683     hasSideEffects = 0 in {
1684   let Defs = [R0],
1685       Uses = [R31R30] in def LPM
1686       : F16<0b1001010111001000, (outs), (ins), "lpm", []>,
1687       Requires<[HasLPM]>;
1689   def LPMRdZ : FLPMX<0, 0,
1690                      (outs GPR8
1691                       : $rd),
1692                      (ins ZREG
1693                       : $z),
1694                      "lpm\t$rd, $z", []>,
1695                Requires<[HasLPMX]>;
1697   // Load program memory, while postincrementing the Z register.
1698   let Defs = [R31R30] in {
1699     def LPMRdZPi : FLPMX<0, 1,
1700                          (outs GPR8
1701                           : $rd),
1702                          (ins ZREG
1703                           : $z),
1704                          "lpm\t$rd, $z+", []>,
1705                    Requires<[HasLPMX]>;
1707     let Constraints = "@earlyclobber $dst" in
1708     def LPMWRdZ : Pseudo<(outs DREGS
1709                           : $dst),
1710                          (ins ZREG
1711                           : $z),
1712                          "lpmw\t$dst, $z", []>,
1713                   Requires<[HasLPMX]>;
1715     def LPMWRdZPi : Pseudo<(outs DREGS
1716                             : $dst),
1717                            (ins ZREG
1718                             : $z),
1719                            "lpmw\t$dst, $z+", []>,
1720                     Requires<[HasLPMX]>;
1721   }
1724 // Extended load program memory operations.
1725 let mayLoad = 1, hasSideEffects = 0 in {
1726   let Defs = [R0],
1727       Uses = [R31R30] in def ELPM
1728       : F16<0b1001010111011000, (outs), (ins), "elpm", []>,
1729       Requires<[HasELPM]>;
1731   def ELPMRdZ : FLPMX<1, 0, (outs GPR8:$rd), (ins ZREG:$z),
1732                       "elpm\t$rd, $z", []>,
1733                 Requires<[HasELPMX]>;
1735   let Defs = [R31R30] in {
1736     def ELPMRdZPi : FLPMX<1, 1, (outs GPR8:$rd), (ins ZREG:$z),
1737                           "elpm\t$rd, $z+", []>,
1738                     Requires<[HasELPMX]>;
1739   }
1741   // These pseudos are combination of the OUT and ELPM instructions.
1742   let Defs = [R31R30], hasSideEffects = 1 in {
1743     def ELPMBRdZ : Pseudo<(outs GPR8:$dst), (ins ZREG:$z, LD8:$p),
1744                           "elpmb\t$dst, $z, $p", []>,
1745                    Requires<[HasELPMX]>;
1747     let Constraints = "@earlyclobber $dst" in
1748     def ELPMWRdZ : Pseudo<(outs DREGS:$dst), (ins ZREG:$z, LD8:$p),
1749                           "elpmw\t$dst, $z, $p", []>,
1750                    Requires<[HasELPMX]>;
1752     def ELPMBRdZPi : Pseudo<(outs GPR8:$dst), (ins ZREG:$z, LD8:$p),
1753                             "elpmb\t$dst, $z+, $p", []>,
1754                      Requires<[HasELPMX]>;
1756     def ELPMWRdZPi : Pseudo<(outs DREGS:$dst), (ins ZREG:$z, LD8:$p),
1757                             "elpmw\t$dst, $z+, $p", []>,
1758                      Requires<[HasELPMX]>;
1759   }
1762 // Store program memory operations.
1763 let Uses = [R1, R0] in {
1764   let Uses = [R31R30, R1, R0] in def SPM
1765       : F16<0b1001010111101000, (outs), (ins), "spm", []>,
1766       Requires<[HasSPM]>;
1768   let Defs = [R31R30] in def SPMZPi : F16<0b1001010111111000, (outs),
1769                                           (ins ZREG
1770                                            : $z),
1771                                           "spm $z+", []>,
1772       Requires<[HasSPMX]>;
1775 // Read data from IO location operations.
1776 let canFoldAsLoad = 1, isReMaterializable = 1 in {
1777   def INRdA : FIORdA<(outs GPR8
1778                       : $rd),
1779                      (ins imm_port6
1780                       : $A),
1781                      "in\t$rd, $A", [(set i8
1782                                          : $rd, (load ioaddr8
1783                                                   : $A))]>;
1785   def INWRdA : Pseudo<(outs DREGS
1786                        : $dst),
1787                       (ins imm_port6
1788                        : $src),
1789                       "inw\t$dst, $src", [(set i16
1790                                            : $dst, (load ioaddr16
1791                                                     : $src))]>;
1794 // Write data to IO location operations.
1795 def OUTARr : FIOARr<(outs),
1796                     (ins imm_port6
1797                      : $A, GPR8
1798                      : $rr),
1799                     "out\t$A, $rr", [(store i8
1800                                          : $rr, ioaddr8
1801                                          : $A)]>;
1803 def OUTWARr : Pseudo<(outs),
1804                      (ins imm_port6
1805                       : $dst, DREGS
1806                       : $src),
1807                      "outw\t$dst, $src", [(store i16
1808                                            : $src, ioaddr16
1809                                            : $dst)]>;
1811 // Stack push/pop operations.
1812 let Defs = [SP], Uses = [SP], hasSideEffects = 0 in {
1813   // Stack push operations.
1814   let mayStore = 1 in {
1815     def PUSHRr : FRd<0b1001, 0b0011111, (outs),
1816                      (ins GPR8
1817                       : $rd),
1818                      "push\t$rd", []>,
1819                  Requires<[HasSRAM]>;
1821     def PUSHWRr : Pseudo<(outs),
1822                          (ins DREGS
1823                           : $reg),
1824                          "pushw\t$reg", []>,
1825                   Requires<[HasSRAM]>;
1826   }
1828   // Stack pop operations.
1829   let mayLoad = 1 in {
1830     def POPRd : FRd<0b1001, 0b0001111,
1831                     (outs GPR8
1832                      : $rd),
1833                     (ins), "pop\t$rd", []>,
1834                 Requires<[HasSRAM]>;
1836     def POPWRd : Pseudo<(outs DREGS
1837                          : $reg),
1838                         (ins), "popw\t$reg", []>,
1839                  Requires<[HasSRAM]>;
1840   }
1843 // Read-Write-Modify (RMW) instructions.
1844 def XCHZRd : FZRd<0b100,
1845                   (outs GPR8
1846                    : $rd),
1847                   (ins ZREG
1848                    : $z),
1849                   "xch\t$z, $rd", []>,
1850              Requires<[SupportsRMW]>;
1852 def LASZRd : FZRd<0b101,
1853                   (outs GPR8
1854                    : $rd),
1855                   (ins ZREG
1856                    : $z),
1857                   "las\t$z, $rd", []>,
1858              Requires<[SupportsRMW]>;
1860 def LACZRd : FZRd<0b110,
1861                   (outs GPR8
1862                    : $rd),
1863                   (ins ZREG
1864                    : $z),
1865                   "lac\t$z, $rd", []>,
1866              Requires<[SupportsRMW]>;
1868 def LATZRd : FZRd<0b111,
1869                   (outs GPR8
1870                    : $rd),
1871                   (ins ZREG
1872                    : $z),
1873                   "lat\t$z, $rd", []>,
1874              Requires<[SupportsRMW]>;
1876 //===----------------------------------------------------------------------===//
1877 // Bit and bit-test instructions
1878 //===----------------------------------------------------------------------===//
1880 // Bit shift/rotate operations.
1881 let Constraints = "$src = $rd", Defs = [SREG] in {
1882   // 8-bit LSL is an alias of ADD Rd, Rd
1884   def LSLWRd : Pseudo<(outs DREGS
1885                        : $rd),
1886                       (ins DREGS
1887                        : $src),
1888                       "lslw\t$rd",
1889                       [(set i16
1890                         : $rd, (AVRlsl i16
1891                                 : $src)),
1892                        (implicit SREG)]>;
1894   def LSLWHiRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), "lslwhi\t$rd",
1895                         [(set i16:$rd, (AVRlslhi i16:$src)), (implicit SREG)]>;
1897   def LSLWNRd : Pseudo<(outs DLDREGS
1898                         : $rd),
1899                        (ins DREGS
1900                         : $src, imm16
1901                         : $bits),
1902                        "lslwn\t$rd, $bits", [
1903                          (set i16
1904                           : $rd, (AVRlslwn i16
1905                                   : $src, imm
1906                                   : $bits)),
1907                          (implicit SREG)
1908                        ]>;
1910   def LSLBNRd : Pseudo<(outs LD8
1911                         : $rd),
1912                        (ins GPR8
1913                         : $src, imm_ldi8
1914                         : $bits),
1915                        "lslbn\t$rd, $bits", [
1916                          (set i8
1917                           : $rd, (AVRlslbn i8
1918                                   : $src, imm
1919                                   : $bits)),
1920                          (implicit SREG)
1921                        ]>;
1923   def LSRRd
1924       : FRd<0b1001, 0b0100110,
1925             (outs GPR8
1926              : $rd),
1927             (ins GPR8
1928              : $src),
1929             "lsr\t$rd", [(set i8
1930                           : $rd, (AVRlsr i8
1931                                   : $src)),
1932                          (implicit SREG)]>;
1934   def LSRWRd : Pseudo<(outs DREGS
1935                        : $rd),
1936                       (ins DREGS
1937                        : $src),
1938                       "lsrw\t$rd",
1939                       [(set i16
1940                         : $rd, (AVRlsr i16
1941                                 : $src)),
1942                        (implicit SREG)]>;
1944   def LSRWLoRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), "lsrwlo\t$rd",
1945                         [(set i16:$rd, (AVRlsrlo i16:$src)), (implicit SREG)]>;
1947   def LSRWNRd : Pseudo<(outs DLDREGS
1948                         : $rd),
1949                        (ins DREGS
1950                         : $src, imm16
1951                         : $bits),
1952                        "lsrwn\t$rd, $bits", [
1953                          (set i16
1954                           : $rd, (AVRlsrwn i16
1955                                   : $src, imm
1956                                   : $bits)),
1957                          (implicit SREG)
1958                        ]>;
1960   def LSRBNRd : Pseudo<(outs LD8
1961                         : $rd),
1962                        (ins GPR8
1963                         : $src, imm_ldi8
1964                         : $bits),
1965                        "lsrbn\t$rd, $bits", [
1966                          (set i8
1967                           : $rd, (AVRlsrbn i8
1968                                   : $src, imm
1969                                   : $bits)),
1970                          (implicit SREG)
1971                        ]>;
1973   def ASRRd
1974       : FRd<0b1001, 0b0100101,
1975             (outs GPR8
1976              : $rd),
1977             (ins GPR8
1978              : $src),
1979             "asr\t$rd", [(set i8
1980                           : $rd, (AVRasr i8
1981                                   : $src)),
1982                          (implicit SREG)]>;
1984   def ASRWNRd : Pseudo<(outs DREGS
1985                         : $rd),
1986                        (ins DREGS
1987                         : $src, imm16
1988                         : $bits),
1989                        "asrwn\t$rd, $bits", [
1990                          (set i16
1991                           : $rd, (AVRasrwn i16
1992                                   : $src, imm
1993                                   : $bits)),
1994                          (implicit SREG)
1995                        ]>;
1997   def ASRBNRd : Pseudo<(outs LD8
1998                         : $rd),
1999                        (ins GPR8
2000                         : $src, imm_ldi8
2001                         : $bits),
2002                        "asrbn\t$rd, $bits", [
2003                          (set i8
2004                           : $rd, (AVRasrbn i8
2005                                   : $src, imm
2006                                   : $bits)),
2007                          (implicit SREG)
2008                        ]>;
2010   def ASRWRd : Pseudo<(outs DREGS
2011                        : $rd),
2012                       (ins DREGS
2013                        : $src),
2014                       "asrw\t$rd",
2015                       [(set i16
2016                         : $rd, (AVRasr i16
2017                                 : $src)),
2018                        (implicit SREG)]>;
2020   def ASRWLoRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), "asrwlo\t$rd",
2021                         [(set i16:$rd, (AVRasrlo i16:$src)), (implicit SREG)]>;
2023   let hasSideEffects=0 in
2024   def ROLBRd : Pseudo<(outs GPR8
2025                        : $rd),
2026                       (ins GPR8:$src, GPR8:$zero),
2027                       "rolb\t$rd",
2028                       []>;
2030   def RORBRd : Pseudo<(outs GPR8
2031                        : $rd),
2032                       (ins GPR8
2033                        : $src),
2034                       "rorb\t$rd",
2035                       [(set i8
2036                         : $rd, (AVRror i8
2037                                 : $src)),
2038                        (implicit SREG)]>;
2040   // Bit rotate operations.
2041   let Uses = [SREG] in {
2043     def ROLWRd
2044         : Pseudo<(outs DREGS
2045                   : $rd),
2046                  (ins DREGS
2047                   : $src),
2048                  "rolw\t$rd",
2049                  [(set i16
2050                    : $rd, (AVRrol i16
2051                            : $src)),
2052                   (implicit SREG)]>;
2054     def RORRd : FRd<0b1001, 0b0100111,
2055                     (outs GPR8
2056                      : $rd),
2057                     (ins GPR8
2058                      : $src),
2059                     "ror\t$rd", []>;
2061     def RORWRd
2062         : Pseudo<(outs DREGS
2063                   : $rd),
2064                  (ins DREGS
2065                   : $src),
2066                  "rorw\t$rd",
2067                  [(set i16
2068                    : $rd, (AVRror i16
2069                            : $src)),
2070                   (implicit SREG)]>;
2071   }
2074 // SWAP Rd
2075 // Swaps the high and low nibbles in a register.
2076 let Constraints =
2077     "$src = $rd" in def SWAPRd : FRd<0b1001, 0b0100010,
2078                                      (outs GPR8
2079                                       : $rd),
2080                                      (ins GPR8
2081                                       : $src),
2082                                      "swap\t$rd", [(set i8
2083                                                     : $rd, (AVRSwap i8
2084                                                             : $src))]>;
2086 // IO register bit set/clear operations.
2087 //: TODO: add patterns when popcount(imm)==2 to be expanded with 2 sbi/cbi
2088 // instead of in+ori+out which requires one more instr.
2089 def SBIAb : FIOBIT<0b10, (outs),
2090                    (ins imm_port5
2091                     : $addr, i8imm
2092                     : $b),
2093                    "sbi\t$addr, $b", [(store(or(i8(load lowioaddr8
2094                                                      : $addr)),
2095                                                iobitpos8
2096                                                : $b),
2097                                          lowioaddr8
2098                                          : $addr)]>;
2100 def CBIAb : FIOBIT<0b00, (outs),
2101                    (ins imm_port5
2102                     : $addr, i8imm
2103                     : $b),
2104                    "cbi\t$addr, $b", [(store(and(i8(load lowioaddr8
2105                                                       : $addr)),
2106                                                iobitposn8
2107                                                : $b),
2108                                          lowioaddr8
2109                                          : $addr)]>;
2111 // Status register bit load/store operations.
2112 let Defs = [SREG] in def BST : FRdB<0b01, (outs),
2113                                     (ins GPR8
2114                                      : $rd, i8imm
2115                                      : $b),
2116                                     "bst\t$rd, $b", []>;
2118 let Constraints = "$src = $rd",
2119     Uses = [SREG] in def BLD : FRdB<0b00,
2120                                     (outs GPR8
2121                                      : $rd),
2122                                     (ins GPR8
2123                                      : $src, i8imm
2124                                      : $b),
2125                                     "bld\t$rd, $b", []>;
2127 def CBR : InstAlias<"cbr\t$rd, $k", (ANDIRdK LD8 : $rd, imm_com8 : $k), 0>;
2129 // CLR Rd
2130 // Alias for EOR Rd, Rd
2131 // -------------
2132 // Clears all bits in a register.
2133 def CLR : InstAlias<"clr\t$rd", (EORRdRr GPR8 : $rd, GPR8 : $rd)>;
2135 // LSL Rd
2136 // Alias for ADD Rd, Rd
2137 // --------------
2138 // Logical shift left one bit.
2139 def LSL : InstAlias<"lsl\t$rd", (ADDRdRr GPR8 : $rd, GPR8 : $rd)>;
2141 def ROL : InstAlias<"rol\t$rd", (ADCRdRr GPR8 : $rd, GPR8 : $rd)>;
2143 // SER Rd
2144 // Alias for LDI Rd, 0xff
2145 // ---------
2146 // Sets all bits in a register.
2147 def : InstAlias<"ser\t$rd", (LDIRdK LD8 : $rd, 0xff), 0>;
2149 let hasSideEffects=1 in {
2150   let Defs = [SREG] in def BSETs : FS<0,
2151                                       (outs),
2152                                       (ins i8imm:$s),
2153                                       "bset\t$s", []>;
2155   let Defs = [SREG] in def BCLRs : FS<1,
2156                                       (outs),
2157                                       (ins i8imm:$s),
2158                                       "bclr\t$s", []>;
2161 // Set/clear aliases for the carry (C) status flag (bit 0).
2162 def : InstAlias<"sec", (BSETs 0)>;
2163 def : InstAlias<"clc", (BCLRs 0)>;
2165 // Set/clear aliases for the zero (Z) status flag (bit 1).
2166 def : InstAlias<"sez", (BSETs 1)>;
2167 def : InstAlias<"clz", (BCLRs 1)>;
2169 // Set/clear aliases for the negative (N) status flag (bit 2).
2170 def : InstAlias<"sen", (BSETs 2)>;
2171 def : InstAlias<"cln", (BCLRs 2)>;
2173 // Set/clear aliases for the overflow (V) status flag (bit 3).
2174 def : InstAlias<"sev", (BSETs 3)>;
2175 def : InstAlias<"clv", (BCLRs 3)>;
2177 // Set/clear aliases for the signed (S) status flag (bit 4).
2178 def : InstAlias<"ses", (BSETs 4)>;
2179 def : InstAlias<"cls", (BCLRs 4)>;
2181 // Set/clear aliases for the half-carry (H) status flag (bit 5).
2182 def : InstAlias<"seh", (BSETs 5)>;
2183 def : InstAlias<"clh", (BCLRs 5)>;
2185 // Set/clear aliases for the T status flag (bit 6).
2186 def : InstAlias<"set", (BSETs 6)>;
2187 def : InstAlias<"clt", (BCLRs 6)>;
2189 // Set/clear aliases for the interrupt (I) status flag (bit 7).
2190 def : InstAlias<"sei", (BSETs 7)>;
2191 def : InstAlias<"cli", (BCLRs 7)>;
2193 //===----------------------------------------------------------------------===//
2194 // Special/Control instructions
2195 //===----------------------------------------------------------------------===//
2197 // BREAK
2198 // Breakpoint instruction
2199 // ---------
2200 // <|1001|0101|1001|1000>
2201 def BREAK : F16<0b1001010110011000, (outs), (ins), "break", []>,
2202             Requires<[HasBREAK]>;
2204 // NOP
2205 // No-operation instruction
2206 // ---------
2207 // <|0000|0000|0000|0000>
2208 def NOP : F16<0b0000000000000000, (outs), (ins), "nop", []>;
2210 // SLEEP
2211 // Sleep instruction
2212 // ---------
2213 // <|1001|0101|1000|1000>
2214 def SLEEP : F16<0b1001010110001000, (outs), (ins), "sleep", []>;
2216 // WDR
2217 // Watchdog reset
2218 // ---------
2219 // <|1001|0101|1010|1000>
2220 def WDR : F16<0b1001010110101000, (outs), (ins), "wdr", []>;
2222 //===----------------------------------------------------------------------===//
2223 // Pseudo instructions for later expansion
2224 //===----------------------------------------------------------------------===//
2226 //: TODO: Optimize this for wider types AND optimize the following code
2227 //       compile int foo(char a, char b, char c, char d) {return d+b;}
2228 //       looks like a missed sext_inreg opportunity.
2229 def SEXT
2230     : ExtensionPseudo<(outs DREGS
2231                        : $dst),
2232                       (ins GPR8
2233                        : $src),
2234                       "sext\t$dst, $src",
2235                       [(set i16
2236                         : $dst, (sext i8
2237                                  : $src)),
2238                        (implicit SREG)]>;
2240 def ZEXT
2241     : ExtensionPseudo<(outs DREGS
2242                        : $dst),
2243                       (ins GPR8
2244                        : $src),
2245                       "zext\t$dst, $src",
2246                       [(set i16
2247                         : $dst, (zext i8
2248                                  : $src)),
2249                        (implicit SREG)]>;
2251 // This pseudo gets expanded into a movw+adiw thus it clobbers SREG.
2252 let Defs = [SREG],
2253     hasSideEffects = 0 in def FRMIDX : Pseudo<(outs DLDREGS
2254                                                : $dst),
2255                                               (ins DLDREGS
2256                                                : $src, i16imm
2257                                                : $src2),
2258                                               "frmidx\t$dst, $src, $src2", []>;
2260 // This pseudo is either converted to a regular store or a push which clobbers
2261 // SP.
2262 def STDSPQRr : StorePseudo<(outs),
2263                            (ins memspi
2264                             : $dst, GPR8
2265                             : $src),
2266                            "stdstk\t$dst, $src", [(store i8
2267                                                    : $src, addr
2268                                                    : $dst)]>;
2270 // This pseudo is either converted to a regular store or a push which clobbers
2271 // SP.
2272 def STDWSPQRr : StorePseudo<(outs),
2273                             (ins memspi
2274                              : $dst, DREGS
2275                              : $src),
2276                             "stdwstk\t$dst, $src", [(store i16
2277                                                      : $src, addr
2278                                                      : $dst)]>;
2280 // SP read/write pseudos.
2281 let hasSideEffects = 0 in {
2282   let Uses = [SP] in def SPREAD : Pseudo<(outs DREGS
2283                                           : $dst),
2284                                          (ins GPRSP
2285                                           : $src),
2286                                          "spread\t$dst, $src", []>;
2288   let Defs = [SP] in def SPWRITE : Pseudo<(outs GPRSP
2289                                            : $dst),
2290                                           (ins DREGS
2291                                            : $src),
2292                                           "spwrite\t$dst, $src", []>;
2295 def Select8 : SelectPseudo<(outs GPR8
2296                             : $dst),
2297                            (ins GPR8
2298                             : $src, GPR8
2299                             : $src2, i8imm
2300                             : $cc),
2301                            "# Select8 PSEUDO", [(set i8
2302                                                  : $dst, (AVRselectcc i8
2303                                                           : $src, i8
2304                                                           : $src2, imm
2305                                                           : $cc))]>;
2307 def Select16 : SelectPseudo<(outs DREGS
2308                              : $dst),
2309                             (ins DREGS
2310                              : $src, DREGS
2311                              : $src2, i8imm
2312                              : $cc),
2313                             "# Select16 PSEUDO", [(set i16
2314                                                    : $dst, (AVRselectcc i16
2315                                                             : $src, i16
2316                                                             : $src2, imm
2317                                                             : $cc))]>;
2319 def Lsl8 : ShiftPseudo<(outs GPR8
2320                         : $dst),
2321                        (ins GPR8
2322                         : $src, GPR8
2323                         : $cnt),
2324                        "# Lsl8 PSEUDO", [(set i8
2325                                           : $dst, (AVRlslLoop i8
2326                                                    : $src, i8
2327                                                    : $cnt))]>;
2329 def Lsl16 : ShiftPseudo<(outs DREGS
2330                          : $dst),
2331                         (ins DREGS
2332                          : $src, GPR8
2333                          : $cnt),
2334                         "# Lsl16 PSEUDO", [(set i16
2335                                             : $dst, (AVRlslLoop i16
2336                                                      : $src, i8
2337                                                      : $cnt))]>;
2339 def Lsr8 : ShiftPseudo<(outs GPR8
2340                         : $dst),
2341                        (ins GPR8
2342                         : $src, GPR8
2343                         : $cnt),
2344                        "# Lsr8 PSEUDO", [(set i8
2345                                           : $dst, (AVRlsrLoop i8
2346                                                    : $src, i8
2347                                                    : $cnt))]>;
2349 def Lsr16 : ShiftPseudo<(outs DREGS
2350                          : $dst),
2351                         (ins DREGS
2352                          : $src, GPR8
2353                          : $cnt),
2354                         "# Lsr16 PSEUDO", [(set i16
2355                                             : $dst, (AVRlsrLoop i16
2356                                                      : $src, i8
2357                                                      : $cnt))]>;
2359 def Rol8 : ShiftPseudo<(outs GPR8
2360                         : $dst),
2361                        (ins GPR8
2362                         : $src, GPR8
2363                         : $cnt),
2364                        "# Rol8 PSEUDO", [(set i8
2365                                           : $dst, (AVRrolLoop i8
2366                                                    : $src, i8
2367                                                    : $cnt))]>;
2369 def Rol16 : ShiftPseudo<(outs DREGS
2370                          : $dst),
2371                         (ins DREGS
2372                          : $src, GPR8
2373                          : $cnt),
2374                         "# Rol16 PSEUDO", [(set i16
2375                                             : $dst, (AVRrolLoop i16
2376                                                      : $src, i8
2377                                                      : $cnt))]>;
2379 def Ror8 : ShiftPseudo<(outs GPR8
2380                         : $dst),
2381                        (ins GPR8
2382                         : $src, GPR8
2383                         : $cnt),
2384                        "# Ror8 PSEUDO", [(set i8
2385                                           : $dst, (AVRrorLoop i8
2386                                                    : $src, i8
2387                                                    : $cnt))]>;
2389 def Ror16 : ShiftPseudo<(outs DREGS
2390                          : $dst),
2391                         (ins DREGS
2392                          : $src, GPR8
2393                          : $cnt),
2394                         "# Ror16 PSEUDO", [(set i16
2395                                             : $dst, (AVRrorLoop i16
2396                                                      : $src, i8
2397                                                      : $cnt))]>;
2399 def Asr8 : ShiftPseudo<(outs GPR8
2400                         : $dst),
2401                        (ins GPR8
2402                         : $src, GPR8
2403                         : $cnt),
2404                        "# Asr8 PSEUDO", [(set i8
2405                                           : $dst, (AVRasrLoop i8
2406                                                    : $src, i8
2407                                                    : $cnt))]>;
2409 def Asr16 : ShiftPseudo<(outs DREGS
2410                          : $dst),
2411                         (ins DREGS
2412                          : $src, GPR8
2413                          : $cnt),
2414                         "# Asr16 PSEUDO", [(set i16
2415                                             : $dst, (AVRasrLoop i16
2416                                                      : $src, i8
2417                                                      : $cnt))]>;
2419 // lowered to a copy from the zero register.
2420 let usesCustomInserter=1 in
2421 def CopyZero : Pseudo<(outs GPR8:$rd), (ins), "clrz\t$rd", [(set i8:$rd, 0)]>;
2423 //===----------------------------------------------------------------------===//
2424 // Non-Instruction Patterns
2425 //===----------------------------------------------------------------------===//
2427 //: TODO: look in x86InstrCompiler.td for odd encoding trick related to
2428 // add x, 128 -> sub x, -128. Clang is emitting an eor for this (ldi+eor)
2430 // the add instruction always writes the carry flag
2431 def : Pat<(addc i8 : $src, i8 : $src2), (ADDRdRr i8 : $src, i8 : $src2)>;
2432 def : Pat<(addc DREGS
2433            : $src, DREGS
2434            : $src2),
2435           (ADDWRdRr DREGS
2436            : $src, DREGS
2437            : $src2)>;
2439 // all sub instruction variants always writes the carry flag
2440 def : Pat<(subc i8 : $src, i8 : $src2), (SUBRdRr i8 : $src, i8 : $src2)>;
2441 def : Pat<(subc i16 : $src, i16 : $src2), (SUBWRdRr i16 : $src, i16 : $src2)>;
2442 def : Pat<(subc i8 : $src, imm : $src2), (SUBIRdK i8 : $src, imm : $src2)>;
2443 def : Pat<(subc i16 : $src, imm : $src2), (SUBIWRdK i16 : $src, imm : $src2)>;
2445 // These patterns convert add (x, -imm) to sub (x, imm) since we dont have
2446 // any add with imm instructions. Also take care of the adiw/sbiw instructions.
2447 def : Pat<(add i16
2448            : $src1, imm0_63_neg
2449            : $src2),
2450           (SBIWRdK i16
2451            : $src1, (imm0_63_neg
2452                      : $src2))>,
2453           Requires<[HasADDSUBIW]>;
2454 def : Pat<(add i16
2455            : $src1, imm
2456            : $src2),
2457           (SUBIWRdK i16
2458            : $src1, (imm16_neg_XFORM imm
2459                      : $src2))>;
2460 def : Pat<(addc i16
2461            : $src1, imm
2462            : $src2),
2463           (SUBIWRdK i16
2464            : $src1, (imm16_neg_XFORM imm
2465                      : $src2))>;
2467 def : Pat<(add i8
2468            : $src1, imm
2469            : $src2),
2470           (SUBIRdK i8
2471            : $src1, (imm8_neg_XFORM imm
2472                      : $src2))>;
2473 def : Pat<(addc i8
2474            : $src1, imm
2475            : $src2),
2476           (SUBIRdK i8
2477            : $src1, (imm8_neg_XFORM imm
2478                      : $src2))>;
2479 def : Pat<(adde i8
2480            : $src1, imm
2481            : $src2),
2482           (SBCIRdK i8
2483            : $src1, (imm8_neg_XFORM imm
2484                      : $src2))>;
2486 // Emit NEGWRd with an extra zero register operand.
2487 def : Pat<(ineg i16:$src),
2488           (NEGWRd i16:$src, (CopyZero))>;
2490 // Calls.
2491 let Predicates = [HasJMPCALL] in {
2492   def : Pat<(AVRcall(i16 tglobaladdr:$dst)), (CALLk tglobaladdr:$dst)>;
2493   def : Pat<(AVRcall(i16 texternalsym:$dst)), (CALLk texternalsym:$dst)>;
2495 def : Pat<(AVRcall(i16 tglobaladdr:$dst)), (RCALLk tglobaladdr:$dst)>;
2496 def : Pat<(AVRcall(i16 texternalsym:$dst)), (RCALLk texternalsym:$dst)>;
2498 // `anyext`
2499 def : Pat<(i16(anyext i8
2500                : $src)),
2501           (INSERT_SUBREG(i16(IMPLICIT_DEF)), i8
2502            : $src, sub_lo)>;
2504 // `trunc`
2505 def : Pat<(i8(trunc i16 : $src)), (EXTRACT_SUBREG i16 : $src, sub_lo)>;
2507 // sext_inreg
2508 def : Pat<(sext_inreg i16
2509            : $src, i8),
2510           (SEXT(i8(EXTRACT_SUBREG i16
2511                    : $src, sub_lo)))>;
2513 // GlobalAddress
2514 def : Pat<(i16(AVRWrapper tglobaladdr : $dst)), (LDIWRdK tglobaladdr : $dst)>;
2515 def : Pat<(add i16
2516            : $src, (AVRWrapper tglobaladdr
2517                     : $src2)),
2518           (SUBIWRdK i16
2519            : $src, tglobaladdr
2520            : $src2)>;
2521 def : Pat<(i8(load(AVRWrapper tglobaladdr:$dst))),
2522           (LDSRdK tglobaladdr:$dst)>,
2523           Requires<[HasSRAM, HasNonTinyEncoding]>;
2524 def : Pat<(i16(load(AVRWrapper tglobaladdr:$dst))),
2525           (LDSWRdK tglobaladdr:$dst)>,
2526           Requires<[HasSRAM, HasNonTinyEncoding]>;
2527 def : Pat<(store i8:$src, (i16(AVRWrapper tglobaladdr:$dst))),
2528           (STSKRr tglobaladdr:$dst, i8:$src)>,
2529           Requires<[HasSRAM, HasNonTinyEncoding]>;
2530 def : Pat<(store i16:$src, (i16(AVRWrapper tglobaladdr:$dst))),
2531           (STSWKRr tglobaladdr:$dst, i16:$src)>,
2532           Requires<[HasSRAM, HasNonTinyEncoding]>;
2534 // BlockAddress
2535 def : Pat<(i16(AVRWrapper tblockaddress
2536                : $dst)),
2537           (LDIWRdK tblockaddress
2538            : $dst)>;
2540 def : Pat<(i8(trunc(AVRlsrwn DLDREGS
2541                     : $src, (i16 8)))),
2542           (EXTRACT_SUBREG DREGS
2543            : $src, sub_hi)>;
2545 // :FIXME: DAGCombiner produces an shl node after legalization from these seq:
2546 // BR_JT -> (mul x, 2) -> (shl x, 1)
2547 def : Pat<(shl i16 : $src1, (i8 1)), (LSLWRd i16 : $src1)>;
2549 // Lowering of 'tst' node to 'TST' instruction.
2550 // TST is an alias of AND Rd, Rd.
2551 def : Pat<(AVRtst i8 : $rd), (ANDRdRr GPR8 : $rd, GPR8 : $rd)>;
2553 // Lowering of 'lsl' node to 'LSL' instruction.
2554 // LSL is an alias of 'ADD Rd, Rd'
2555 def : Pat<(AVRlsl i8 : $rd), (ADDRdRr GPR8 : $rd, GPR8 : $rd)>;