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