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