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