1 //===-- AVRInstrInfo.td - AVR Instruction defs -------------*- tablegen -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file describes the AVR instructions in TableGen format.
11 //===----------------------------------------------------------------------===//
13 include "AVRInstrFormats.td"
15 //===----------------------------------------------------------------------===//
17 //===----------------------------------------------------------------------===//
19 def SDT_AVRCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i16>, SDTCisVT<1, i16>]>;
20 def SDT_AVRCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i16>, SDTCisVT<1, i16>]>;
21 def SDT_AVRCall : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
22 def SDT_AVRWrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>;
24 : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisVT<1, i8>]>;
25 def SDT_AVRCmp : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
26 def SDT_AVRTst : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
29 [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>;
31 //===----------------------------------------------------------------------===//
32 // AVR Specific Node Definitions
33 //===----------------------------------------------------------------------===//
35 def AVRretflag : SDNode<"AVRISD::RET_FLAG", SDTNone,
36 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
37 def AVRretiflag : SDNode<"AVRISD::RETI_FLAG", SDTNone,
38 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
40 def AVRcallseq_start : SDNode<"ISD::CALLSEQ_START", SDT_AVRCallSeqStart,
41 [SDNPHasChain, SDNPOutGlue]>;
42 def AVRcallseq_end : SDNode<"ISD::CALLSEQ_END", SDT_AVRCallSeqEnd,
43 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
45 def AVRcall : SDNode<"AVRISD::CALL", SDT_AVRCall,
46 [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, SDNPVariadic]>;
48 def AVRWrapper : SDNode<"AVRISD::WRAPPER", SDT_AVRWrapper>;
51 : SDNode<"AVRISD::BRCOND", SDT_AVRBrcond, [SDNPHasChain, SDNPInGlue]>;
52 def AVRcmp : SDNode<"AVRISD::CMP", SDT_AVRCmp, [SDNPOutGlue]>;
53 def AVRcmpc : SDNode<"AVRISD::CMPC", SDT_AVRCmp, [SDNPInGlue, SDNPOutGlue]>;
54 def AVRtst : SDNode<"AVRISD::TST", SDT_AVRTst, [SDNPOutGlue]>;
55 def AVRselectcc : SDNode<"AVRISD::SELECT_CC", SDT_AVRSelectCC, [SDNPInGlue]>;
58 def AVRlsl : SDNode<"AVRISD::LSL", SDTIntUnaryOp>;
59 def AVRlsr : SDNode<"AVRISD::LSR", SDTIntUnaryOp>;
60 def AVRrol : SDNode<"AVRISD::ROL", SDTIntUnaryOp>;
61 def AVRror : SDNode<"AVRISD::ROR", SDTIntUnaryOp>;
62 def AVRasr : SDNode<"AVRISD::ASR", SDTIntUnaryOp>;
63 def AVRlslbn : SDNode<"AVRISD::LSLBN", SDTIntBinOp>;
64 def AVRlsrbn : SDNode<"AVRISD::LSRBN", SDTIntBinOp>;
65 def AVRasrbn : SDNode<"AVRISD::ASRBN", SDTIntBinOp>;
66 def AVRlslwn : SDNode<"AVRISD::LSLWN", SDTIntBinOp>;
67 def AVRlsrwn : SDNode<"AVRISD::LSRWN", SDTIntBinOp>;
68 def AVRasrwn : SDNode<"AVRISD::ASRWN", SDTIntBinOp>;
70 // Pseudo shift nodes for non-constant shift amounts.
71 def AVRlslLoop : SDNode<"AVRISD::LSLLOOP", SDTIntShiftOp>;
72 def AVRlsrLoop : SDNode<"AVRISD::LSRLOOP", SDTIntShiftOp>;
73 def AVRrolLoop : SDNode<"AVRISD::ROLLOOP", SDTIntShiftOp>;
74 def AVRrorLoop : SDNode<"AVRISD::RORLOOP", SDTIntShiftOp>;
75 def AVRasrLoop : SDNode<"AVRISD::ASRLOOP", SDTIntShiftOp>;
78 def AVRSwap : SDNode<"AVRISD::SWAP", SDTIntUnaryOp>;
80 //===----------------------------------------------------------------------===//
81 // AVR Operands, Complex Patterns and Transformations Definitions.
82 //===----------------------------------------------------------------------===//
84 def imm8_neg_XFORM : SDNodeXForm<imm, [{
85 return CurDAG->getTargetConstant(
86 -N->getAPIntValue(), SDLoc(N), MVT::i8);
91 return CurDAG->getTargetConstant(-N->getAPIntValue(),
95 def imm0_63_neg : PatLeaf<(imm), [{
96 int64_t val = -N->getSExtValue();
97 return val >= 0 && val < 64;
101 def uimm6 : PatLeaf<(imm), [{ return isUInt<6>(N->getZExtValue()); }]>;
103 // imm_com8_XFORM - Return the complement of a imm_com8 value
105 : SDNodeXForm<imm, [{
106 return CurDAG->getTargetConstant(
107 ~((uint8_t) N->getZExtValue()), SDLoc(N), MVT::i8);
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.
115 def imm_com8_asmoperand : AsmOperandClass { let Name = "ImmCom8"; }
116 def imm_com8 : Operand<i8> { let ParserMatchClass = imm_com8_asmoperand; }
119 : SDNodeXForm<imm, [{
120 uint8_t offset = Subtarget->getIORegisterOffset();
121 return CurDAG->getTargetConstant(
122 uint8_t(N->getZExtValue()) - offset, SDLoc(N), MVT::i8);
126 : SDNodeXForm<imm, [{
127 return CurDAG->getTargetConstant(
128 Log2_32(uint8_t(N->getZExtValue())), SDLoc(N), MVT::i8);
131 def iobitposn8_XFORM : SDNodeXForm<imm, [{
132 return CurDAG->getTargetConstant(
133 Log2_32(uint8_t(~N->getZExtValue())),
137 def ioaddr8 : PatLeaf<(imm), [{
138 uint8_t offset = Subtarget->getIORegisterOffset();
139 uint64_t val = N->getZExtValue() - offset;
144 def lowioaddr8 : PatLeaf<(imm), [{
145 uint8_t offset = Subtarget->getIORegisterOffset();
146 uint64_t val = N->getZExtValue() - offset;
151 def ioaddr16 : PatLeaf<(imm), [{
152 uint8_t offset = Subtarget->getIORegisterOffset();
153 uint64_t val = N->getZExtValue() - offset;
159 : PatLeaf<(imm), [{ return isPowerOf2_32(uint8_t(N->getZExtValue())); }],
163 : PatLeaf<(imm), [{ return isPowerOf2_32(uint8_t(~N->getZExtValue())); }],
166 def MemriAsmOperand : AsmOperandClass {
168 let ParserMethod = "parseMemriOperand";
171 /// Address operand for `reg+imm` used by STD and LDD.
172 def memri : Operand<iPTR> {
173 let MIOperandInfo = (ops PTRDISPREGS, i16imm);
175 let PrintMethod = "printMemri";
176 let EncoderMethod = "encodeMemri";
178 let ParserMatchClass = MemriAsmOperand;
181 // Address operand for `SP+imm` used by STD{W}SPQRr
182 def memspi : Operand<iPTR> { let MIOperandInfo = (ops GPRSP, i16imm); }
184 def relbrtarget_7 : Operand<OtherVT> {
185 let PrintMethod = "printPCRelImm";
186 let EncoderMethod = "encodeRelCondBrTarget<AVR::fixup_7_pcrel>";
189 def brtarget_13 : Operand<OtherVT> {
190 let PrintMethod = "printPCRelImm";
191 let EncoderMethod = "encodeRelCondBrTarget<AVR::fixup_13_pcrel>";
194 // The target of a 22 or 16-bit call/jmp instruction.
195 def call_target : Operand<iPTR> {
196 let EncoderMethod = "encodeCallTarget";
197 let DecoderMethod = "decodeCallTarget";
200 // A 16-bit address (which can lead to an R_AVR_16 relocation).
201 def imm16 : Operand<i16> { let EncoderMethod = "encodeImm<AVR::fixup_16, 2>"; }
203 /// A 6-bit immediate used in the ADIW/SBIW instructions.
204 def imm_arith6 : Operand<i16> {
205 let EncoderMethod = "encodeImm<AVR::fixup_6_adiw, 0>";
208 /// An 8-bit immediate inside an instruction with the same format
209 /// as the `LDI` instruction (the `FRdK` format).
210 def imm_ldi8 : Operand<i8> {
211 let EncoderMethod = "encodeImm<AVR::fixup_ldi, 0>";
214 /// A 5-bit port number used in SBIC and friends (the `FIOBIT` format).
215 def imm_port5 : Operand<i8> {
216 let EncoderMethod = "encodeImm<AVR::fixup_port5, 0>";
219 /// A 6-bit port number used in the `IN` instruction and friends (the
221 def imm_port6 : Operand<i8> {
222 let EncoderMethod = "encodeImm<AVR::fixup_port6, 0>";
225 // Addressing mode pattern reg+imm6
226 def addr : ComplexPattern<iPTR, 2, "SelectAddr", [], [SDNPWantRoot]>;
228 // AsmOperand class for a pointer register.
229 // Used with the LD/ST family of instructions.
230 // See FSTLD in AVRInstrFormats.td
231 def PtrRegAsmOperand : AsmOperandClass { let Name = "Reg"; }
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
236 def LDSTPtrReg : Operand<i16> {
237 let MIOperandInfo = (ops PTRREGS);
238 let EncoderMethod = "encodeLDSTPtrReg";
240 let ParserMatchClass = PtrRegAsmOperand;
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.
246 def LDDSTDPtrReg : Operand<i16> {
247 let MIOperandInfo = (ops PTRDISPREGS);
248 let EncoderMethod = "encodeLDSTPtrReg";
250 let ParserMatchClass = PtrRegAsmOperand;
253 //===----------------------------------------------------------------------===//
254 // AVR predicates for subtarget features
255 //===----------------------------------------------------------------------===//
257 def HasSRAM : Predicate<"Subtarget->hasSRAM()">,
258 AssemblerPredicate<(all_of FeatureSRAM)>;
260 def HasJMPCALL : Predicate<"Subtarget->hasJMPCALL()">,
261 AssemblerPredicate<(all_of FeatureJMPCALL)>;
263 def HasIJMPCALL : Predicate<"Subtarget->hasIJMPCALL()">,
264 AssemblerPredicate<(all_of FeatureIJMPCALL)>;
266 def HasEIJMPCALL : Predicate<"Subtarget->hasEIJMPCALL()">,
267 AssemblerPredicate<(all_of FeatureEIJMPCALL)>;
269 def HasADDSUBIW : Predicate<"Subtarget->hasADDSUBIW()">,
270 AssemblerPredicate<(all_of FeatureADDSUBIW)>;
272 def HasSmallStack : Predicate<"Subtarget->HasSmallStack()">,
273 AssemblerPredicate<(all_of FeatureSmallStack)>;
275 def HasMOVW : Predicate<"Subtarget->hasMOVW()">,
276 AssemblerPredicate<(all_of FeatureMOVW)>;
278 def HasLPM : Predicate<"Subtarget->hasLPM()">,
279 AssemblerPredicate<(all_of FeatureLPM)>;
281 def HasLPMX : Predicate<"Subtarget->hasLPMX()">,
282 AssemblerPredicate<(all_of FeatureLPMX)>;
284 def HasELPM : Predicate<"Subtarget->hasELPM()">,
285 AssemblerPredicate<(all_of FeatureELPM)>;
287 def HasELPMX : Predicate<"Subtarget->hasELPMX()">,
288 AssemblerPredicate<(all_of FeatureELPMX)>;
290 def HasSPM : Predicate<"Subtarget->hasSPM()">,
291 AssemblerPredicate<(all_of FeatureSPM)>;
293 def HasSPMX : Predicate<"Subtarget->hasSPMX()">,
294 AssemblerPredicate<(all_of FeatureSPMX)>;
296 def HasDES : Predicate<"Subtarget->hasDES()">,
297 AssemblerPredicate<(all_of FeatureDES)>;
299 def SupportsRMW : Predicate<"Subtarget->supportsRMW()">,
300 AssemblerPredicate<(all_of FeatureRMW)>;
302 def SupportsMultiplication : Predicate<"Subtarget->supportsMultiplication()">,
303 AssemblerPredicate<(all_of FeatureMultiplication)>;
305 def HasBREAK : Predicate<"Subtarget->hasBREAK()">,
306 AssemblerPredicate<(all_of FeatureBREAK)>;
308 def HasTinyEncoding : Predicate<"Subtarget->hasTinyEncoding()">,
309 AssemblerPredicate<(all_of FeatureTinyEncoding)>;
311 // AVR specific condition code. These correspond to AVR_*_COND in
312 // AVRInstrInfo.td. They must be kept in synch.
313 def AVR_COND_EQ : PatLeaf<(i8 0)>;
314 def AVR_COND_NE : PatLeaf<(i8 1)>;
315 def AVR_COND_GE : PatLeaf<(i8 2)>;
316 def AVR_COND_LT : PatLeaf<(i8 3)>;
317 def AVR_COND_SH : PatLeaf<(i8 4)>;
318 def AVR_COND_LO : PatLeaf<(i8 5)>;
319 def AVR_COND_MI : PatLeaf<(i8 6)>;
320 def AVR_COND_PL : PatLeaf<(i8 7)>;
322 //===----------------------------------------------------------------------===//
323 //===----------------------------------------------------------------------===//
324 // AVR Instruction list
325 //===----------------------------------------------------------------------===//
326 //===----------------------------------------------------------------------===//
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.
333 let Defs = [SP, SREG], Uses = [SP] in {
334 def ADJCALLSTACKDOWN : Pseudo<(outs),
338 "#ADJCALLSTACKDOWN", [(AVRcallseq_start timm
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
347 let Defs = [R31R30], hasSideEffects = 1 in def ADJCALLSTACKUP
352 "#ADJCALLSTACKUP", [(AVRcallseq_end timm
357 //===----------------------------------------------------------------------===//
359 //===----------------------------------------------------------------------===//
360 let isCommutable = 1, Constraints = "$src = $rd", Defs = [SREG] in {
362 // Adds two 8-bit registers.
364 : FRdRr<0b0000, 0b11,
377 // ADDW Rd+1:Rd, Rr+1:Rr
378 // Pseudo instruction to add four 8-bit registers as two 16-bit values.
397 // Adds two 8-bit registers with carry.
398 let Uses = [SREG] in def ADCRdRr
399 : FRdRr<0b0001, 0b11,
412 // ADCW Rd+1:Rd, Rr+1:Rr
413 // Pseudo instruction to add four 8-bit registers as two 16-bit values with
419 let Uses = [SREG] in def ADCWRdRr : Pseudo<(outs DREGS
433 // Adds an immediate 6-bit value K to Rd, placing the result in Rd.
447 Requires<[HasADDSUBIW]>;
450 //===----------------------------------------------------------------------===//
452 //===----------------------------------------------------------------------===//
453 let Constraints = "$src = $rd", Defs = [SREG] in {
455 // Subtracts the 8-bit value of Rr from Rd and places the value in Rd.
457 : FRdRr<0b0001, 0b10,
470 // SUBW Rd+1:Rd, Rr+1:Rr
471 // Subtracts two 16-bit values and places the result into Rd.
503 // SUBIW Rd+1:Rd, K+1:K
509 : Pseudo<(outs DLDREGS
534 Requires<[HasADDSUBIW]>;
536 // Subtract with carry operations which must read the carry flag in SREG.
537 let Uses = [SREG] in {
539 : FRdRr<0b0000, 0b10,
552 // SBCW Rd+1:Rd, Rr+1:Rr
557 def SBCWRdRr : Pseudo<(outs DREGS
584 // SBCIW Rd+1:Rd, K+1:K
587 def SBCIWRdK : Pseudo<(outs DLDREGS
602 //===----------------------------------------------------------------------===//
603 // Increment and Decrement
604 //===----------------------------------------------------------------------===//
605 let Constraints = "$src = $rd", Defs = [SREG] in {
607 : FRd<0b1001, 0b0100011,
618 : FRd<0b1001, 0b0101010,
629 //===----------------------------------------------------------------------===//
631 //===----------------------------------------------------------------------===//
633 let isCommutable = 1, Defs = [R1, R0, SREG] in {
635 // Multiplies Rd by Rr and places the result into R1:R0.
636 let usesCustomInserter = 1 in {
637 def MULRdRr : FRdRr<0b1001, 0b11, (outs),
642 [/*(set R1, R0, (smullohi i8:$lhs, i8:$rhs))*/]>,
643 Requires<[SupportsMultiplication]>;
645 def MULSRdRr : FMUL2RdRr<0, (outs),
649 "muls\t$lhs, $rhs", []>,
650 Requires<[SupportsMultiplication]>;
653 def MULSURdRr : FMUL2RdRr<1, (outs),
657 "mulsu\t$lhs, $rhs", []>,
658 Requires<[SupportsMultiplication]>;
660 def FMUL : FFMULRdRr<0b01, (outs),
664 "fmul\t$lhs, $rhs", []>,
665 Requires<[SupportsMultiplication]>;
667 def FMULS : FFMULRdRr<0b10, (outs),
671 "fmuls\t$lhs, $rhs", []>,
672 Requires<[SupportsMultiplication]>;
674 def FMULSU : FFMULRdRr<0b11, (outs),
678 "fmulsu\t$lhs, $rhs", []>,
679 Requires<[SupportsMultiplication]>;
683 [R15, R14, R13, R12, R11, R10, R9, R8, R7, R6, R5, R4, R3, R2, R1,
684 R0] in def DESK : FDES<(outs),
690 //===----------------------------------------------------------------------===//
692 //===----------------------------------------------------------------------===//
693 let Constraints = "$src = $rd", Defs = [SREG] in {
694 // Register-Register logic instructions (which have the
695 // property of commutativity).
696 let isCommutable = 1 in {
698 : FRdRr<0b0010, 0b00,
711 // ANDW Rd+1:Rd, Rr+1:Rr
716 def ANDWRdRr : Pseudo<(outs DREGS
730 : FRdRr<0b0010, 0b10,
743 // ORW Rd+1:Rd, Rr+1:Rr
748 def ORWRdRr : Pseudo<(outs DREGS
762 : FRdRr<0b0010, 0b01,
775 // EORW Rd+1:Rd, Rr+1:Rr
780 def EORWRdRr : Pseudo<(outs DREGS
808 // ANDI Rd+1:Rd, K+1:K
814 : Pseudo<(outs DLDREGS
840 // ORIW Rd+1:Rd, K+1,K
846 : Pseudo<(outs DLDREGS
859 //===----------------------------------------------------------------------===//
860 // One's/Two's Complement
861 //===----------------------------------------------------------------------===//
862 let Constraints = "$src = $rd", Defs = [SREG] in {
864 : FRd<0b1001, 0b0100000,
879 def COMWRd : Pseudo<(outs DREGS
890 : FRd<0b1001, 0b0100001,
906 def NEGWRd : Pseudo<(outs DREGS
918 // Test for zero of minus.
919 // This operation is identical to a `Rd AND Rd`.
920 def : InstAlias<"tst\t$rd", (ANDRdRr GPR8 : $rd, GPR8 : $rd)>;
924 // Mnemonic alias to 'ORI Rd, K'. Same bit pattern, same operands,
926 def : InstAlias<"sbr\t$rd, $k",
930 /* Disable display, so we don't override ORI */ 0>;
932 //===----------------------------------------------------------------------===//
934 //===----------------------------------------------------------------------===//
935 let isBarrier = 1, isBranch = 1, isTerminator = 1 in {
936 def RJMPk : FBRk<0, (outs),
939 "rjmp\t$target", [(br bb
942 let isIndirectBranch = 1,
943 Uses = [R31R30] in def IJMP
944 : F16<0b1001010000001001, (outs), (ins), "ijmp", []>,
945 Requires<[HasIJMPCALL]>;
947 let isIndirectBranch = 1,
948 Uses = [R31R30] in def EIJMP
949 : F16<0b1001010000011001, (outs), (ins), "eijmp", []>,
950 Requires<[HasEIJMPCALL]>;
952 def JMPk : F32BRk<0b110, (outs),
956 Requires<[HasJMPCALL]>;
959 //===----------------------------------------------------------------------===//
961 //===----------------------------------------------------------------------===//
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),
968 "rcall\t$target", []>;
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]>;
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]>;
982 // SP is marked as a use to prevent stack-pointer assignments that appear
983 // immediately before calls from potentially appearing dead.
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),
990 "call\t$k", [(AVRcall imm
992 Requires<[HasJMPCALL]>;
995 //===----------------------------------------------------------------------===//
996 // Return instructions.
997 //===----------------------------------------------------------------------===//
998 let isTerminator = 1, isReturn = 1, isBarrier = 1 in {
999 def RET : F16<0b1001010100001000, (outs), (ins), "ret", [(AVRretflag)]>;
1001 def RETI : F16<0b1001010100011000, (outs), (ins), "reti", [(AVRretiflag)]>;
1004 //===----------------------------------------------------------------------===//
1005 // Compare operations.
1006 //===----------------------------------------------------------------------===//
1007 let Defs = [SREG] in {
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),
1015 "cpse\t$rd, $rr", []>;
1018 : FRdRr<0b0001, 0b01, (outs),
1022 "cp\t$rd, $rr", [(AVRcmp i8
1027 // CPW Rd+1:Rd, Rr+1:Rr
1032 def CPWRdRr : Pseudo<(outs),
1042 let Uses = [SREG] in def CPCRdRr
1043 : FRdRr<0b0000, 0b01, (outs),
1047 "cpc\t$rd, $rr", [(AVRcmpc i8
1052 // CPCW Rd+1:Rd. Rr+1:Rr
1057 let Uses = [SREG] in def CPCWRdRr
1062 "cpcw\t$src, $src2",
1069 // Compares a register with an 8 bit immediate.
1071 : FRdK<0b0011, (outs),
1075 "cpi\t$rd, $k", [(AVRcmp i8
1081 //===----------------------------------------------------------------------===//
1082 // Register conditional skipping/branching operations.
1083 //===----------------------------------------------------------------------===//
1084 let 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),
1092 "sbrc\t$rr, $b", []>;
1094 def SBRSRrB : FRdB<0b11, (outs),
1098 "sbrs\t$rr, $b", []>;
1100 def SBICAb : FIOBIT<0b01, (outs),
1104 "sbic\t$a, $b", []>;
1106 def SBISAb : FIOBIT<0b11, (outs),
1110 "sbis\t$a, $b", []>;
1113 // Relative branches on status flag bits.
1114 let Uses = [SREG] in {
1116 // Branch if `s` flag in status register is set.
1117 def BRBSsk : FSK<0, (outs),
1121 "brbs\t$s, $k", []>;
1124 // Branch if `s` flag in status register is clear.
1125 def BRBCsk : FSK<1, (outs),
1129 "brbc\t$s, $k", []>;
1134 // Branch if carry flag is set
1135 def : InstAlias<"brcs\t$k", (BRBSsk 0, relbrtarget_7 : $k)>;
1138 // Branch if carry flag is clear
1139 def : InstAlias<"brcc\t$k", (BRBCsk 0, relbrtarget_7 : $k)>;
1142 // Branch if half carry flag is set
1143 def : InstAlias<"brhs\t$k", (BRBSsk 5, relbrtarget_7 : $k)>;
1146 // Branch if half carry flag is clear
1147 def : InstAlias<"brhc\t$k", (BRBCsk 5, relbrtarget_7 : $k)>;
1150 // Branch if the T flag is set
1151 def : InstAlias<"brts\t$k", (BRBSsk 6, relbrtarget_7 : $k)>;
1154 // Branch if the T flag is clear
1155 def : InstAlias<"brtc\t$k", (BRBCsk 6, relbrtarget_7 : $k)>;
1158 // Branch if the overflow flag is set
1159 def : InstAlias<"brvs\t$k", (BRBSsk 3, relbrtarget_7 : $k)>;
1162 // Branch if the overflow flag is clear
1163 def : InstAlias<"brvc\t$k", (BRBCsk 3, relbrtarget_7 : $k)>;
1166 // Branch if the global interrupt flag is enabled
1167 def : InstAlias<"brie\t$k", (BRBSsk 7, relbrtarget_7 : $k)>;
1170 // Branch if the global interrupt flag is disabled
1171 def : InstAlias<"brid\t$k", (BRBCsk 7, relbrtarget_7 : $k)>;
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.
1178 let isBranch = 1, isTerminator = 1, Uses = [SREG] in {
1179 def BREQk : FBRsk<0, 0b001, (outs),
1182 "breq\t$target", [(AVRbrcond bb
1183 : $target, AVR_COND_EQ)]>;
1185 def BRNEk : FBRsk<1, 0b001, (outs),
1188 "brne\t$target", [(AVRbrcond bb
1189 : $target, AVR_COND_NE)]>;
1191 def BRSHk : FBRsk<1, 0b000, (outs),
1194 "brsh\t$target", [(AVRbrcond bb
1195 : $target, AVR_COND_SH)]>;
1197 def BRLOk : FBRsk<0, 0b000, (outs),
1200 "brlo\t$target", [(AVRbrcond bb
1201 : $target, AVR_COND_LO)]>;
1203 def BRMIk : FBRsk<0, 0b010, (outs),
1206 "brmi\t$target", [(AVRbrcond bb
1207 : $target, AVR_COND_MI)]>;
1209 def BRPLk : FBRsk<1, 0b010, (outs),
1212 "brpl\t$target", [(AVRbrcond bb
1213 : $target, AVR_COND_PL)]>;
1215 def BRGEk : FBRsk<1, 0b100, (outs),
1218 "brge\t$target", [(AVRbrcond bb
1219 : $target, AVR_COND_GE)]>;
1221 def BRLTk : FBRsk<0, 0b100, (outs),
1224 "brlt\t$target", [(AVRbrcond bb
1225 : $target, AVR_COND_LT)]>;
1228 //===----------------------------------------------------------------------===//
1229 // Data transfer instructions
1230 //===----------------------------------------------------------------------===//
1231 // 8 and 16-bit register move instructions.
1232 let hasSideEffects = 0 in {
1233 def MOVRdRr : FRdRr<0b0010, 0b11,
1238 "mov\t$rd, $rr", []>;
1240 def MOVWRdRr : FMOVWRdRr<(outs DREGS
1244 "movw\t$dst, $src", []>,
1245 Requires<[HasMOVW]>;
1248 // Load immediate values into registers.
1249 let isReMaterializable = 1 in {
1250 def LDIRdK : FRdK<0b1110,
1255 "ldi\t$rd, $k", [(set i8
1259 // LDIW Rd+1:Rd, K+1:K
1264 def LDIWRdK : Pseudo<(outs DLDREGS
1268 "ldiw\t$dst, $src", [(set i16
1273 // Load from data space into register.
1274 let canFoldAsLoad = 1, isReMaterializable = 1 in {
1275 def LDSRdK : F32DM<0b0,
1280 "lds\t$rd, $k", [(set i8
1283 Requires<[HasSRAM]>;
1285 // LDSW Rd+1:Rd, K+1:K
1289 // lds Rd+1 (K+1:K) + 1
1290 def LDSWRdK : Pseudo<(outs DREGS
1294 "ldsw\t$dst, $src", [(set i16
1297 Requires<[HasSRAM]>;
1301 let canFoldAsLoad = 1, isReMaterializable = 1 in {
1302 def LDRdPtr : FSTLD<0, 0b00,
1307 "ld\t$reg, $ptrreg", [(set GPR8
1310 Requires<[HasSRAM]>;
1317 let Constraints = "@earlyclobber $reg" in def LDWRdPtr
1318 : Pseudo<(outs DREGS
1322 "ldw\t$reg, $ptrreg", [(set i16
1325 Requires<[HasSRAM]>;
1328 // Indirect loads (with postincrement or predecrement).
1329 let mayLoad = 1, hasSideEffects = 0,
1330 Constraints = "$ptrreg = $base_wb,@earlyclobber $reg" in {
1331 def LDRdPtrPi : FSTLD<0, 0b01,
1337 "ld\t$reg, $ptrreg+", []>,
1338 Requires<[HasSRAM]>;
1344 def LDWRdPtrPi : Pseudo<(outs DREGS
1349 "ldw\t$reg, $ptrreg+", []>,
1350 Requires<[HasSRAM]>;
1352 def LDRdPtrPd : FSTLD<0, 0b10,
1358 "ld\t$reg, -$ptrreg", []>,
1359 Requires<[HasSRAM]>;
1366 def LDWRdPtrPd : Pseudo<(outs DREGS
1371 "ldw\t$reg, -$ptrreg", []>,
1372 Requires<[HasSRAM]>;
1375 // Load indirect with displacement operations.
1376 let canFoldAsLoad = 1, isReMaterializable = 1 in {
1377 let Constraints = "@earlyclobber $reg" in def LDDRdPtrQ
1383 "ldd\t$reg, $memri", [(set i8
1386 Requires<[HasSRAM]>;
1388 // LDDW Rd+1:Rd, P+q
1393 let Constraints = "@earlyclobber $dst" in def LDDWRdPtrQ
1394 : Pseudo<(outs DREGS_WITHOUT_YZ_WORKAROUND
1398 "lddw\t$dst, $memri", [(set i16
1401 Requires<[HasSRAM]>;
1403 // An identical pseudo instruction to LDDWRdPtrQ, expect restricted to the Y
1404 // register and without the @earlyclobber flag.
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
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.
1416 // The pseudo expansion pass trivially expands this into LDDWRdPtrQ.
1418 // This instruction may be removed once PR13375 is fixed.
1420 hasSideEffects = 0 in def LDDWRdYQ : Pseudo<(outs DREGS
1424 "lddw\t$dst, $memri", []>,
1425 Requires<[HasSRAM]>;
1428 class AtomicLoad<PatFrag Op, RegisterClass DRC, RegisterClass PTRRC>
1433 "atomic_op", [(set DRC
1437 class AtomicStore<PatFrag Op, RegisterClass DRC, RegisterClass PTRRC>
1442 "atomic_op", [(Op i16
1447 "@earlyclobber $rd" in class AtomicLoadOp<PatFrag Op, RegisterClass DRC,
1448 RegisterClass PTRRC>
1454 "atomic_op", [(set DRC
1459 // FIXME: I think 16-bit atomic binary ops need to mark
1462 // Atomic instructions
1463 // ===================
1465 // These are all expanded by AVRExpandPseudoInsts
1467 // 8-bit operations can use any pointer register because
1468 // they are expanded directly into an LD/ST instruction.
1470 // 16-bit operations use 16-bit load/store postincrement instructions,
1471 // which require PTRDISPREGS.
1473 def AtomicLoad8 : AtomicLoad<atomic_load_8, GPR8, PTRREGS>;
1474 def AtomicLoad16 : AtomicLoad<atomic_load_16, DREGS, PTRDISPREGS>;
1476 def AtomicStore8 : AtomicStore<atomic_store_8, GPR8, PTRREGS>;
1477 def AtomicStore16 : AtomicStore<atomic_store_16, DREGS, PTRDISPREGS>;
1479 class AtomicLoadOp8<PatFrag Op> : AtomicLoadOp<Op, GPR8, PTRREGS>;
1480 class AtomicLoadOp16<PatFrag Op> : AtomicLoadOp<Op, DREGS, PTRDISPREGS>;
1482 def AtomicLoadAdd8 : AtomicLoadOp8<atomic_load_add_8>;
1483 def AtomicLoadAdd16 : AtomicLoadOp16<atomic_load_add_16>;
1484 def AtomicLoadSub8 : AtomicLoadOp8<atomic_load_sub_8>;
1485 def AtomicLoadSub16 : AtomicLoadOp16<atomic_load_sub_16>;
1486 def AtomicLoadAnd8 : AtomicLoadOp8<atomic_load_and_8>;
1487 def AtomicLoadAnd16 : AtomicLoadOp16<atomic_load_and_16>;
1488 def AtomicLoadOr8 : AtomicLoadOp8<atomic_load_or_8>;
1489 def AtomicLoadOr16 : AtomicLoadOp16<atomic_load_or_16>;
1490 def AtomicLoadXor8 : AtomicLoadOp8<atomic_load_xor_8>;
1491 def AtomicLoadXor16 : AtomicLoadOp16<atomic_load_xor_16>;
1493 : Pseudo<(outs), (ins), "atomic_fence", [(atomic_fence timm, timm)]>;
1495 // Indirect store from register to data space.
1496 def STSKRr : F32DM<0b1, (outs),
1500 "sts\t$k, $rd", [(store i8
1503 Requires<[HasSRAM]>;
1505 // STSW K+1:K, Rr+1:Rr
1508 // sts Rr+1, (K+1:K) + 1
1510 def STSWKRr : Pseudo<(outs),
1514 "stsw\t$dst, $src", [(store i16
1517 Requires<[HasSRAM]>;
1521 // Stores the value of Rr into the location addressed by pointer P.
1522 def STPtrRr : FSTLD<1, 0b00, (outs),
1526 "st\t$ptrreg, $reg", [(store GPR8
1529 Requires<[HasSRAM]>;
1532 // Stores the value of Rr into the location addressed by pointer P.
1537 def STWPtrRr : Pseudo<(outs),
1541 "stw\t$ptrreg, $reg", [(store i16
1544 Requires<[HasSRAM]>;
1546 // Indirect stores (with postincrement or predecrement).
1547 let Constraints = "$ptrreg = $base_wb,@earlyclobber $base_wb" in {
1550 // Stores the value of Rr into the location addressed by pointer P.
1551 // Post increments P.
1552 def STPtrPiRr : FSTLD<1, 0b01,
1559 "st\t$ptrreg+, $reg", [(set i16
1560 : $base_wb, (post_store GPR8
1564 Requires<[HasSRAM]>;
1567 // Stores the value of Rr into the location addressed by pointer P.
1568 // Post increments P.
1573 def STWPtrPiRr : Pseudo<(outs PTRREGS
1579 "stw\t$ptrreg+, $trh", [(set PTRREGS
1580 : $base_wb, (post_store DREGS
1584 Requires<[HasSRAM]>;
1587 // Stores the value of Rr into the location addressed by pointer P.
1588 // Pre decrements P.
1589 def STPtrPdRr : FSTLD<1, 0b10,
1596 "st\t-$ptrreg, $reg", [(set i16
1597 : $base_wb, (pre_store GPR8
1601 Requires<[HasSRAM]>;
1604 // Stores the value of Rr into the location addressed by pointer P.
1605 // Pre decrements P.
1610 def STWPtrPdRr : Pseudo<(outs PTRREGS
1616 "stw\t-$ptrreg, $reg", [(set PTRREGS
1617 : $base_wb, (pre_store i16
1621 Requires<[HasSRAM]>;
1624 // Store indirect with displacement operations.
1626 // Stores the value of Rr into the location addressed by pointer P with a
1627 // displacement of q. Does not modify P.
1628 def STDPtrQRr : FSTDLDD<1, (outs),
1632 "std\t$memri, $reg", [(store i8
1635 Requires<[HasSRAM]>;
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.
1644 def STDWPtrQRr : Pseudo<(outs),
1648 "stdw\t$memri, $src", [(store i16
1651 Requires<[HasSRAM]>;
1653 // Load program memory operations.
1654 let canFoldAsLoad = 1, isReMaterializable = 1, mayLoad = 1,
1655 hasSideEffects = 0 in {
1657 Uses = [R31R30] in def LPM
1658 : F16<0b1001010111001000, (outs), (ins), "lpm", []>,
1661 def LPMRdZ : FLPMX<0, 0,
1666 "lpm\t$dst, $z", []>,
1667 Requires<[HasLPMX]>;
1669 // Load program memory, while postincrementing the Z register.
1670 let Defs = [R31R30] in {
1671 def LPMRdZPi : FLPMX<0, 1,
1676 "lpm\t$dst, $z+", []>,
1677 Requires<[HasLPMX]>;
1679 def LPMWRdZ : Pseudo<(outs DREGS
1683 "lpmw\t$dst, $z", []>,
1684 Requires<[HasLPMX]>;
1686 def LPMWRdZPi : Pseudo<(outs DREGS
1690 "lpmw\t$dst, $z+", []>,
1691 Requires<[HasLPMX]>;
1695 // Extended load program memory operations.
1696 let mayLoad = 1, hasSideEffects = 0 in {
1698 Uses = [R31R30] in def ELPM
1699 : F16<0b1001010111011000, (outs), (ins), "elpm", []>,
1700 Requires<[HasELPM]>;
1702 def ELPMRdZ : FLPMX<1, 0,
1707 "elpm\t$dst, $z", []>,
1708 Requires<[HasELPMX]>;
1710 let Defs = [R31R30] in def ELPMRdZPi : FLPMX<1, 1,
1715 "elpm\t$dst, $z+", []>,
1716 Requires<[HasELPMX]>;
1719 // Store program memory operations.
1720 let Uses = [R1, R0] in {
1721 let Uses = [R31R30, R1, R0] in def SPM
1722 : F16<0b1001010111101000, (outs), (ins), "spm", []>,
1725 let Defs = [R31R30] in def SPMZPi : F16<0b1001010111111000, (outs),
1729 Requires<[HasSPMX]>;
1732 // Read data from IO location operations.
1733 let canFoldAsLoad = 1, isReMaterializable = 1 in {
1734 def INRdA : FIORdA<(outs GPR8
1738 "in\t$dst, $src", [(set i8
1739 : $dst, (load ioaddr8
1742 def INWRdA : Pseudo<(outs DREGS
1746 "inw\t$dst, $src", [(set i16
1747 : $dst, (load ioaddr16
1751 // Write data to IO location operations.
1752 def OUTARr : FIOARr<(outs),
1756 "out\t$dst, $src", [(store i8
1760 def OUTWARr : Pseudo<(outs),
1764 "outw\t$dst, $src", [(store i16
1768 // Stack push/pop operations.
1769 let Defs = [SP], Uses = [SP], hasSideEffects = 0 in {
1770 // Stack push operations.
1771 let mayStore = 1 in {
1772 def PUSHRr : FRd<0b1001, 0b0011111, (outs),
1776 Requires<[HasSRAM]>;
1778 def PUSHWRr : Pseudo<(outs),
1782 Requires<[HasSRAM]>;
1785 // Stack pop operations.
1786 let mayLoad = 1 in {
1787 def POPRd : FRd<0b1001, 0b0001111,
1790 (ins), "pop\t$reg", []>,
1791 Requires<[HasSRAM]>;
1793 def POPWRd : Pseudo<(outs DREGS
1795 (ins), "popw\t$reg", []>,
1796 Requires<[HasSRAM]>;
1800 // Read-Write-Modify (RMW) instructions.
1801 def XCHZRd : FZRd<0b100,
1806 "xch\t$z, $rd", []>,
1807 Requires<[SupportsRMW]>;
1809 def LASZRd : FZRd<0b101,
1814 "las\t$z, $rd", []>,
1815 Requires<[SupportsRMW]>;
1817 def LACZRd : FZRd<0b110,
1822 "lac\t$z, $rd", []>,
1823 Requires<[SupportsRMW]>;
1825 def LATZRd : FZRd<0b111,
1830 "lat\t$z, $rd", []>,
1831 Requires<[SupportsRMW]>;
1833 //===----------------------------------------------------------------------===//
1834 // Bit and bit-test instructions
1835 //===----------------------------------------------------------------------===//
1837 // Bit shift/rotate operations.
1838 let Constraints = "$src = $rd", Defs = [SREG] in {
1839 // 8-bit LSL is an alias of ADD Rd, Rd
1841 def LSLWRd : Pseudo<(outs DREGS
1851 def LSLWNRd : Pseudo<(outs DLDREGS
1856 "lslwn\t$rd, $bits", [
1858 : $rd, (AVRlslwn i16
1864 def LSLBNRd : Pseudo<(outs LD8
1869 "lslbn\t$rd, $bits", [
1878 : FRd<0b1001, 0b0100110,
1883 "lsr\t$rd", [(set i8
1888 def LSRWRd : Pseudo<(outs DREGS
1898 def LSRWNRd : Pseudo<(outs DLDREGS
1903 "lsrwn\t$rd, $bits", [
1905 : $rd, (AVRlsrwn i16
1911 def LSRBNRd : Pseudo<(outs LD8
1916 "lsrbn\t$rd, $bits", [
1925 : FRd<0b1001, 0b0100101,
1930 "asr\t$rd", [(set i8
1935 def ASRWNRd : Pseudo<(outs DLDREGS
1940 "asrwn\t$rd, $bits", [
1942 : $rd, (AVRasrwn i16
1948 def ASRBNRd : Pseudo<(outs LD8
1953 "asrbn\t$rd, $bits", [
1961 def ASRWRd : Pseudo<(outs DREGS
1971 def ROLBRd : Pseudo<(outs GPR8
1981 def RORBRd : Pseudo<(outs GPR8
1991 // Bit rotate operations.
1992 let Uses = [SREG] in {
1995 : Pseudo<(outs DREGS
2005 def RORRd : FRd<0b1001, 0b0100111,
2013 : Pseudo<(outs DREGS
2026 // Swaps the high and low nibbles in a register.
2028 "$src = $rd" in def SWAPRd : FRd<0b1001, 0b0100010,
2033 "swap\t$rd", [(set i8
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.
2040 def SBIAb : FIOBIT<0b10, (outs),
2044 "sbi\t$addr, $bit", [(store(or(i8(load lowioaddr8
2051 def CBIAb : FIOBIT<0b00, (outs),
2055 "cbi\t$addr, $bit", [(store(and(i8(load lowioaddr8
2062 // Status register bit load/store operations.
2063 let Defs = [SREG] in def BST : FRdB<0b01, (outs),
2067 "bst\t$rd, $b", []>;
2069 let Constraints = "$src = $rd",
2070 Uses = [SREG] in def BLD : FRdB<0b00,
2076 "bld\t$rd, $b", []>;
2078 def CBR : InstAlias<"cbr\t$rd, $k", (ANDIRdK LD8 : $rd, imm_com8 : $k), 0>;
2081 // Alias for EOR Rd, Rd
2083 // Clears all bits in a register.
2084 def CLR : InstAlias<"clr\t$rd", (EORRdRr GPR8 : $rd, GPR8 : $rd)>;
2087 // Alias for ADD Rd, Rd
2089 // Logical shift left one bit.
2090 def LSL : InstAlias<"lsl\t$rd", (ADDRdRr GPR8 : $rd, GPR8 : $rd)>;
2092 def ROL : InstAlias<"rol\t$rd", (ADCRdRr GPR8 : $rd, GPR8 : $rd)>;
2095 // Alias for LDI Rd, 0xff
2097 // Sets all bits in a register.
2098 def : InstAlias<"ser\t$rd", (LDIRdK LD8 : $rd, 0xff), 0>;
2100 let Defs = [SREG] in def BSETs : FS<0, (outs),
2105 let Defs = [SREG] in def BCLRs : FS<1, (outs),
2110 // Set/clear aliases for the carry (C) status flag (bit 0).
2111 def : InstAlias<"sec", (BSETs 0)>;
2112 def : InstAlias<"clc", (BCLRs 0)>;
2114 // Set/clear aliases for the zero (Z) status flag (bit 1).
2115 def : InstAlias<"sez", (BSETs 1)>;
2116 def : InstAlias<"clz", (BCLRs 1)>;
2118 // Set/clear aliases for the negative (N) status flag (bit 2).
2119 def : InstAlias<"sen", (BSETs 2)>;
2120 def : InstAlias<"cln", (BCLRs 2)>;
2122 // Set/clear aliases for the overflow (V) status flag (bit 3).
2123 def : InstAlias<"sev", (BSETs 3)>;
2124 def : InstAlias<"clv", (BCLRs 3)>;
2126 // Set/clear aliases for the signed (S) status flag (bit 4).
2127 def : InstAlias<"ses", (BSETs 4)>;
2128 def : InstAlias<"cls", (BCLRs 4)>;
2130 // Set/clear aliases for the half-carry (H) status flag (bit 5).
2131 def : InstAlias<"seh", (BSETs 5)>;
2132 def : InstAlias<"clh", (BCLRs 5)>;
2134 // Set/clear aliases for the T status flag (bit 6).
2135 def : InstAlias<"set", (BSETs 6)>;
2136 def : InstAlias<"clt", (BCLRs 6)>;
2138 // Set/clear aliases for the interrupt (I) status flag (bit 7).
2139 def : InstAlias<"sei", (BSETs 7)>;
2140 def : InstAlias<"cli", (BCLRs 7)>;
2142 //===----------------------------------------------------------------------===//
2143 // Special/Control instructions
2144 //===----------------------------------------------------------------------===//
2147 // Breakpoint instruction
2149 // <|1001|0101|1001|1000>
2150 def BREAK : F16<0b1001010110011000, (outs), (ins), "break", []>,
2151 Requires<[HasBREAK]>;
2154 // No-operation instruction
2156 // <|0000|0000|0000|0000>
2157 def NOP : F16<0b0000000000000000, (outs), (ins), "nop", []>;
2160 // Sleep instruction
2162 // <|1001|0101|1000|1000>
2163 def SLEEP : F16<0b1001010110001000, (outs), (ins), "sleep", []>;
2168 // <|1001|0101|1010|1000>
2169 def WDR : F16<0b1001010110101000, (outs), (ins), "wdr", []>;
2171 //===----------------------------------------------------------------------===//
2172 // Pseudo instructions for later expansion
2173 //===----------------------------------------------------------------------===//
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.
2179 : ExtensionPseudo<(outs DREGS
2190 : ExtensionPseudo<(outs DREGS
2200 // This pseudo gets expanded into a movw+adiw thus it clobbers SREG.
2202 hasSideEffects = 0 in def FRMIDX : Pseudo<(outs DLDREGS
2207 "frmidx\t$dst, $src, $src2", []>;
2209 // This pseudo is either converted to a regular store or a push which clobbers
2211 def STDSPQRr : StorePseudo<(outs),
2215 "stdstk\t$dst, $src", [(store i8
2219 // This pseudo is either converted to a regular store or a push which clobbers
2221 def STDWSPQRr : StorePseudo<(outs),
2225 "stdwstk\t$dst, $src", [(store i16
2229 // SP read/write pseudos.
2230 let hasSideEffects = 0 in {
2231 let Uses = [SP] in def SPREAD : Pseudo<(outs DREGS
2235 "spread\t$dst, $src", []>;
2237 let Defs = [SP] in def SPWRITE : Pseudo<(outs GPRSP
2241 "spwrite\t$dst, $src", []>;
2244 def Select8 : SelectPseudo<(outs GPR8
2250 "# Select8 PSEUDO", [(set i8
2251 : $dst, (AVRselectcc i8
2256 def Select16 : SelectPseudo<(outs DREGS
2262 "# Select16 PSEUDO", [(set i16
2263 : $dst, (AVRselectcc i16
2268 def Lsl8 : ShiftPseudo<(outs GPR8
2273 "# Lsl8 PSEUDO", [(set i8
2274 : $dst, (AVRlslLoop i8
2278 def Lsl16 : ShiftPseudo<(outs DREGS
2283 "# Lsl16 PSEUDO", [(set i16
2284 : $dst, (AVRlslLoop i16
2288 def Lsr8 : ShiftPseudo<(outs GPR8
2293 "# Lsr8 PSEUDO", [(set i8
2294 : $dst, (AVRlsrLoop i8
2298 def Lsr16 : ShiftPseudo<(outs DREGS
2303 "# Lsr16 PSEUDO", [(set i16
2304 : $dst, (AVRlsrLoop i16
2308 def Rol8 : ShiftPseudo<(outs GPR8
2313 "# Rol8 PSEUDO", [(set i8
2314 : $dst, (AVRrolLoop i8
2318 def Rol16 : ShiftPseudo<(outs DREGS
2323 "# Rol16 PSEUDO", [(set i16
2324 : $dst, (AVRrolLoop i16
2328 def Ror8 : ShiftPseudo<(outs GPR8
2333 "# Ror8 PSEUDO", [(set i8
2334 : $dst, (AVRrorLoop i8
2338 def Ror16 : ShiftPseudo<(outs DREGS
2343 "# Ror16 PSEUDO", [(set i16
2344 : $dst, (AVRrorLoop i16
2348 def Asr8 : ShiftPseudo<(outs GPR8
2353 "# Asr8 PSEUDO", [(set i8
2354 : $dst, (AVRasrLoop i8
2358 def Asr16 : ShiftPseudo<(outs DREGS
2363 "# Asr16 PSEUDO", [(set i16
2364 : $dst, (AVRasrLoop i16
2368 //===----------------------------------------------------------------------===//
2369 // Non-Instruction Patterns
2370 //===----------------------------------------------------------------------===//
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)
2375 // the add instruction always writes the carry flag
2376 def : Pat<(addc i8 : $src, i8 : $src2), (ADDRdRr i8 : $src, i8 : $src2)>;
2377 def : Pat<(addc DREGS
2384 // all sub instruction variants always writes the carry flag
2385 def : Pat<(subc i8 : $src, i8 : $src2), (SUBRdRr i8 : $src, i8 : $src2)>;
2386 def : Pat<(subc i16 : $src, i16 : $src2), (SUBWRdRr i16 : $src, i16 : $src2)>;
2387 def : Pat<(subc i8 : $src, imm : $src2), (SUBIRdK i8 : $src, imm : $src2)>;
2388 def : Pat<(subc i16 : $src, imm : $src2), (SUBIWRdK i16 : $src, imm : $src2)>;
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.
2393 : $src1, imm0_63_neg
2396 : $src1, (imm0_63_neg
2402 : $src1, (imm16_neg_XFORM imm
2408 : $src1, (imm16_neg_XFORM imm
2415 : $src1, (imm8_neg_XFORM imm
2421 : $src1, (imm8_neg_XFORM imm
2427 : $src1, (imm8_neg_XFORM imm
2431 def : Pat<(AVRcall(i16 tglobaladdr : $dst)), (CALLk tglobaladdr : $dst)>;
2432 def : Pat<(AVRcall(i16 texternalsym : $dst)), (CALLk texternalsym : $dst)>;
2435 def : Pat<(i16(anyext i8
2437 (INSERT_SUBREG(i16(IMPLICIT_DEF)), i8
2441 def : Pat<(i8(trunc i16 : $src)), (EXTRACT_SUBREG i16 : $src, sub_lo)>;
2444 def : Pat<(sext_inreg i16
2446 (SEXT(i8(EXTRACT_SUBREG i16
2450 def : Pat<(i16(AVRWrapper tglobaladdr : $dst)), (LDIWRdK tglobaladdr : $dst)>;
2452 : $src, (AVRWrapper tglobaladdr
2457 def : Pat<(i8(load(AVRWrapper tglobaladdr
2461 def : Pat<(i16(load(AVRWrapper tglobaladdr
2463 (LDSWRdK tglobaladdr
2466 : $src, (i16(AVRWrapper tglobaladdr
2471 def : Pat<(store i16
2472 : $src, (i16(AVRWrapper tglobaladdr
2474 (STSWKRr tglobaladdr
2479 def : Pat<(i16(AVRWrapper tblockaddress
2481 (LDIWRdK tblockaddress
2484 def : Pat<(i8(trunc(AVRlsrwn DLDREGS
2486 (EXTRACT_SUBREG DREGS
2489 // :FIXME: DAGCombiner produces an shl node after legalization from these seq:
2490 // BR_JT -> (mul x, 2) -> (shl x, 1)
2491 def : Pat<(shl i16 : $src1, (i8 1)), (LSLWRd i16 : $src1)>;
2493 // Lowering of 'tst' node to 'TST' instruction.
2494 // TST is an alias of AND Rd, Rd.
2495 def : Pat<(AVRtst i8 : $rd), (ANDRdRr GPR8 : $rd, GPR8 : $rd)>;
2497 // Lowering of 'lsl' node to 'LSL' instruction.
2498 // LSL is an alias of 'ADD Rd, Rd'
2499 def : Pat<(AVRlsl i8 : $rd), (ADDRdRr GPR8 : $rd, GPR8 : $rd)>;