xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===-- AVRExpandPseudoInsts.cpp - Expand pseudo instructions -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains a pass that expands pseudo instructions into target
100b57cec5SDimitry Andric // instructions. This pass should be run after register allocation but before
110b57cec5SDimitry Andric // the post-regalloc scheduling pass.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "AVR.h"
160b57cec5SDimitry Andric #include "AVRInstrInfo.h"
170b57cec5SDimitry Andric #include "AVRTargetMachine.h"
180b57cec5SDimitry Andric #include "MCTargetDesc/AVRMCTargetDesc.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric #define AVR_EXPAND_PSEUDO_NAME "AVR pseudo instruction expansion pass"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric namespace {
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric /// Expands "placeholder" instructions marked as pseudo into
320b57cec5SDimitry Andric /// actual AVR instructions.
330b57cec5SDimitry Andric class AVRExpandPseudo : public MachineFunctionPass {
340b57cec5SDimitry Andric public:
350b57cec5SDimitry Andric   static char ID;
360b57cec5SDimitry Andric 
AVRExpandPseudo()370b57cec5SDimitry Andric   AVRExpandPseudo() : MachineFunctionPass(ID) {
380b57cec5SDimitry Andric     initializeAVRExpandPseudoPass(*PassRegistry::getPassRegistry());
390b57cec5SDimitry Andric   }
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
420b57cec5SDimitry Andric 
getPassName() const430b57cec5SDimitry Andric   StringRef getPassName() const override { return AVR_EXPAND_PSEUDO_NAME; }
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric private:
460b57cec5SDimitry Andric   typedef MachineBasicBlock Block;
470b57cec5SDimitry Andric   typedef Block::iterator BlockIt;
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   const AVRRegisterInfo *TRI;
500b57cec5SDimitry Andric   const TargetInstrInfo *TII;
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   bool expandMBB(Block &MBB);
530b57cec5SDimitry Andric   bool expandMI(Block &MBB, BlockIt MBBI);
540b57cec5SDimitry Andric   template <unsigned OP> bool expand(Block &MBB, BlockIt MBBI);
550b57cec5SDimitry Andric 
buildMI(Block & MBB,BlockIt MBBI,unsigned Opcode)560b57cec5SDimitry Andric   MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode) {
570b57cec5SDimitry Andric     return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode));
580b57cec5SDimitry Andric   }
590b57cec5SDimitry Andric 
buildMI(Block & MBB,BlockIt MBBI,unsigned Opcode,Register DstReg)600b57cec5SDimitry Andric   MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode,
615ffd83dbSDimitry Andric                               Register DstReg) {
620b57cec5SDimitry Andric     return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode), DstReg);
630b57cec5SDimitry Andric   }
640b57cec5SDimitry Andric 
getRegInfo(Block & MBB)65349cc55cSDimitry Andric   MachineRegisterInfo &getRegInfo(Block &MBB) {
66349cc55cSDimitry Andric     return MBB.getParent()->getRegInfo();
67349cc55cSDimitry Andric   }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   bool expandArith(unsigned OpLo, unsigned OpHi, Block &MBB, BlockIt MBBI);
700b57cec5SDimitry Andric   bool expandLogic(unsigned Op, Block &MBB, BlockIt MBBI);
710b57cec5SDimitry Andric   bool expandLogicImm(unsigned Op, Block &MBB, BlockIt MBBI);
720b57cec5SDimitry Andric   bool isLogicImmOpRedundant(unsigned Op, unsigned ImmVal) const;
73*06c3fb27SDimitry Andric   bool isLogicRegOpUndef(unsigned Op, unsigned ImmVal) const;
740b57cec5SDimitry Andric 
75349cc55cSDimitry Andric   template <typename Func> bool expandAtomic(Block &MBB, BlockIt MBBI, Func f);
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   template <typename Func>
780b57cec5SDimitry Andric   bool expandAtomicBinaryOp(unsigned Opcode, Block &MBB, BlockIt MBBI, Func f);
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   bool expandAtomicBinaryOp(unsigned Opcode, Block &MBB, BlockIt MBBI);
810b57cec5SDimitry Andric 
8281ad6265SDimitry Andric   /// Specific shift implementation for int8.
83fe6060f1SDimitry Andric   bool expandLSLB7Rd(Block &MBB, BlockIt MBBI);
84fe6060f1SDimitry Andric   bool expandLSRB7Rd(Block &MBB, BlockIt MBBI);
8504eeddc0SDimitry Andric   bool expandASRB6Rd(Block &MBB, BlockIt MBBI);
86fe6060f1SDimitry Andric   bool expandASRB7Rd(Block &MBB, BlockIt MBBI);
8781ad6265SDimitry Andric 
8881ad6265SDimitry Andric   /// Specific shift implementation for int16.
89fe6060f1SDimitry Andric   bool expandLSLW4Rd(Block &MBB, BlockIt MBBI);
90fe6060f1SDimitry Andric   bool expandLSRW4Rd(Block &MBB, BlockIt MBBI);
9181ad6265SDimitry Andric   bool expandASRW7Rd(Block &MBB, BlockIt MBBI);
92fe6060f1SDimitry Andric   bool expandLSLW8Rd(Block &MBB, BlockIt MBBI);
93fe6060f1SDimitry Andric   bool expandLSRW8Rd(Block &MBB, BlockIt MBBI);
94fe6060f1SDimitry Andric   bool expandASRW8Rd(Block &MBB, BlockIt MBBI);
95fe6060f1SDimitry Andric   bool expandLSLW12Rd(Block &MBB, BlockIt MBBI);
96fe6060f1SDimitry Andric   bool expandLSRW12Rd(Block &MBB, BlockIt MBBI);
9781ad6265SDimitry Andric   bool expandASRW14Rd(Block &MBB, BlockIt MBBI);
9881ad6265SDimitry Andric   bool expandASRW15Rd(Block &MBB, BlockIt MBBI);
99fe6060f1SDimitry Andric 
10004eeddc0SDimitry Andric   // Common implementation of LPMWRdZ and ELPMWRdZ.
101*06c3fb27SDimitry Andric   bool expandLPMWELPMW(Block &MBB, BlockIt MBBI, bool IsELPM);
102*06c3fb27SDimitry Andric   // Common implementation of LPMBRdZ and ELPMBRdZ.
103*06c3fb27SDimitry Andric   bool expandLPMBELPMB(Block &MBB, BlockIt MBBI, bool IsELPM);
104*06c3fb27SDimitry Andric   // Common implementation of ROLBRdR1 and ROLBRdR17.
105*06c3fb27SDimitry Andric   bool expandROLBRd(Block &MBB, BlockIt MBBI);
1060b57cec5SDimitry Andric };
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric char AVRExpandPseudo::ID = 0;
1090b57cec5SDimitry Andric 
expandMBB(MachineBasicBlock & MBB)1100b57cec5SDimitry Andric bool AVRExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
1110b57cec5SDimitry Andric   bool Modified = false;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   BlockIt MBBI = MBB.begin(), E = MBB.end();
1140b57cec5SDimitry Andric   while (MBBI != E) {
1150b57cec5SDimitry Andric     BlockIt NMBBI = std::next(MBBI);
1160b57cec5SDimitry Andric     Modified |= expandMI(MBB, MBBI);
1170b57cec5SDimitry Andric     MBBI = NMBBI;
1180b57cec5SDimitry Andric   }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   return Modified;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)1230b57cec5SDimitry Andric bool AVRExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
1240b57cec5SDimitry Andric   bool Modified = false;
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
1270b57cec5SDimitry Andric   TRI = STI.getRegisterInfo();
1280b57cec5SDimitry Andric   TII = STI.getInstrInfo();
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   for (Block &MBB : MF) {
1310b57cec5SDimitry Andric     bool ContinueExpanding = true;
1320b57cec5SDimitry Andric     unsigned ExpandCount = 0;
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric     // Continue expanding the block until all pseudos are expanded.
1350b57cec5SDimitry Andric     do {
1360b57cec5SDimitry Andric       assert(ExpandCount < 10 && "pseudo expand limit reached");
13781ad6265SDimitry Andric       (void)ExpandCount;
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric       bool BlockModified = expandMBB(MBB);
1400b57cec5SDimitry Andric       Modified |= BlockModified;
1410b57cec5SDimitry Andric       ExpandCount++;
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric       ContinueExpanding = BlockModified;
1440b57cec5SDimitry Andric     } while (ContinueExpanding);
1450b57cec5SDimitry Andric   }
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   return Modified;
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric 
expandArith(unsigned OpLo,unsigned OpHi,Block & MBB,BlockIt MBBI)150349cc55cSDimitry Andric bool AVRExpandPseudo::expandArith(unsigned OpLo, unsigned OpHi, Block &MBB,
151349cc55cSDimitry Andric                                   BlockIt MBBI) {
1520b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
1535ffd83dbSDimitry Andric   Register SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
1548bcb0991SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
1558bcb0991SDimitry Andric   Register SrcReg = MI.getOperand(2).getReg();
1560b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
1570b57cec5SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
1580b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(2).isKill();
1590b57cec5SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
1600b57cec5SDimitry Andric   TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
1610b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   buildMI(MBB, MBBI, OpLo)
1640b57cec5SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1650b57cec5SDimitry Andric       .addReg(DstLoReg, getKillRegState(DstIsKill))
1660b57cec5SDimitry Andric       .addReg(SrcLoReg, getKillRegState(SrcIsKill));
1670b57cec5SDimitry Andric 
168349cc55cSDimitry Andric   auto MIBHI =
169349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpHi)
1700b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1710b57cec5SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill))
1720b57cec5SDimitry Andric           .addReg(SrcHiReg, getKillRegState(SrcIsKill));
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   if (ImpIsDead)
1750b57cec5SDimitry Andric     MIBHI->getOperand(3).setIsDead();
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   // SREG is always implicitly killed
1780b57cec5SDimitry Andric   MIBHI->getOperand(4).setIsKill();
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   MI.eraseFromParent();
1810b57cec5SDimitry Andric   return true;
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric 
expandLogic(unsigned Op,Block & MBB,BlockIt MBBI)184349cc55cSDimitry Andric bool AVRExpandPseudo::expandLogic(unsigned Op, Block &MBB, BlockIt MBBI) {
1850b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
1865ffd83dbSDimitry Andric   Register SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
1878bcb0991SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
1888bcb0991SDimitry Andric   Register SrcReg = MI.getOperand(2).getReg();
1890b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
1900b57cec5SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
1910b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(2).isKill();
1920b57cec5SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
1930b57cec5SDimitry Andric   TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
1940b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1950b57cec5SDimitry Andric 
196349cc55cSDimitry Andric   auto MIBLO =
197349cc55cSDimitry Andric       buildMI(MBB, MBBI, Op)
1980b57cec5SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1990b57cec5SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill))
2000b57cec5SDimitry Andric           .addReg(SrcLoReg, getKillRegState(SrcIsKill));
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric   // SREG is always implicitly dead
2030b57cec5SDimitry Andric   MIBLO->getOperand(3).setIsDead();
2040b57cec5SDimitry Andric 
205349cc55cSDimitry Andric   auto MIBHI =
206349cc55cSDimitry Andric       buildMI(MBB, MBBI, Op)
2070b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
2080b57cec5SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill))
2090b57cec5SDimitry Andric           .addReg(SrcHiReg, getKillRegState(SrcIsKill));
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   if (ImpIsDead)
2120b57cec5SDimitry Andric     MIBHI->getOperand(3).setIsDead();
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   MI.eraseFromParent();
2150b57cec5SDimitry Andric   return true;
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric 
isLogicImmOpRedundant(unsigned Op,unsigned ImmVal) const218349cc55cSDimitry Andric bool AVRExpandPseudo::isLogicImmOpRedundant(unsigned Op,
219349cc55cSDimitry Andric                                             unsigned ImmVal) const {
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric   // ANDI Rd, 0xff is redundant.
2220b57cec5SDimitry Andric   if (Op == AVR::ANDIRdK && ImmVal == 0xff)
2230b57cec5SDimitry Andric     return true;
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   // ORI Rd, 0x0 is redundant.
2260b57cec5SDimitry Andric   if (Op == AVR::ORIRdK && ImmVal == 0x0)
2270b57cec5SDimitry Andric     return true;
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   return false;
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric 
isLogicRegOpUndef(unsigned Op,unsigned ImmVal) const232*06c3fb27SDimitry Andric bool AVRExpandPseudo::isLogicRegOpUndef(unsigned Op, unsigned ImmVal) const {
233*06c3fb27SDimitry Andric   // ANDI Rd, 0x00 clears all input bits.
234*06c3fb27SDimitry Andric   if (Op == AVR::ANDIRdK && ImmVal == 0x00)
235*06c3fb27SDimitry Andric     return true;
236*06c3fb27SDimitry Andric 
237*06c3fb27SDimitry Andric   // ORI Rd, 0xff sets all input bits.
238*06c3fb27SDimitry Andric   if (Op == AVR::ORIRdK && ImmVal == 0xff)
239*06c3fb27SDimitry Andric     return true;
240*06c3fb27SDimitry Andric 
241*06c3fb27SDimitry Andric   return false;
242*06c3fb27SDimitry Andric }
243*06c3fb27SDimitry Andric 
expandLogicImm(unsigned Op,Block & MBB,BlockIt MBBI)244349cc55cSDimitry Andric bool AVRExpandPseudo::expandLogicImm(unsigned Op, Block &MBB, BlockIt MBBI) {
2450b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
2465ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
2478bcb0991SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
2480b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
2490b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
2500b57cec5SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
2510b57cec5SDimitry Andric   unsigned Imm = MI.getOperand(2).getImm();
2520b57cec5SDimitry Andric   unsigned Lo8 = Imm & 0xff;
2530b57cec5SDimitry Andric   unsigned Hi8 = (Imm >> 8) & 0xff;
2540b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric   if (!isLogicImmOpRedundant(Op, Lo8)) {
257349cc55cSDimitry Andric     auto MIBLO =
258349cc55cSDimitry Andric         buildMI(MBB, MBBI, Op)
2590b57cec5SDimitry Andric             .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
2600b57cec5SDimitry Andric             .addReg(DstLoReg, getKillRegState(SrcIsKill))
2610b57cec5SDimitry Andric             .addImm(Lo8);
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric     // SREG is always implicitly dead
2640b57cec5SDimitry Andric     MIBLO->getOperand(3).setIsDead();
265*06c3fb27SDimitry Andric 
266*06c3fb27SDimitry Andric     if (isLogicRegOpUndef(Op, Lo8))
267*06c3fb27SDimitry Andric       MIBLO->getOperand(1).setIsUndef(true);
2680b57cec5SDimitry Andric   }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   if (!isLogicImmOpRedundant(Op, Hi8)) {
271349cc55cSDimitry Andric     auto MIBHI =
272349cc55cSDimitry Andric         buildMI(MBB, MBBI, Op)
2730b57cec5SDimitry Andric             .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
2740b57cec5SDimitry Andric             .addReg(DstHiReg, getKillRegState(SrcIsKill))
2750b57cec5SDimitry Andric             .addImm(Hi8);
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric     if (ImpIsDead)
2780b57cec5SDimitry Andric       MIBHI->getOperand(3).setIsDead();
279*06c3fb27SDimitry Andric 
280*06c3fb27SDimitry Andric     if (isLogicRegOpUndef(Op, Hi8))
281*06c3fb27SDimitry Andric       MIBHI->getOperand(1).setIsUndef(true);
2820b57cec5SDimitry Andric   }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   MI.eraseFromParent();
2850b57cec5SDimitry Andric   return true;
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)2890b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::ADDWRdRr>(Block &MBB, BlockIt MBBI) {
2900b57cec5SDimitry Andric   return expandArith(AVR::ADDRdRr, AVR::ADCRdRr, MBB, MBBI);
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)2940b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::ADCWRdRr>(Block &MBB, BlockIt MBBI) {
2950b57cec5SDimitry Andric   return expandArith(AVR::ADCRdRr, AVR::ADCRdRr, MBB, MBBI);
2960b57cec5SDimitry Andric }
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)2990b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::SUBWRdRr>(Block &MBB, BlockIt MBBI) {
3000b57cec5SDimitry Andric   return expandArith(AVR::SUBRdRr, AVR::SBCRdRr, MBB, MBBI);
3010b57cec5SDimitry Andric }
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)3040b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::SUBIWRdK>(Block &MBB, BlockIt MBBI) {
3050b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
3065ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
3075ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
3080b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
3090b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
3100b57cec5SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
3110b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
3120b57cec5SDimitry Andric 
313349cc55cSDimitry Andric   auto MIBLO =
314349cc55cSDimitry Andric       buildMI(MBB, MBBI, AVR::SUBIRdK)
3150b57cec5SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
3160b57cec5SDimitry Andric           .addReg(DstLoReg, getKillRegState(SrcIsKill));
3170b57cec5SDimitry Andric 
318349cc55cSDimitry Andric   auto MIBHI =
319349cc55cSDimitry Andric       buildMI(MBB, MBBI, AVR::SBCIRdK)
3200b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
3210b57cec5SDimitry Andric           .addReg(DstHiReg, getKillRegState(SrcIsKill));
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric   switch (MI.getOperand(2).getType()) {
3240b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress: {
3250b57cec5SDimitry Andric     const GlobalValue *GV = MI.getOperand(2).getGlobal();
3260b57cec5SDimitry Andric     int64_t Offs = MI.getOperand(2).getOffset();
3270b57cec5SDimitry Andric     unsigned TF = MI.getOperand(2).getTargetFlags();
3280b57cec5SDimitry Andric     MIBLO.addGlobalAddress(GV, Offs, TF | AVRII::MO_NEG | AVRII::MO_LO);
3290b57cec5SDimitry Andric     MIBHI.addGlobalAddress(GV, Offs, TF | AVRII::MO_NEG | AVRII::MO_HI);
3300b57cec5SDimitry Andric     break;
3310b57cec5SDimitry Andric   }
3320b57cec5SDimitry Andric   case MachineOperand::MO_Immediate: {
3330b57cec5SDimitry Andric     unsigned Imm = MI.getOperand(2).getImm();
3340b57cec5SDimitry Andric     MIBLO.addImm(Imm & 0xff);
3350b57cec5SDimitry Andric     MIBHI.addImm((Imm >> 8) & 0xff);
3360b57cec5SDimitry Andric     break;
3370b57cec5SDimitry Andric   }
3380b57cec5SDimitry Andric   default:
3390b57cec5SDimitry Andric     llvm_unreachable("Unknown operand type!");
3400b57cec5SDimitry Andric   }
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric   if (ImpIsDead)
3430b57cec5SDimitry Andric     MIBHI->getOperand(3).setIsDead();
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric   // SREG is always implicitly killed
3460b57cec5SDimitry Andric   MIBHI->getOperand(4).setIsKill();
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric   MI.eraseFromParent();
3490b57cec5SDimitry Andric   return true;
3500b57cec5SDimitry Andric }
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)3530b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::SBCWRdRr>(Block &MBB, BlockIt MBBI) {
3540b57cec5SDimitry Andric   return expandArith(AVR::SBCRdRr, AVR::SBCRdRr, MBB, MBBI);
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)3580b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::SBCIWRdK>(Block &MBB, BlockIt MBBI) {
3590b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
3605ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
3615ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
3620b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
3630b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
3640b57cec5SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
3650b57cec5SDimitry Andric   unsigned Imm = MI.getOperand(2).getImm();
3660b57cec5SDimitry Andric   unsigned Lo8 = Imm & 0xff;
3670b57cec5SDimitry Andric   unsigned Hi8 = (Imm >> 8) & 0xff;
3685ffd83dbSDimitry Andric   unsigned OpLo = AVR::SBCIRdK;
3695ffd83dbSDimitry Andric   unsigned OpHi = AVR::SBCIRdK;
3700b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
3710b57cec5SDimitry Andric 
372349cc55cSDimitry Andric   auto MIBLO =
373349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpLo)
3740b57cec5SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
3750b57cec5SDimitry Andric           .addReg(DstLoReg, getKillRegState(SrcIsKill))
3760b57cec5SDimitry Andric           .addImm(Lo8);
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric   // SREG is always implicitly killed
3790b57cec5SDimitry Andric   MIBLO->getOperand(4).setIsKill();
3800b57cec5SDimitry Andric 
381349cc55cSDimitry Andric   auto MIBHI =
382349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpHi)
3830b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
3840b57cec5SDimitry Andric           .addReg(DstHiReg, getKillRegState(SrcIsKill))
3850b57cec5SDimitry Andric           .addImm(Hi8);
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   if (ImpIsDead)
3880b57cec5SDimitry Andric     MIBHI->getOperand(3).setIsDead();
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric   // SREG is always implicitly killed
3910b57cec5SDimitry Andric   MIBHI->getOperand(4).setIsKill();
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   MI.eraseFromParent();
3940b57cec5SDimitry Andric   return true;
3950b57cec5SDimitry Andric }
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)3980b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::ANDWRdRr>(Block &MBB, BlockIt MBBI) {
3990b57cec5SDimitry Andric   return expandLogic(AVR::ANDRdRr, MBB, MBBI);
4000b57cec5SDimitry Andric }
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)4030b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::ANDIWRdK>(Block &MBB, BlockIt MBBI) {
4040b57cec5SDimitry Andric   return expandLogicImm(AVR::ANDIRdK, MBB, MBBI);
4050b57cec5SDimitry Andric }
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)4080b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::ORWRdRr>(Block &MBB, BlockIt MBBI) {
4090b57cec5SDimitry Andric   return expandLogic(AVR::ORRdRr, MBB, MBBI);
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)4130b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::ORIWRdK>(Block &MBB, BlockIt MBBI) {
4140b57cec5SDimitry Andric   return expandLogicImm(AVR::ORIRdK, MBB, MBBI);
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)4180b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::EORWRdRr>(Block &MBB, BlockIt MBBI) {
4190b57cec5SDimitry Andric   return expandLogic(AVR::EORRdRr, MBB, MBBI);
4200b57cec5SDimitry Andric }
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)4230b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::COMWRd>(Block &MBB, BlockIt MBBI) {
4240b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
4255ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
4265ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
4270b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
4280b57cec5SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
4290b57cec5SDimitry Andric   bool ImpIsDead = MI.getOperand(2).isDead();
4305ffd83dbSDimitry Andric   unsigned OpLo = AVR::COMRd;
4315ffd83dbSDimitry Andric   unsigned OpHi = AVR::COMRd;
4320b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
4330b57cec5SDimitry Andric 
434349cc55cSDimitry Andric   auto MIBLO =
435349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpLo)
4360b57cec5SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
4370b57cec5SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill));
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   // SREG is always implicitly dead
4400b57cec5SDimitry Andric   MIBLO->getOperand(2).setIsDead();
4410b57cec5SDimitry Andric 
442349cc55cSDimitry Andric   auto MIBHI =
443349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpHi)
4440b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
4450b57cec5SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill));
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric   if (ImpIsDead)
4480b57cec5SDimitry Andric     MIBHI->getOperand(2).setIsDead();
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric   MI.eraseFromParent();
4510b57cec5SDimitry Andric   return true;
4520b57cec5SDimitry Andric }
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)455e8d8bef9SDimitry Andric bool AVRExpandPseudo::expand<AVR::NEGWRd>(Block &MBB, BlockIt MBBI) {
456e8d8bef9SDimitry Andric   MachineInstr &MI = *MBBI;
457e8d8bef9SDimitry Andric   Register DstLoReg, DstHiReg;
458e8d8bef9SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
459bdd1243dSDimitry Andric   Register ZeroReg = MI.getOperand(2).getReg();
460e8d8bef9SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
461e8d8bef9SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
462e8d8bef9SDimitry Andric   bool ImpIsDead = MI.getOperand(2).isDead();
463e8d8bef9SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
464e8d8bef9SDimitry Andric 
465e8d8bef9SDimitry Andric   // Do NEG on the upper byte.
466e8d8bef9SDimitry Andric   auto MIBHI =
467e8d8bef9SDimitry Andric       buildMI(MBB, MBBI, AVR::NEGRd)
468e8d8bef9SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
46981ad6265SDimitry Andric           .addReg(DstHiReg, RegState::Kill);
470e8d8bef9SDimitry Andric   // SREG is always implicitly dead
471e8d8bef9SDimitry Andric   MIBHI->getOperand(2).setIsDead();
472e8d8bef9SDimitry Andric 
473e8d8bef9SDimitry Andric   // Do NEG on the lower byte.
474e8d8bef9SDimitry Andric   buildMI(MBB, MBBI, AVR::NEGRd)
475e8d8bef9SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
476e8d8bef9SDimitry Andric       .addReg(DstLoReg, getKillRegState(DstIsKill));
477e8d8bef9SDimitry Andric 
478fe6060f1SDimitry Andric   // Do an extra SBC.
479e8d8bef9SDimitry Andric   auto MISBCI =
480fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::SBCRdRr)
481e8d8bef9SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
482e8d8bef9SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill))
483bdd1243dSDimitry Andric           .addReg(ZeroReg);
484e8d8bef9SDimitry Andric   if (ImpIsDead)
485e8d8bef9SDimitry Andric     MISBCI->getOperand(3).setIsDead();
486e8d8bef9SDimitry Andric   // SREG is always implicitly killed
487e8d8bef9SDimitry Andric   MISBCI->getOperand(4).setIsKill();
488e8d8bef9SDimitry Andric 
489e8d8bef9SDimitry Andric   MI.eraseFromParent();
490e8d8bef9SDimitry Andric   return true;
491e8d8bef9SDimitry Andric }
492e8d8bef9SDimitry Andric 
493e8d8bef9SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)4940b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::CPWRdRr>(Block &MBB, BlockIt MBBI) {
4950b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
4965ffd83dbSDimitry Andric   Register SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
4975ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
4985ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
4990b57cec5SDimitry Andric   bool DstIsKill = MI.getOperand(0).isKill();
5000b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
5010b57cec5SDimitry Andric   bool ImpIsDead = MI.getOperand(2).isDead();
5025ffd83dbSDimitry Andric   unsigned OpLo = AVR::CPRdRr;
5035ffd83dbSDimitry Andric   unsigned OpHi = AVR::CPCRdRr;
5040b57cec5SDimitry Andric   TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
5050b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric   // Low part
5080b57cec5SDimitry Andric   buildMI(MBB, MBBI, OpLo)
5090b57cec5SDimitry Andric       .addReg(DstLoReg, getKillRegState(DstIsKill))
5100b57cec5SDimitry Andric       .addReg(SrcLoReg, getKillRegState(SrcIsKill));
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   auto MIBHI = buildMI(MBB, MBBI, OpHi)
5130b57cec5SDimitry Andric                    .addReg(DstHiReg, getKillRegState(DstIsKill))
5140b57cec5SDimitry Andric                    .addReg(SrcHiReg, getKillRegState(SrcIsKill));
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric   if (ImpIsDead)
5170b57cec5SDimitry Andric     MIBHI->getOperand(2).setIsDead();
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric   // SREG is always implicitly killed
5200b57cec5SDimitry Andric   MIBHI->getOperand(3).setIsKill();
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric   MI.eraseFromParent();
5230b57cec5SDimitry Andric   return true;
5240b57cec5SDimitry Andric }
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)5270b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::CPCWRdRr>(Block &MBB, BlockIt MBBI) {
5280b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
5295ffd83dbSDimitry Andric   Register SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
5305ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
5315ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
5320b57cec5SDimitry Andric   bool DstIsKill = MI.getOperand(0).isKill();
5330b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
5340b57cec5SDimitry Andric   bool ImpIsDead = MI.getOperand(2).isDead();
5355ffd83dbSDimitry Andric   unsigned OpLo = AVR::CPCRdRr;
5365ffd83dbSDimitry Andric   unsigned OpHi = AVR::CPCRdRr;
5370b57cec5SDimitry Andric   TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
5380b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
5390b57cec5SDimitry Andric 
5400b57cec5SDimitry Andric   auto MIBLO = buildMI(MBB, MBBI, OpLo)
5410b57cec5SDimitry Andric                    .addReg(DstLoReg, getKillRegState(DstIsKill))
5420b57cec5SDimitry Andric                    .addReg(SrcLoReg, getKillRegState(SrcIsKill));
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric   // SREG is always implicitly killed
5450b57cec5SDimitry Andric   MIBLO->getOperand(3).setIsKill();
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric   auto MIBHI = buildMI(MBB, MBBI, OpHi)
5480b57cec5SDimitry Andric                    .addReg(DstHiReg, getKillRegState(DstIsKill))
5490b57cec5SDimitry Andric                    .addReg(SrcHiReg, getKillRegState(SrcIsKill));
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric   if (ImpIsDead)
5520b57cec5SDimitry Andric     MIBHI->getOperand(2).setIsDead();
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric   // SREG is always implicitly killed
5550b57cec5SDimitry Andric   MIBHI->getOperand(3).setIsKill();
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   MI.eraseFromParent();
5580b57cec5SDimitry Andric   return true;
5590b57cec5SDimitry Andric }
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)5620b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::LDIWRdK>(Block &MBB, BlockIt MBBI) {
5630b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
5645ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
5655ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
5660b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
5675ffd83dbSDimitry Andric   unsigned OpLo = AVR::LDIRdK;
5685ffd83dbSDimitry Andric   unsigned OpHi = AVR::LDIRdK;
5690b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
5700b57cec5SDimitry Andric 
571349cc55cSDimitry Andric   auto MIBLO =
572349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpLo)
5730b57cec5SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead));
5740b57cec5SDimitry Andric 
575349cc55cSDimitry Andric   auto MIBHI =
576349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpHi)
5770b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead));
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric   switch (MI.getOperand(1).getType()) {
5800b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress: {
5810b57cec5SDimitry Andric     const GlobalValue *GV = MI.getOperand(1).getGlobal();
5820b57cec5SDimitry Andric     int64_t Offs = MI.getOperand(1).getOffset();
5830b57cec5SDimitry Andric     unsigned TF = MI.getOperand(1).getTargetFlags();
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric     MIBLO.addGlobalAddress(GV, Offs, TF | AVRII::MO_LO);
5860b57cec5SDimitry Andric     MIBHI.addGlobalAddress(GV, Offs, TF | AVRII::MO_HI);
5870b57cec5SDimitry Andric     break;
5880b57cec5SDimitry Andric   }
5890b57cec5SDimitry Andric   case MachineOperand::MO_BlockAddress: {
5900b57cec5SDimitry Andric     const BlockAddress *BA = MI.getOperand(1).getBlockAddress();
5910b57cec5SDimitry Andric     unsigned TF = MI.getOperand(1).getTargetFlags();
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric     MIBLO.add(MachineOperand::CreateBA(BA, TF | AVRII::MO_LO));
5940b57cec5SDimitry Andric     MIBHI.add(MachineOperand::CreateBA(BA, TF | AVRII::MO_HI));
5950b57cec5SDimitry Andric     break;
5960b57cec5SDimitry Andric   }
5970b57cec5SDimitry Andric   case MachineOperand::MO_Immediate: {
5980b57cec5SDimitry Andric     unsigned Imm = MI.getOperand(1).getImm();
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric     MIBLO.addImm(Imm & 0xff);
6010b57cec5SDimitry Andric     MIBHI.addImm((Imm >> 8) & 0xff);
6020b57cec5SDimitry Andric     break;
6030b57cec5SDimitry Andric   }
6040b57cec5SDimitry Andric   default:
6050b57cec5SDimitry Andric     llvm_unreachable("Unknown operand type!");
6060b57cec5SDimitry Andric   }
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric   MI.eraseFromParent();
6090b57cec5SDimitry Andric   return true;
6100b57cec5SDimitry Andric }
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)6130b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::LDSWRdK>(Block &MBB, BlockIt MBBI) {
6140b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
6155ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
6165ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
6170b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
6185ffd83dbSDimitry Andric   unsigned OpLo = AVR::LDSRdK;
6195ffd83dbSDimitry Andric   unsigned OpHi = AVR::LDSRdK;
6200b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
6210b57cec5SDimitry Andric 
622349cc55cSDimitry Andric   auto MIBLO =
623349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpLo)
6240b57cec5SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead));
6250b57cec5SDimitry Andric 
626349cc55cSDimitry Andric   auto MIBHI =
627349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpHi)
6280b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead));
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric   switch (MI.getOperand(1).getType()) {
6310b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress: {
6320b57cec5SDimitry Andric     const GlobalValue *GV = MI.getOperand(1).getGlobal();
6330b57cec5SDimitry Andric     int64_t Offs = MI.getOperand(1).getOffset();
6340b57cec5SDimitry Andric     unsigned TF = MI.getOperand(1).getTargetFlags();
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric     MIBLO.addGlobalAddress(GV, Offs, TF);
6370b57cec5SDimitry Andric     MIBHI.addGlobalAddress(GV, Offs + 1, TF);
6380b57cec5SDimitry Andric     break;
6390b57cec5SDimitry Andric   }
6400b57cec5SDimitry Andric   case MachineOperand::MO_Immediate: {
6410b57cec5SDimitry Andric     unsigned Imm = MI.getOperand(1).getImm();
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric     MIBLO.addImm(Imm);
6440b57cec5SDimitry Andric     MIBHI.addImm(Imm + 1);
6450b57cec5SDimitry Andric     break;
6460b57cec5SDimitry Andric   }
6470b57cec5SDimitry Andric   default:
6480b57cec5SDimitry Andric     llvm_unreachable("Unknown operand type!");
6490b57cec5SDimitry Andric   }
6500b57cec5SDimitry Andric 
6510b57cec5SDimitry Andric   MIBLO.setMemRefs(MI.memoperands());
6520b57cec5SDimitry Andric   MIBHI.setMemRefs(MI.memoperands());
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric   MI.eraseFromParent();
6550b57cec5SDimitry Andric   return true;
6560b57cec5SDimitry Andric }
6570b57cec5SDimitry Andric 
6580b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)6590b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::LDWRdPtr>(Block &MBB, BlockIt MBBI) {
6600b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
6615ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
6625ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
663bdd1243dSDimitry Andric   bool DstIsKill = MI.getOperand(0).isKill();
6640b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
665bdd1243dSDimitry Andric   const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
666bdd1243dSDimitry Andric 
667bdd1243dSDimitry Andric   // DstReg has an earlyclobber so the register allocator will allocate them in
668bdd1243dSDimitry Andric   // separate registers.
669bdd1243dSDimitry Andric   assert(DstReg != SrcReg && "Dst and Src registers are the same!");
670bdd1243dSDimitry Andric 
671bdd1243dSDimitry Andric   if (STI.hasTinyEncoding()) {
672bdd1243dSDimitry Andric     // Handle this case in the expansion of LDDWRdPtrQ because it is very
673bdd1243dSDimitry Andric     // similar.
674bdd1243dSDimitry Andric     buildMI(MBB, MBBI, AVR::LDDWRdPtrQ)
675bdd1243dSDimitry Andric         .addDef(DstReg, getKillRegState(DstIsKill))
676bdd1243dSDimitry Andric         .addReg(SrcReg, getKillRegState(SrcIsKill))
677bdd1243dSDimitry Andric         .addImm(0)
678bdd1243dSDimitry Andric         .setMemRefs(MI.memoperands());
679bdd1243dSDimitry Andric 
680bdd1243dSDimitry Andric   } else {
681bdd1243dSDimitry Andric     Register DstLoReg, DstHiReg;
6820b57cec5SDimitry Andric     TRI->splitReg(DstReg, DstLoReg, DstHiReg);
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric     // Load low byte.
685bdd1243dSDimitry Andric     buildMI(MBB, MBBI, AVR::LDRdPtr)
686bdd1243dSDimitry Andric         .addReg(DstLoReg, RegState::Define)
687bdd1243dSDimitry Andric         .addReg(SrcReg)
688bdd1243dSDimitry Andric         .setMemRefs(MI.memoperands());
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric     // Load high byte.
691bdd1243dSDimitry Andric     buildMI(MBB, MBBI, AVR::LDDRdPtrQ)
692bdd1243dSDimitry Andric         .addReg(DstHiReg, RegState::Define)
6930b57cec5SDimitry Andric         .addReg(SrcReg, getKillRegState(SrcIsKill))
694bdd1243dSDimitry Andric         .addImm(1)
695bdd1243dSDimitry Andric         .setMemRefs(MI.memoperands());
6960b57cec5SDimitry Andric   }
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric   MI.eraseFromParent();
6990b57cec5SDimitry Andric   return true;
7000b57cec5SDimitry Andric }
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)7030b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::LDWRdPtrPi>(Block &MBB, BlockIt MBBI) {
7040b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
7055ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
7065ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
7075ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
7080b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
7090b57cec5SDimitry Andric   bool SrcIsDead = MI.getOperand(1).isKill();
7105ffd83dbSDimitry Andric   unsigned OpLo = AVR::LDRdPtrPi;
7115ffd83dbSDimitry Andric   unsigned OpHi = AVR::LDRdPtrPi;
7120b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric   assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
7150b57cec5SDimitry Andric 
716349cc55cSDimitry Andric   auto MIBLO =
717349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpLo)
7180b57cec5SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
7190b57cec5SDimitry Andric           .addReg(SrcReg, RegState::Define)
7200b57cec5SDimitry Andric           .addReg(SrcReg, RegState::Kill);
7210b57cec5SDimitry Andric 
722349cc55cSDimitry Andric   auto MIBHI =
723349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpHi)
7240b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
7250b57cec5SDimitry Andric           .addReg(SrcReg, RegState::Define | getDeadRegState(SrcIsDead))
7260b57cec5SDimitry Andric           .addReg(SrcReg, RegState::Kill);
7270b57cec5SDimitry Andric 
7280b57cec5SDimitry Andric   MIBLO.setMemRefs(MI.memoperands());
7290b57cec5SDimitry Andric   MIBHI.setMemRefs(MI.memoperands());
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric   MI.eraseFromParent();
7320b57cec5SDimitry Andric   return true;
7330b57cec5SDimitry Andric }
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)7360b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::LDWRdPtrPd>(Block &MBB, BlockIt MBBI) {
7370b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
7385ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
7395ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
7405ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
7410b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
7420b57cec5SDimitry Andric   bool SrcIsDead = MI.getOperand(1).isKill();
7435ffd83dbSDimitry Andric   unsigned OpLo = AVR::LDRdPtrPd;
7445ffd83dbSDimitry Andric   unsigned OpHi = AVR::LDRdPtrPd;
7450b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric   assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
7480b57cec5SDimitry Andric 
749349cc55cSDimitry Andric   auto MIBHI =
750349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpHi)
7510b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
7520b57cec5SDimitry Andric           .addReg(SrcReg, RegState::Define)
7530b57cec5SDimitry Andric           .addReg(SrcReg, RegState::Kill);
7540b57cec5SDimitry Andric 
755349cc55cSDimitry Andric   auto MIBLO =
756349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpLo)
7570b57cec5SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
7580b57cec5SDimitry Andric           .addReg(SrcReg, RegState::Define | getDeadRegState(SrcIsDead))
7590b57cec5SDimitry Andric           .addReg(SrcReg, RegState::Kill);
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric   MIBLO.setMemRefs(MI.memoperands());
7620b57cec5SDimitry Andric   MIBHI.setMemRefs(MI.memoperands());
7630b57cec5SDimitry Andric 
7640b57cec5SDimitry Andric   MI.eraseFromParent();
7650b57cec5SDimitry Andric   return true;
7660b57cec5SDimitry Andric }
7670b57cec5SDimitry Andric 
7680b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)7690b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
7700b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
7715ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
7725ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
7730b57cec5SDimitry Andric   unsigned Imm = MI.getOperand(2).getImm();
774bdd1243dSDimitry Andric   bool DstIsKill = MI.getOperand(0).isKill();
7750b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
776bdd1243dSDimitry Andric   const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
7770b57cec5SDimitry Andric 
778349cc55cSDimitry Andric   // Since we add 1 to the Imm value for the high byte below, and 63 is the
779349cc55cSDimitry Andric   // highest Imm value allowed for the instruction, 62 is the limit here.
7800b57cec5SDimitry Andric   assert(Imm <= 62 && "Offset is out of range");
7810b57cec5SDimitry Andric 
782bdd1243dSDimitry Andric   // DstReg has an earlyclobber so the register allocator will allocate them in
783bdd1243dSDimitry Andric   // separate registers.
784bdd1243dSDimitry Andric   assert(DstReg != SrcReg && "Dst and Src registers are the same!");
7850b57cec5SDimitry Andric 
786bdd1243dSDimitry Andric   if (STI.hasTinyEncoding()) {
787bdd1243dSDimitry Andric     // Reduced tiny cores don't support load/store with displacement. However,
788bdd1243dSDimitry Andric     // they do support postincrement. So we'll simply adjust the pointer before
789bdd1243dSDimitry Andric     // and after and use postincrement to load multiple registers.
7900b57cec5SDimitry Andric 
791bdd1243dSDimitry Andric     // Add offset. The offset can be 0 when expanding this instruction from the
792bdd1243dSDimitry Andric     // more specific LDWRdPtr instruction.
793bdd1243dSDimitry Andric     if (Imm != 0) {
794bdd1243dSDimitry Andric       buildMI(MBB, MBBI, AVR::SUBIWRdK, SrcReg)
7950b57cec5SDimitry Andric           .addReg(SrcReg)
796bdd1243dSDimitry Andric           .addImm(0x10000 - Imm);
7970b57cec5SDimitry Andric     }
7980b57cec5SDimitry Andric 
799bdd1243dSDimitry Andric     // Do a word load with postincrement. This will be lowered to a two byte
800bdd1243dSDimitry Andric     // load.
801bdd1243dSDimitry Andric     buildMI(MBB, MBBI, AVR::LDWRdPtrPi)
802bdd1243dSDimitry Andric         .addDef(DstReg, getKillRegState(DstIsKill))
803bdd1243dSDimitry Andric         .addReg(SrcReg, getKillRegState(SrcIsKill))
804bdd1243dSDimitry Andric         .addImm(0)
805bdd1243dSDimitry Andric         .setMemRefs(MI.memoperands());
806bdd1243dSDimitry Andric 
807bdd1243dSDimitry Andric     // If the pointer is used after the store instruction, subtract the new
808bdd1243dSDimitry Andric     // offset (with 2 added after the postincrement instructions) so it is the
809bdd1243dSDimitry Andric     // same as before.
810bdd1243dSDimitry Andric     if (!SrcIsKill) {
811bdd1243dSDimitry Andric       buildMI(MBB, MBBI, AVR::SUBIWRdK, SrcReg).addReg(SrcReg).addImm(Imm + 2);
812bdd1243dSDimitry Andric     }
813bdd1243dSDimitry Andric   } else {
814bdd1243dSDimitry Andric     Register DstLoReg, DstHiReg;
815bdd1243dSDimitry Andric     TRI->splitReg(DstReg, DstLoReg, DstHiReg);
816bdd1243dSDimitry Andric 
817bdd1243dSDimitry Andric     // Load low byte.
818bdd1243dSDimitry Andric     buildMI(MBB, MBBI, AVR::LDDRdPtrQ)
819bdd1243dSDimitry Andric         .addReg(DstLoReg, RegState::Define)
820bdd1243dSDimitry Andric         .addReg(SrcReg)
821bdd1243dSDimitry Andric         .addImm(Imm)
822bdd1243dSDimitry Andric         .setMemRefs(MI.memoperands());
823bdd1243dSDimitry Andric 
824bdd1243dSDimitry Andric     // Load high byte.
825bdd1243dSDimitry Andric     buildMI(MBB, MBBI, AVR::LDDRdPtrQ)
826bdd1243dSDimitry Andric         .addReg(DstHiReg, RegState::Define)
827bdd1243dSDimitry Andric         .addReg(SrcReg, getKillRegState(SrcIsKill))
828bdd1243dSDimitry Andric         .addImm(Imm + 1)
829bdd1243dSDimitry Andric         .setMemRefs(MI.memoperands());
830bdd1243dSDimitry Andric   }
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric   MI.eraseFromParent();
8330b57cec5SDimitry Andric   return true;
8340b57cec5SDimitry Andric }
8350b57cec5SDimitry Andric 
expandLPMWELPMW(Block & MBB,BlockIt MBBI,bool IsELPM)836*06c3fb27SDimitry Andric bool AVRExpandPseudo::expandLPMWELPMW(Block &MBB, BlockIt MBBI, bool IsELPM) {
8370b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
8385ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
8395ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
8405ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
841*06c3fb27SDimitry Andric   Register SrcLoReg, SrcHiReg;
8420b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
843*06c3fb27SDimitry Andric   const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
844*06c3fb27SDimitry Andric   bool IsLPMRn = IsELPM ? STI.hasELPMX() : STI.hasLPMX();
845*06c3fb27SDimitry Andric 
8460b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
847*06c3fb27SDimitry Andric   TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
8480b57cec5SDimitry Andric 
84904eeddc0SDimitry Andric   // Set the I/O register RAMPZ for ELPM.
850*06c3fb27SDimitry Andric   if (IsELPM) {
85104eeddc0SDimitry Andric     Register Bank = MI.getOperand(2).getReg();
85204eeddc0SDimitry Andric     // out RAMPZ, rtmp
85304eeddc0SDimitry Andric     buildMI(MBB, MBBI, AVR::OUTARr).addImm(STI.getIORegRAMPZ()).addReg(Bank);
85404eeddc0SDimitry Andric   }
85504eeddc0SDimitry Andric 
856bdd1243dSDimitry Andric   // This is enforced by the @earlyclobber constraint.
857bdd1243dSDimitry Andric   assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
8580b57cec5SDimitry Andric 
859*06c3fb27SDimitry Andric   if (IsLPMRn) {
860*06c3fb27SDimitry Andric     unsigned OpLo = IsELPM ? AVR::ELPMRdZPi : AVR::LPMRdZPi;
861*06c3fb27SDimitry Andric     unsigned OpHi = IsELPM ? AVR::ELPMRdZ : AVR::LPMRdZ;
8620b57cec5SDimitry Andric     // Load low byte.
8630b57cec5SDimitry Andric     auto MIBLO = buildMI(MBB, MBBI, OpLo)
864bdd1243dSDimitry Andric                      .addReg(DstLoReg, RegState::Define)
8650b57cec5SDimitry Andric                      .addReg(SrcReg);
8660b57cec5SDimitry Andric     // Load high byte.
8670b57cec5SDimitry Andric     auto MIBHI = buildMI(MBB, MBBI, OpHi)
868bdd1243dSDimitry Andric                      .addReg(DstHiReg, RegState::Define)
8690b57cec5SDimitry Andric                      .addReg(SrcReg, getKillRegState(SrcIsKill));
8700b57cec5SDimitry Andric     MIBLO.setMemRefs(MI.memoperands());
8710b57cec5SDimitry Andric     MIBHI.setMemRefs(MI.memoperands());
872*06c3fb27SDimitry Andric   } else {
873*06c3fb27SDimitry Andric     unsigned Opc = IsELPM ? AVR::ELPM : AVR::LPM;
874*06c3fb27SDimitry Andric     // Load low byte, and copy to the low destination register.
875*06c3fb27SDimitry Andric     auto MIBLO = buildMI(MBB, MBBI, Opc);
876*06c3fb27SDimitry Andric     buildMI(MBB, MBBI, AVR::MOVRdRr)
877*06c3fb27SDimitry Andric         .addReg(DstLoReg, RegState::Define)
878*06c3fb27SDimitry Andric         .addReg(AVR::R0, RegState::Kill);
879*06c3fb27SDimitry Andric     MIBLO.setMemRefs(MI.memoperands());
880*06c3fb27SDimitry Andric     // Increase the Z register by 1.
881*06c3fb27SDimitry Andric     if (STI.hasADDSUBIW()) {
882*06c3fb27SDimitry Andric       // adiw r31:r30, 1
883*06c3fb27SDimitry Andric       auto MIINC = buildMI(MBB, MBBI, AVR::ADIWRdK)
884*06c3fb27SDimitry Andric                        .addReg(SrcReg, RegState::Define)
885*06c3fb27SDimitry Andric                        .addReg(SrcReg, getKillRegState(SrcIsKill))
886*06c3fb27SDimitry Andric                        .addImm(1);
887*06c3fb27SDimitry Andric       MIINC->getOperand(3).setIsDead();
888*06c3fb27SDimitry Andric     } else {
889*06c3fb27SDimitry Andric       // subi r30, 255
890*06c3fb27SDimitry Andric       // sbci r31, 255
891*06c3fb27SDimitry Andric       buildMI(MBB, MBBI, AVR::SUBIRdK)
892*06c3fb27SDimitry Andric           .addReg(SrcLoReg, RegState::Define)
893*06c3fb27SDimitry Andric           .addReg(SrcLoReg, getKillRegState(SrcIsKill))
894*06c3fb27SDimitry Andric           .addImm(255);
895*06c3fb27SDimitry Andric       auto MIZHI = buildMI(MBB, MBBI, AVR::SBCIRdK)
896*06c3fb27SDimitry Andric                        .addReg(SrcHiReg, RegState::Define)
897*06c3fb27SDimitry Andric                        .addReg(SrcHiReg, getKillRegState(SrcIsKill))
898*06c3fb27SDimitry Andric                        .addImm(255);
899*06c3fb27SDimitry Andric       MIZHI->getOperand(3).setIsDead();
900*06c3fb27SDimitry Andric       MIZHI->getOperand(4).setIsKill();
901*06c3fb27SDimitry Andric     }
902*06c3fb27SDimitry Andric     // Load high byte, and copy to the high destination register.
903*06c3fb27SDimitry Andric     auto MIBHI = buildMI(MBB, MBBI, Opc);
904*06c3fb27SDimitry Andric     buildMI(MBB, MBBI, AVR::MOVRdRr)
905*06c3fb27SDimitry Andric         .addReg(DstHiReg, RegState::Define)
906*06c3fb27SDimitry Andric         .addReg(AVR::R0, RegState::Kill);
907*06c3fb27SDimitry Andric     MIBHI.setMemRefs(MI.memoperands());
908*06c3fb27SDimitry Andric   }
909*06c3fb27SDimitry Andric 
910*06c3fb27SDimitry Andric   // Restore the Z register if it is not killed.
911*06c3fb27SDimitry Andric   if (!SrcIsKill) {
912*06c3fb27SDimitry Andric     if (STI.hasADDSUBIW()) {
913*06c3fb27SDimitry Andric       // sbiw r31:r30, 1
914*06c3fb27SDimitry Andric       auto MIDEC = buildMI(MBB, MBBI, AVR::SBIWRdK)
915*06c3fb27SDimitry Andric                        .addReg(SrcReg, RegState::Define)
916*06c3fb27SDimitry Andric                        .addReg(SrcReg, getKillRegState(SrcIsKill))
917*06c3fb27SDimitry Andric                        .addImm(1);
918*06c3fb27SDimitry Andric       MIDEC->getOperand(3).setIsDead();
919*06c3fb27SDimitry Andric     } else {
920*06c3fb27SDimitry Andric       // subi r30, 1
921*06c3fb27SDimitry Andric       // sbci r31, 0
922*06c3fb27SDimitry Andric       buildMI(MBB, MBBI, AVR::SUBIRdK)
923*06c3fb27SDimitry Andric           .addReg(SrcLoReg, RegState::Define)
924*06c3fb27SDimitry Andric           .addReg(SrcLoReg, getKillRegState(SrcIsKill))
925*06c3fb27SDimitry Andric           .addImm(1);
926*06c3fb27SDimitry Andric       auto MIZHI = buildMI(MBB, MBBI, AVR::SBCIRdK)
927*06c3fb27SDimitry Andric                        .addReg(SrcHiReg, RegState::Define)
928*06c3fb27SDimitry Andric                        .addReg(SrcHiReg, getKillRegState(SrcIsKill))
929*06c3fb27SDimitry Andric                        .addImm(0);
930*06c3fb27SDimitry Andric       MIZHI->getOperand(3).setIsDead();
931*06c3fb27SDimitry Andric       MIZHI->getOperand(4).setIsKill();
932*06c3fb27SDimitry Andric     }
933*06c3fb27SDimitry Andric   }
9340b57cec5SDimitry Andric 
9350b57cec5SDimitry Andric   MI.eraseFromParent();
9360b57cec5SDimitry Andric   return true;
9370b57cec5SDimitry Andric }
9380b57cec5SDimitry Andric 
9390b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)94004eeddc0SDimitry Andric bool AVRExpandPseudo::expand<AVR::LPMWRdZ>(Block &MBB, BlockIt MBBI) {
94104eeddc0SDimitry Andric   return expandLPMWELPMW(MBB, MBBI, false);
94204eeddc0SDimitry Andric }
94304eeddc0SDimitry Andric 
94404eeddc0SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)94504eeddc0SDimitry Andric bool AVRExpandPseudo::expand<AVR::ELPMWRdZ>(Block &MBB, BlockIt MBBI) {
94604eeddc0SDimitry Andric   return expandLPMWELPMW(MBB, MBBI, true);
94704eeddc0SDimitry Andric }
94804eeddc0SDimitry Andric 
expandLPMBELPMB(Block & MBB,BlockIt MBBI,bool IsELPM)949*06c3fb27SDimitry Andric bool AVRExpandPseudo::expandLPMBELPMB(Block &MBB, BlockIt MBBI, bool IsELPM) {
95004eeddc0SDimitry Andric   MachineInstr &MI = *MBBI;
95104eeddc0SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
95204eeddc0SDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
95304eeddc0SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
95404eeddc0SDimitry Andric   const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
955*06c3fb27SDimitry Andric   bool IsLPMRn = IsELPM ? STI.hasELPMX() : STI.hasLPMX();
95604eeddc0SDimitry Andric 
95704eeddc0SDimitry Andric   // Set the I/O register RAMPZ for ELPM (out RAMPZ, rtmp).
958*06c3fb27SDimitry Andric   if (IsELPM) {
959*06c3fb27SDimitry Andric     Register BankReg = MI.getOperand(2).getReg();
96004eeddc0SDimitry Andric     buildMI(MBB, MBBI, AVR::OUTARr).addImm(STI.getIORegRAMPZ()).addReg(BankReg);
961*06c3fb27SDimitry Andric   }
96204eeddc0SDimitry Andric 
96304eeddc0SDimitry Andric   // Load byte.
964*06c3fb27SDimitry Andric   if (IsLPMRn) {
965*06c3fb27SDimitry Andric     unsigned Opc = IsELPM ? AVR::ELPMRdZ : AVR::LPMRdZ;
966*06c3fb27SDimitry Andric     auto MILB = buildMI(MBB, MBBI, Opc)
96704eeddc0SDimitry Andric                     .addReg(DstReg, RegState::Define)
96804eeddc0SDimitry Andric                     .addReg(SrcReg, getKillRegState(SrcIsKill));
96904eeddc0SDimitry Andric     MILB.setMemRefs(MI.memoperands());
970*06c3fb27SDimitry Andric   } else {
971*06c3fb27SDimitry Andric     // For the basic ELPM/LPM instruction, its operand[0] is the implicit
972*06c3fb27SDimitry Andric     // 'Z' register, and its operand[1] is the implicit 'R0' register.
973*06c3fb27SDimitry Andric     unsigned Opc = IsELPM ? AVR::ELPM : AVR::LPM;
974*06c3fb27SDimitry Andric     auto MILB = buildMI(MBB, MBBI, Opc);
975*06c3fb27SDimitry Andric     buildMI(MBB, MBBI, AVR::MOVRdRr)
976*06c3fb27SDimitry Andric         .addReg(DstReg, RegState::Define)
977*06c3fb27SDimitry Andric         .addReg(AVR::R0, RegState::Kill);
978*06c3fb27SDimitry Andric     MILB.setMemRefs(MI.memoperands());
979*06c3fb27SDimitry Andric   }
98004eeddc0SDimitry Andric 
98104eeddc0SDimitry Andric   MI.eraseFromParent();
98204eeddc0SDimitry Andric   return true;
98304eeddc0SDimitry Andric }
98404eeddc0SDimitry Andric 
98504eeddc0SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)986*06c3fb27SDimitry Andric bool AVRExpandPseudo::expand<AVR::ELPMBRdZ>(Block &MBB, BlockIt MBBI) {
987*06c3fb27SDimitry Andric   return expandLPMBELPMB(MBB, MBBI, true);
988*06c3fb27SDimitry Andric }
989*06c3fb27SDimitry Andric 
990*06c3fb27SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)991*06c3fb27SDimitry Andric bool AVRExpandPseudo::expand<AVR::LPMBRdZ>(Block &MBB, BlockIt MBBI) {
992*06c3fb27SDimitry Andric   return expandLPMBELPMB(MBB, MBBI, false);
993*06c3fb27SDimitry Andric }
994*06c3fb27SDimitry Andric 
995*06c3fb27SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)9960b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::LPMWRdZPi>(Block &MBB, BlockIt MBBI) {
99704eeddc0SDimitry Andric   llvm_unreachable("16-bit LPMPi is unimplemented");
99804eeddc0SDimitry Andric }
99904eeddc0SDimitry Andric 
100004eeddc0SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)100104eeddc0SDimitry Andric bool AVRExpandPseudo::expand<AVR::ELPMBRdZPi>(Block &MBB, BlockIt MBBI) {
1002bdd1243dSDimitry Andric   llvm_unreachable("8-bit ELPMPi is unimplemented");
100304eeddc0SDimitry Andric }
100404eeddc0SDimitry Andric 
100504eeddc0SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)100604eeddc0SDimitry Andric bool AVRExpandPseudo::expand<AVR::ELPMWRdZPi>(Block &MBB, BlockIt MBBI) {
100704eeddc0SDimitry Andric   llvm_unreachable("16-bit ELPMPi is unimplemented");
10080b57cec5SDimitry Andric }
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric template <typename Func>
expandAtomic(Block & MBB,BlockIt MBBI,Func f)10110b57cec5SDimitry Andric bool AVRExpandPseudo::expandAtomic(Block &MBB, BlockIt MBBI, Func f) {
10120b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
101381ad6265SDimitry Andric   const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric   // Store the SREG.
10160b57cec5SDimitry Andric   buildMI(MBB, MBBI, AVR::INRdA)
1017bdd1243dSDimitry Andric       .addReg(STI.getTmpRegister(), RegState::Define)
101881ad6265SDimitry Andric       .addImm(STI.getIORegSREG());
10190b57cec5SDimitry Andric 
10200b57cec5SDimitry Andric   // Disable exceptions.
10210b57cec5SDimitry Andric   buildMI(MBB, MBBI, AVR::BCLRs).addImm(7); // CLI
10220b57cec5SDimitry Andric 
10230b57cec5SDimitry Andric   f(MI);
10240b57cec5SDimitry Andric 
10250b57cec5SDimitry Andric   // Restore the status reg.
102681ad6265SDimitry Andric   buildMI(MBB, MBBI, AVR::OUTARr)
102781ad6265SDimitry Andric       .addImm(STI.getIORegSREG())
1028bdd1243dSDimitry Andric       .addReg(STI.getTmpRegister());
10290b57cec5SDimitry Andric 
10300b57cec5SDimitry Andric   MI.eraseFromParent();
10310b57cec5SDimitry Andric   return true;
10320b57cec5SDimitry Andric }
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric template <typename Func>
expandAtomicBinaryOp(unsigned Opcode,Block & MBB,BlockIt MBBI,Func f)1035349cc55cSDimitry Andric bool AVRExpandPseudo::expandAtomicBinaryOp(unsigned Opcode, Block &MBB,
1036349cc55cSDimitry Andric                                            BlockIt MBBI, Func f) {
10370b57cec5SDimitry Andric   return expandAtomic(MBB, MBBI, [&](MachineInstr &MI) {
10380b57cec5SDimitry Andric     auto Op1 = MI.getOperand(0);
10390b57cec5SDimitry Andric     auto Op2 = MI.getOperand(1);
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric     MachineInstr &NewInst =
10420b57cec5SDimitry Andric         *buildMI(MBB, MBBI, Opcode).add(Op1).add(Op2).getInstr();
10430b57cec5SDimitry Andric     f(NewInst);
10440b57cec5SDimitry Andric   });
10450b57cec5SDimitry Andric }
10460b57cec5SDimitry Andric 
expandAtomicBinaryOp(unsigned Opcode,Block & MBB,BlockIt MBBI)1047349cc55cSDimitry Andric bool AVRExpandPseudo::expandAtomicBinaryOp(unsigned Opcode, Block &MBB,
10480b57cec5SDimitry Andric                                            BlockIt MBBI) {
10490b57cec5SDimitry Andric   return expandAtomicBinaryOp(Opcode, MBB, MBBI, [](MachineInstr &MI) {});
10500b57cec5SDimitry Andric }
10510b57cec5SDimitry Andric 
10520b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)10530b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::AtomicLoad8>(Block &MBB, BlockIt MBBI) {
10540b57cec5SDimitry Andric   return expandAtomicBinaryOp(AVR::LDRdPtr, MBB, MBBI);
10550b57cec5SDimitry Andric }
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)10580b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::AtomicLoad16>(Block &MBB, BlockIt MBBI) {
10590b57cec5SDimitry Andric   return expandAtomicBinaryOp(AVR::LDWRdPtr, MBB, MBBI);
10600b57cec5SDimitry Andric }
10610b57cec5SDimitry Andric 
10620b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)10630b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::AtomicStore8>(Block &MBB, BlockIt MBBI) {
10640b57cec5SDimitry Andric   return expandAtomicBinaryOp(AVR::STPtrRr, MBB, MBBI);
10650b57cec5SDimitry Andric }
10660b57cec5SDimitry Andric 
10670b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)10680b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::AtomicStore16>(Block &MBB, BlockIt MBBI) {
10690b57cec5SDimitry Andric   return expandAtomicBinaryOp(AVR::STWPtrRr, MBB, MBBI);
10700b57cec5SDimitry Andric }
10710b57cec5SDimitry Andric 
10720b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)10730b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::AtomicFence>(Block &MBB, BlockIt MBBI) {
10740b57cec5SDimitry Andric   // On AVR, there is only one core and so atomic fences do nothing.
10750b57cec5SDimitry Andric   MBBI->eraseFromParent();
10760b57cec5SDimitry Andric   return true;
10770b57cec5SDimitry Andric }
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)10800b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::STSWKRr>(Block &MBB, BlockIt MBBI) {
1081*06c3fb27SDimitry Andric   const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
10820b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
10835ffd83dbSDimitry Andric   Register SrcLoReg, SrcHiReg;
10845ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
10850b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
10860b57cec5SDimitry Andric   TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
10870b57cec5SDimitry Andric 
1088*06c3fb27SDimitry Andric   auto MIB0 = buildMI(MBB, MBBI, AVR::STSKRr);
1089*06c3fb27SDimitry Andric   auto MIB1 = buildMI(MBB, MBBI, AVR::STSKRr);
10900b57cec5SDimitry Andric 
10910b57cec5SDimitry Andric   switch (MI.getOperand(0).getType()) {
10920b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress: {
10930b57cec5SDimitry Andric     const GlobalValue *GV = MI.getOperand(0).getGlobal();
10940b57cec5SDimitry Andric     int64_t Offs = MI.getOperand(0).getOffset();
10950b57cec5SDimitry Andric     unsigned TF = MI.getOperand(0).getTargetFlags();
10960b57cec5SDimitry Andric 
1097*06c3fb27SDimitry Andric     if (STI.hasLowByteFirst()) {
1098*06c3fb27SDimitry Andric       // Write the low byte first for XMEGA devices.
1099*06c3fb27SDimitry Andric       MIB0.addGlobalAddress(GV, Offs, TF);
1100*06c3fb27SDimitry Andric       MIB1.addGlobalAddress(GV, Offs + 1, TF);
1101*06c3fb27SDimitry Andric     } else {
1102*06c3fb27SDimitry Andric       // Write the high byte first for traditional devices.
1103*06c3fb27SDimitry Andric       MIB0.addGlobalAddress(GV, Offs + 1, TF);
1104*06c3fb27SDimitry Andric       MIB1.addGlobalAddress(GV, Offs, TF);
1105*06c3fb27SDimitry Andric     }
1106*06c3fb27SDimitry Andric 
11070b57cec5SDimitry Andric     break;
11080b57cec5SDimitry Andric   }
11090b57cec5SDimitry Andric   case MachineOperand::MO_Immediate: {
11100b57cec5SDimitry Andric     unsigned Imm = MI.getOperand(0).getImm();
11110b57cec5SDimitry Andric 
1112*06c3fb27SDimitry Andric     if (STI.hasLowByteFirst()) {
1113*06c3fb27SDimitry Andric       // Write the low byte first for XMEGA devices.
1114*06c3fb27SDimitry Andric       MIB0.addImm(Imm);
1115*06c3fb27SDimitry Andric       MIB1.addImm(Imm + 1);
1116*06c3fb27SDimitry Andric     } else {
1117*06c3fb27SDimitry Andric       // Write the high byte first for traditional devices.
1118*06c3fb27SDimitry Andric       MIB0.addImm(Imm + 1);
1119*06c3fb27SDimitry Andric       MIB1.addImm(Imm);
1120*06c3fb27SDimitry Andric     }
1121*06c3fb27SDimitry Andric 
11220b57cec5SDimitry Andric     break;
11230b57cec5SDimitry Andric   }
11240b57cec5SDimitry Andric   default:
11250b57cec5SDimitry Andric     llvm_unreachable("Unknown operand type!");
11260b57cec5SDimitry Andric   }
11270b57cec5SDimitry Andric 
1128*06c3fb27SDimitry Andric   if (STI.hasLowByteFirst()) {
1129*06c3fb27SDimitry Andric     // Write the low byte first for XMEGA devices.
1130*06c3fb27SDimitry Andric     MIB0.addReg(SrcLoReg, getKillRegState(SrcIsKill))
1131*06c3fb27SDimitry Andric         .setMemRefs(MI.memoperands());
1132*06c3fb27SDimitry Andric     MIB1.addReg(SrcHiReg, getKillRegState(SrcIsKill))
1133*06c3fb27SDimitry Andric         .setMemRefs(MI.memoperands());
1134*06c3fb27SDimitry Andric   } else {
1135*06c3fb27SDimitry Andric     // Write the high byte first for traditional devices.
1136*06c3fb27SDimitry Andric     MIB0.addReg(SrcHiReg, getKillRegState(SrcIsKill))
1137*06c3fb27SDimitry Andric         .setMemRefs(MI.memoperands());
1138*06c3fb27SDimitry Andric     MIB1.addReg(SrcLoReg, getKillRegState(SrcIsKill))
1139*06c3fb27SDimitry Andric         .setMemRefs(MI.memoperands());
1140*06c3fb27SDimitry Andric   }
11410b57cec5SDimitry Andric 
11420b57cec5SDimitry Andric   MI.eraseFromParent();
11430b57cec5SDimitry Andric   return true;
11440b57cec5SDimitry Andric }
11450b57cec5SDimitry Andric 
11460b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)11470b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::STWPtrRr>(Block &MBB, BlockIt MBBI) {
11480b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
11495ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
11505ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
1151bdd1243dSDimitry Andric   bool DstIsKill = MI.getOperand(0).isKill();
1152fe6060f1SDimitry Andric   bool DstIsUndef = MI.getOperand(0).isUndef();
11530b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
1154bdd1243dSDimitry Andric   const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric   //: TODO: need to reverse this order like inw and stsw?
11570b57cec5SDimitry Andric 
1158bdd1243dSDimitry Andric   if (STI.hasTinyEncoding()) {
1159bdd1243dSDimitry Andric     // Handle this case in the expansion of STDWPtrQRr because it is very
1160bdd1243dSDimitry Andric     // similar.
1161bdd1243dSDimitry Andric     buildMI(MBB, MBBI, AVR::STDWPtrQRr)
1162bdd1243dSDimitry Andric         .addReg(DstReg,
1163bdd1243dSDimitry Andric                 getKillRegState(DstIsKill) | getUndefRegState(DstIsUndef))
1164bdd1243dSDimitry Andric         .addImm(0)
1165bdd1243dSDimitry Andric         .addReg(SrcReg, getKillRegState(SrcIsKill))
1166bdd1243dSDimitry Andric         .setMemRefs(MI.memoperands());
1167bdd1243dSDimitry Andric 
1168bdd1243dSDimitry Andric   } else {
1169bdd1243dSDimitry Andric     Register SrcLoReg, SrcHiReg;
1170bdd1243dSDimitry Andric     TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
1171*06c3fb27SDimitry Andric     if (STI.hasLowByteFirst()) {
1172bdd1243dSDimitry Andric       buildMI(MBB, MBBI, AVR::STPtrRr)
1173bdd1243dSDimitry Andric           .addReg(DstReg, getUndefRegState(DstIsUndef))
1174bdd1243dSDimitry Andric           .addReg(SrcLoReg, getKillRegState(SrcIsKill))
1175bdd1243dSDimitry Andric           .setMemRefs(MI.memoperands());
1176bdd1243dSDimitry Andric       buildMI(MBB, MBBI, AVR::STDPtrQRr)
1177fe6060f1SDimitry Andric           .addReg(DstReg, getUndefRegState(DstIsUndef))
11780b57cec5SDimitry Andric           .addImm(1)
1179bdd1243dSDimitry Andric           .addReg(SrcHiReg, getKillRegState(SrcIsKill))
1180bdd1243dSDimitry Andric           .setMemRefs(MI.memoperands());
1181*06c3fb27SDimitry Andric     } else {
1182*06c3fb27SDimitry Andric       buildMI(MBB, MBBI, AVR::STDPtrQRr)
1183*06c3fb27SDimitry Andric           .addReg(DstReg, getUndefRegState(DstIsUndef))
1184*06c3fb27SDimitry Andric           .addImm(1)
1185*06c3fb27SDimitry Andric           .addReg(SrcHiReg, getKillRegState(SrcIsKill))
1186*06c3fb27SDimitry Andric           .setMemRefs(MI.memoperands());
1187*06c3fb27SDimitry Andric       buildMI(MBB, MBBI, AVR::STPtrRr)
1188*06c3fb27SDimitry Andric           .addReg(DstReg, getUndefRegState(DstIsUndef))
1189*06c3fb27SDimitry Andric           .addReg(SrcLoReg, getKillRegState(SrcIsKill))
1190*06c3fb27SDimitry Andric           .setMemRefs(MI.memoperands());
1191*06c3fb27SDimitry Andric     }
1192bdd1243dSDimitry Andric   }
11930b57cec5SDimitry Andric 
11940b57cec5SDimitry Andric   MI.eraseFromParent();
11950b57cec5SDimitry Andric   return true;
11960b57cec5SDimitry Andric }
11970b57cec5SDimitry Andric 
11980b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)11990b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::STWPtrPiRr>(Block &MBB, BlockIt MBBI) {
12000b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
12015ffd83dbSDimitry Andric   Register SrcLoReg, SrcHiReg;
12025ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
12035ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(2).getReg();
12040b57cec5SDimitry Andric   unsigned Imm = MI.getOperand(3).getImm();
12050b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
12060b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(2).isKill();
12075ffd83dbSDimitry Andric   unsigned OpLo = AVR::STPtrPiRr;
12085ffd83dbSDimitry Andric   unsigned OpHi = AVR::STPtrPiRr;
12090b57cec5SDimitry Andric   TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
12100b57cec5SDimitry Andric 
12110b57cec5SDimitry Andric   assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
12120b57cec5SDimitry Andric 
12130b57cec5SDimitry Andric   auto MIBLO = buildMI(MBB, MBBI, OpLo)
12140b57cec5SDimitry Andric                    .addReg(DstReg, RegState::Define)
12150b57cec5SDimitry Andric                    .addReg(DstReg, RegState::Kill)
12160b57cec5SDimitry Andric                    .addReg(SrcLoReg, getKillRegState(SrcIsKill))
12170b57cec5SDimitry Andric                    .addImm(Imm);
12180b57cec5SDimitry Andric 
1219349cc55cSDimitry Andric   auto MIBHI =
1220349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpHi)
12210b57cec5SDimitry Andric           .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
12220b57cec5SDimitry Andric           .addReg(DstReg, RegState::Kill)
12230b57cec5SDimitry Andric           .addReg(SrcHiReg, getKillRegState(SrcIsKill))
12240b57cec5SDimitry Andric           .addImm(Imm);
12250b57cec5SDimitry Andric 
12260b57cec5SDimitry Andric   MIBLO.setMemRefs(MI.memoperands());
12270b57cec5SDimitry Andric   MIBHI.setMemRefs(MI.memoperands());
12280b57cec5SDimitry Andric 
12290b57cec5SDimitry Andric   MI.eraseFromParent();
12300b57cec5SDimitry Andric   return true;
12310b57cec5SDimitry Andric }
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)12340b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::STWPtrPdRr>(Block &MBB, BlockIt MBBI) {
12350b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
12365ffd83dbSDimitry Andric   Register SrcLoReg, SrcHiReg;
12375ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
12385ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(2).getReg();
12390b57cec5SDimitry Andric   unsigned Imm = MI.getOperand(3).getImm();
12400b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
12410b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(2).isKill();
12425ffd83dbSDimitry Andric   unsigned OpLo = AVR::STPtrPdRr;
12435ffd83dbSDimitry Andric   unsigned OpHi = AVR::STPtrPdRr;
12440b57cec5SDimitry Andric   TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
12450b57cec5SDimitry Andric 
12460b57cec5SDimitry Andric   assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
12470b57cec5SDimitry Andric 
12480b57cec5SDimitry Andric   auto MIBHI = buildMI(MBB, MBBI, OpHi)
12490b57cec5SDimitry Andric                    .addReg(DstReg, RegState::Define)
12500b57cec5SDimitry Andric                    .addReg(DstReg, RegState::Kill)
12510b57cec5SDimitry Andric                    .addReg(SrcHiReg, getKillRegState(SrcIsKill))
12520b57cec5SDimitry Andric                    .addImm(Imm);
12530b57cec5SDimitry Andric 
1254349cc55cSDimitry Andric   auto MIBLO =
1255349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpLo)
12560b57cec5SDimitry Andric           .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
12570b57cec5SDimitry Andric           .addReg(DstReg, RegState::Kill)
12580b57cec5SDimitry Andric           .addReg(SrcLoReg, getKillRegState(SrcIsKill))
12590b57cec5SDimitry Andric           .addImm(Imm);
12600b57cec5SDimitry Andric 
12610b57cec5SDimitry Andric   MIBLO.setMemRefs(MI.memoperands());
12620b57cec5SDimitry Andric   MIBHI.setMemRefs(MI.memoperands());
12630b57cec5SDimitry Andric 
12640b57cec5SDimitry Andric   MI.eraseFromParent();
12650b57cec5SDimitry Andric   return true;
12660b57cec5SDimitry Andric }
12670b57cec5SDimitry Andric 
12680b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)12690b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {
12700b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
1271bdd1243dSDimitry Andric   const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
127281ad6265SDimitry Andric 
12735ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
12740b57cec5SDimitry Andric   bool DstIsKill = MI.getOperand(0).isKill();
127581ad6265SDimitry Andric   unsigned Imm = MI.getOperand(1).getImm();
127681ad6265SDimitry Andric   Register SrcReg = MI.getOperand(2).getReg();
12770b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(2).isKill();
127881ad6265SDimitry Andric 
127981ad6265SDimitry Andric   // STD's maximum displacement is 63, so larger stores have to be split into a
1280bdd1243dSDimitry Andric   // set of operations.
1281bdd1243dSDimitry Andric   // For avrtiny chips, STD is not available at all so we always have to fall
1282bdd1243dSDimitry Andric   // back to manual pointer adjustments.
1283bdd1243dSDimitry Andric   if (Imm >= 63 || STI.hasTinyEncoding()) {
1284bdd1243dSDimitry Andric     // Add offset. The offset can be 0 when expanding this instruction from the
1285bdd1243dSDimitry Andric     // more specific STWPtrRr instruction.
1286bdd1243dSDimitry Andric     if (Imm != 0) {
1287bdd1243dSDimitry Andric       buildMI(MBB, MBBI, AVR::SUBIWRdK, DstReg)
1288bdd1243dSDimitry Andric           .addReg(DstReg, RegState::Kill)
1289bdd1243dSDimitry Andric           .addImm(0x10000 - Imm);
129081ad6265SDimitry Andric     }
129181ad6265SDimitry Andric 
1292bdd1243dSDimitry Andric     // Do the store. This is a word store, that will be expanded further.
1293bdd1243dSDimitry Andric     buildMI(MBB, MBBI, AVR::STWPtrPiRr, DstReg)
1294bdd1243dSDimitry Andric         .addReg(DstReg, getKillRegState(DstIsKill))
1295bdd1243dSDimitry Andric         .addReg(SrcReg, getKillRegState(SrcIsKill))
1296bdd1243dSDimitry Andric         .addImm(0)
1297bdd1243dSDimitry Andric         .setMemRefs(MI.memoperands());
129881ad6265SDimitry Andric 
1299bdd1243dSDimitry Andric     // If the pointer is used after the store instruction, subtract the new
1300bdd1243dSDimitry Andric     // offset (with 2 added after the postincrement instructions) so it is the
1301bdd1243dSDimitry Andric     // same as before.
130281ad6265SDimitry Andric     if (!DstIsKill) {
1303bdd1243dSDimitry Andric       buildMI(MBB, MBBI, AVR::SUBIWRdK, DstReg)
1304bdd1243dSDimitry Andric           .addReg(DstReg, RegState::Kill)
1305bdd1243dSDimitry Andric           .addImm(Imm + 2);
130681ad6265SDimitry Andric     }
130781ad6265SDimitry Andric   } else {
130881ad6265SDimitry Andric     Register SrcLoReg, SrcHiReg;
13090b57cec5SDimitry Andric     TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
13100b57cec5SDimitry Andric 
1311*06c3fb27SDimitry Andric     if (STI.hasLowByteFirst()) {
1312*06c3fb27SDimitry Andric       buildMI(MBB, MBBI, AVR::STDPtrQRr)
13130b57cec5SDimitry Andric           .addReg(DstReg)
13140b57cec5SDimitry Andric           .addImm(Imm)
1315*06c3fb27SDimitry Andric           .addReg(SrcLoReg, getKillRegState(SrcIsKill))
1316*06c3fb27SDimitry Andric           .setMemRefs(MI.memoperands());
1317*06c3fb27SDimitry Andric       buildMI(MBB, MBBI, AVR::STDPtrQRr)
13180b57cec5SDimitry Andric           .addReg(DstReg, getKillRegState(DstIsKill))
13190b57cec5SDimitry Andric           .addImm(Imm + 1)
1320*06c3fb27SDimitry Andric           .addReg(SrcHiReg, getKillRegState(SrcIsKill))
1321*06c3fb27SDimitry Andric           .setMemRefs(MI.memoperands());
1322*06c3fb27SDimitry Andric     } else {
1323*06c3fb27SDimitry Andric       buildMI(MBB, MBBI, AVR::STDPtrQRr)
1324*06c3fb27SDimitry Andric           .addReg(DstReg)
1325*06c3fb27SDimitry Andric           .addImm(Imm + 1)
1326*06c3fb27SDimitry Andric           .addReg(SrcHiReg, getKillRegState(SrcIsKill))
1327*06c3fb27SDimitry Andric           .setMemRefs(MI.memoperands());
1328*06c3fb27SDimitry Andric       buildMI(MBB, MBBI, AVR::STDPtrQRr)
1329*06c3fb27SDimitry Andric           .addReg(DstReg, getKillRegState(DstIsKill))
1330*06c3fb27SDimitry Andric           .addImm(Imm)
1331*06c3fb27SDimitry Andric           .addReg(SrcLoReg, getKillRegState(SrcIsKill))
1332*06c3fb27SDimitry Andric           .setMemRefs(MI.memoperands());
1333*06c3fb27SDimitry Andric     }
133481ad6265SDimitry Andric   }
13350b57cec5SDimitry Andric 
13360b57cec5SDimitry Andric   MI.eraseFromParent();
13370b57cec5SDimitry Andric   return true;
13380b57cec5SDimitry Andric }
13390b57cec5SDimitry Andric 
13400b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)134181ad6265SDimitry Andric bool AVRExpandPseudo::expand<AVR::STDSPQRr>(Block &MBB, BlockIt MBBI) {
134281ad6265SDimitry Andric   MachineInstr &MI = *MBBI;
134381ad6265SDimitry Andric   const MachineFunction &MF = *MBB.getParent();
134481ad6265SDimitry Andric   const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
134581ad6265SDimitry Andric 
134681ad6265SDimitry Andric   assert(MI.getOperand(0).getReg() == AVR::SP &&
134781ad6265SDimitry Andric          "SP is expected as base pointer");
134881ad6265SDimitry Andric 
134981ad6265SDimitry Andric   assert(STI.getFrameLowering()->hasReservedCallFrame(MF) &&
135081ad6265SDimitry Andric          "unexpected STDSPQRr pseudo instruction");
135181ad6265SDimitry Andric   (void)STI;
135281ad6265SDimitry Andric 
135381ad6265SDimitry Andric   MI.setDesc(TII->get(AVR::STDPtrQRr));
135481ad6265SDimitry Andric   MI.getOperand(0).setReg(AVR::R29R28);
135581ad6265SDimitry Andric 
135681ad6265SDimitry Andric   return true;
135781ad6265SDimitry Andric }
135881ad6265SDimitry Andric 
135981ad6265SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)136081ad6265SDimitry Andric bool AVRExpandPseudo::expand<AVR::STDWSPQRr>(Block &MBB, BlockIt MBBI) {
136181ad6265SDimitry Andric   MachineInstr &MI = *MBBI;
136281ad6265SDimitry Andric   const MachineFunction &MF = *MBB.getParent();
136381ad6265SDimitry Andric   const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
136481ad6265SDimitry Andric 
136581ad6265SDimitry Andric   assert(MI.getOperand(0).getReg() == AVR::SP &&
136681ad6265SDimitry Andric          "SP is expected as base pointer");
136781ad6265SDimitry Andric 
136881ad6265SDimitry Andric   assert(STI.getFrameLowering()->hasReservedCallFrame(MF) &&
136981ad6265SDimitry Andric          "unexpected STDWSPQRr pseudo instruction");
137081ad6265SDimitry Andric   (void)STI;
137181ad6265SDimitry Andric 
137281ad6265SDimitry Andric   MI.setDesc(TII->get(AVR::STDWPtrQRr));
137381ad6265SDimitry Andric   MI.getOperand(0).setReg(AVR::R29R28);
137481ad6265SDimitry Andric 
137581ad6265SDimitry Andric   return true;
137681ad6265SDimitry Andric }
137781ad6265SDimitry Andric 
137881ad6265SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)13790b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::INWRdA>(Block &MBB, BlockIt MBBI) {
13800b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
13815ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
13820b57cec5SDimitry Andric   unsigned Imm = MI.getOperand(1).getImm();
13835ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
13840b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
13855ffd83dbSDimitry Andric   unsigned OpLo = AVR::INRdA;
13865ffd83dbSDimitry Andric   unsigned OpHi = AVR::INRdA;
13870b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
13880b57cec5SDimitry Andric 
1389349cc55cSDimitry Andric   // Since we add 1 to the Imm value for the high byte below, and 63 is the
1390349cc55cSDimitry Andric   // highest Imm value allowed for the instruction, 62 is the limit here.
13910b57cec5SDimitry Andric   assert(Imm <= 62 && "Address is out of range");
13920b57cec5SDimitry Andric 
1393349cc55cSDimitry Andric   auto MIBLO =
1394349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpLo)
13950b57cec5SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
13960b57cec5SDimitry Andric           .addImm(Imm);
13970b57cec5SDimitry Andric 
1398349cc55cSDimitry Andric   auto MIBHI =
1399349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpHi)
14000b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
14010b57cec5SDimitry Andric           .addImm(Imm + 1);
14020b57cec5SDimitry Andric 
14030b57cec5SDimitry Andric   MIBLO.setMemRefs(MI.memoperands());
14040b57cec5SDimitry Andric   MIBHI.setMemRefs(MI.memoperands());
14050b57cec5SDimitry Andric 
14060b57cec5SDimitry Andric   MI.eraseFromParent();
14070b57cec5SDimitry Andric   return true;
14080b57cec5SDimitry Andric }
14090b57cec5SDimitry Andric 
14100b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)14110b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::OUTWARr>(Block &MBB, BlockIt MBBI) {
1412*06c3fb27SDimitry Andric   const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
14130b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
14145ffd83dbSDimitry Andric   Register SrcLoReg, SrcHiReg;
14150b57cec5SDimitry Andric   unsigned Imm = MI.getOperand(0).getImm();
14165ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
14170b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
14180b57cec5SDimitry Andric   TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
14190b57cec5SDimitry Andric 
1420349cc55cSDimitry Andric   // Since we add 1 to the Imm value for the high byte below, and 63 is the
1421349cc55cSDimitry Andric   // highest Imm value allowed for the instruction, 62 is the limit here.
14220b57cec5SDimitry Andric   assert(Imm <= 62 && "Address is out of range");
14230b57cec5SDimitry Andric 
1424*06c3fb27SDimitry Andric   // 16 bit I/O writes need the high byte first on normal AVR devices,
1425*06c3fb27SDimitry Andric   // and in reverse order for the XMEGA/XMEGA3/XMEGAU families.
1426*06c3fb27SDimitry Andric   auto MIBHI = buildMI(MBB, MBBI, AVR::OUTARr)
1427*06c3fb27SDimitry Andric                    .addImm(STI.hasLowByteFirst() ? Imm : Imm + 1)
1428*06c3fb27SDimitry Andric                    .addReg(STI.hasLowByteFirst() ? SrcLoReg : SrcHiReg,
1429*06c3fb27SDimitry Andric                            getKillRegState(SrcIsKill));
1430*06c3fb27SDimitry Andric   auto MIBLO = buildMI(MBB, MBBI, AVR::OUTARr)
1431*06c3fb27SDimitry Andric                    .addImm(STI.hasLowByteFirst() ? Imm + 1 : Imm)
1432*06c3fb27SDimitry Andric                    .addReg(STI.hasLowByteFirst() ? SrcHiReg : SrcLoReg,
1433*06c3fb27SDimitry Andric                            getKillRegState(SrcIsKill));
14340b57cec5SDimitry Andric 
14350b57cec5SDimitry Andric   MIBLO.setMemRefs(MI.memoperands());
14360b57cec5SDimitry Andric   MIBHI.setMemRefs(MI.memoperands());
14370b57cec5SDimitry Andric 
14380b57cec5SDimitry Andric   MI.eraseFromParent();
14390b57cec5SDimitry Andric   return true;
14400b57cec5SDimitry Andric }
14410b57cec5SDimitry Andric 
14420b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)14430b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::PUSHWRr>(Block &MBB, BlockIt MBBI) {
14440b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
14455ffd83dbSDimitry Andric   Register SrcLoReg, SrcHiReg;
14465ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(0).getReg();
14470b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(0).isKill();
14480b57cec5SDimitry Andric   unsigned Flags = MI.getFlags();
14495ffd83dbSDimitry Andric   unsigned OpLo = AVR::PUSHRr;
14505ffd83dbSDimitry Andric   unsigned OpHi = AVR::PUSHRr;
14510b57cec5SDimitry Andric   TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
14520b57cec5SDimitry Andric 
14530b57cec5SDimitry Andric   // Low part
14540b57cec5SDimitry Andric   buildMI(MBB, MBBI, OpLo)
14550b57cec5SDimitry Andric       .addReg(SrcLoReg, getKillRegState(SrcIsKill))
14560b57cec5SDimitry Andric       .setMIFlags(Flags);
14570b57cec5SDimitry Andric 
14580b57cec5SDimitry Andric   // High part
14590b57cec5SDimitry Andric   buildMI(MBB, MBBI, OpHi)
14600b57cec5SDimitry Andric       .addReg(SrcHiReg, getKillRegState(SrcIsKill))
14610b57cec5SDimitry Andric       .setMIFlags(Flags);
14620b57cec5SDimitry Andric 
14630b57cec5SDimitry Andric   MI.eraseFromParent();
14640b57cec5SDimitry Andric   return true;
14650b57cec5SDimitry Andric }
14660b57cec5SDimitry Andric 
14670b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)14680b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::POPWRd>(Block &MBB, BlockIt MBBI) {
14690b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
14705ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
14715ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
14720b57cec5SDimitry Andric   unsigned Flags = MI.getFlags();
14735ffd83dbSDimitry Andric   unsigned OpLo = AVR::POPRd;
14745ffd83dbSDimitry Andric   unsigned OpHi = AVR::POPRd;
14750b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
14760b57cec5SDimitry Andric 
14770b57cec5SDimitry Andric   buildMI(MBB, MBBI, OpHi, DstHiReg).setMIFlags(Flags); // High
14780b57cec5SDimitry Andric   buildMI(MBB, MBBI, OpLo, DstLoReg).setMIFlags(Flags); // Low
14790b57cec5SDimitry Andric 
14800b57cec5SDimitry Andric   MI.eraseFromParent();
14810b57cec5SDimitry Andric   return true;
14820b57cec5SDimitry Andric }
14830b57cec5SDimitry Andric 
expandROLBRd(Block & MBB,BlockIt MBBI)1484*06c3fb27SDimitry Andric bool AVRExpandPseudo::expandROLBRd(Block &MBB, BlockIt MBBI) {
1485480093f4SDimitry Andric   // In AVR, the rotate instructions behave quite unintuitively. They rotate
1486480093f4SDimitry Andric   // bits through the carry bit in SREG, effectively rotating over 9 bits,
1487480093f4SDimitry Andric   // instead of 8. This is useful when we are dealing with numbers over
1488480093f4SDimitry Andric   // multiple registers, but when we actually need to rotate stuff, we have
1489480093f4SDimitry Andric   // to explicitly add the carry bit.
1490480093f4SDimitry Andric 
1491480093f4SDimitry Andric   MachineInstr &MI = *MBBI;
1492480093f4SDimitry Andric   unsigned OpShift, OpCarry;
14935ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
1494*06c3fb27SDimitry Andric   Register ZeroReg = MI.getOperand(3).getReg();
1495480093f4SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
149681ad6265SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
1497480093f4SDimitry Andric   OpShift = AVR::ADDRdRr;
1498480093f4SDimitry Andric   OpCarry = AVR::ADCRdRr;
1499480093f4SDimitry Andric 
1500480093f4SDimitry Andric   // add r16, r16
1501480093f4SDimitry Andric   // adc r16, r1
1502480093f4SDimitry Andric 
1503480093f4SDimitry Andric   // Shift part
1504480093f4SDimitry Andric   buildMI(MBB, MBBI, OpShift)
1505480093f4SDimitry Andric       .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
150681ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill)
150781ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill);
1508480093f4SDimitry Andric 
1509480093f4SDimitry Andric   // Add the carry bit
1510480093f4SDimitry Andric   auto MIB = buildMI(MBB, MBBI, OpCarry)
1511480093f4SDimitry Andric                  .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
151281ad6265SDimitry Andric                  .addReg(DstReg, getKillRegState(DstIsKill))
1513bdd1243dSDimitry Andric                  .addReg(ZeroReg);
1514480093f4SDimitry Andric 
1515bdd1243dSDimitry Andric   MIB->getOperand(3).setIsDead(); // SREG is always dead
1516bdd1243dSDimitry Andric   MIB->getOperand(4).setIsKill(); // SREG is always implicitly killed
1517480093f4SDimitry Andric 
1518480093f4SDimitry Andric   MI.eraseFromParent();
1519480093f4SDimitry Andric   return true;
1520480093f4SDimitry Andric }
1521480093f4SDimitry Andric 
1522480093f4SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)1523*06c3fb27SDimitry Andric bool AVRExpandPseudo::expand<AVR::ROLBRdR1>(Block &MBB, BlockIt MBBI) {
1524*06c3fb27SDimitry Andric   return expandROLBRd(MBB, MBBI);
1525*06c3fb27SDimitry Andric }
1526*06c3fb27SDimitry Andric 
1527*06c3fb27SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)1528*06c3fb27SDimitry Andric bool AVRExpandPseudo::expand<AVR::ROLBRdR17>(Block &MBB, BlockIt MBBI) {
1529*06c3fb27SDimitry Andric   return expandROLBRd(MBB, MBBI);
1530*06c3fb27SDimitry Andric }
1531*06c3fb27SDimitry Andric 
1532*06c3fb27SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)1533480093f4SDimitry Andric bool AVRExpandPseudo::expand<AVR::RORBRd>(Block &MBB, BlockIt MBBI) {
1534480093f4SDimitry Andric   // In AVR, the rotate instructions behave quite unintuitively. They rotate
1535480093f4SDimitry Andric   // bits through the carry bit in SREG, effectively rotating over 9 bits,
1536480093f4SDimitry Andric   // instead of 8. This is useful when we are dealing with numbers over
1537480093f4SDimitry Andric   // multiple registers, but when we actually need to rotate stuff, we have
1538480093f4SDimitry Andric   // to explicitly add the carry bit.
1539480093f4SDimitry Andric 
1540480093f4SDimitry Andric   MachineInstr &MI = *MBBI;
15415ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
1542480093f4SDimitry Andric 
1543fe6060f1SDimitry Andric   // bst r16, 0
1544fe6060f1SDimitry Andric   // ror r16
1545fe6060f1SDimitry Andric   // bld r16, 7
1546480093f4SDimitry Andric 
1547fe6060f1SDimitry Andric   // Move the lowest bit from DstReg into the T bit
1548fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::BST).addReg(DstReg).addImm(0);
1549480093f4SDimitry Andric 
1550fe6060f1SDimitry Andric   // Rotate to the right
1551fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::RORRd, DstReg).addReg(DstReg);
1552480093f4SDimitry Andric 
1553fe6060f1SDimitry Andric   // Move the T bit into the highest bit of DstReg.
1554fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::BLD, DstReg).addReg(DstReg).addImm(7);
1555480093f4SDimitry Andric 
1556480093f4SDimitry Andric   MI.eraseFromParent();
1557480093f4SDimitry Andric   return true;
1558480093f4SDimitry Andric }
1559480093f4SDimitry Andric 
1560480093f4SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)15610b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::LSLWRd>(Block &MBB, BlockIt MBBI) {
15620b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
15635ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
15645ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
15650b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
15660b57cec5SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
15670b57cec5SDimitry Andric   bool ImpIsDead = MI.getOperand(2).isDead();
15685ffd83dbSDimitry Andric   unsigned OpLo = AVR::ADDRdRr; // ADD Rd, Rd <==> LSL Rd
15695ffd83dbSDimitry Andric   unsigned OpHi = AVR::ADCRdRr; // ADC Rd, Rd <==> ROL Rd
15700b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
15710b57cec5SDimitry Andric 
15720b57cec5SDimitry Andric   // Low part
15730b57cec5SDimitry Andric   buildMI(MBB, MBBI, OpLo)
15740b57cec5SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
157581ad6265SDimitry Andric       .addReg(DstLoReg, getKillRegState(DstIsKill))
15760b57cec5SDimitry Andric       .addReg(DstLoReg, getKillRegState(DstIsKill));
15770b57cec5SDimitry Andric 
1578349cc55cSDimitry Andric   auto MIBHI =
1579349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpHi)
15800b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
158181ad6265SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill))
15820b57cec5SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill));
15830b57cec5SDimitry Andric 
15840b57cec5SDimitry Andric   if (ImpIsDead)
15850b57cec5SDimitry Andric     MIBHI->getOperand(3).setIsDead();
15860b57cec5SDimitry Andric 
15870b57cec5SDimitry Andric   // SREG is always implicitly killed
15880b57cec5SDimitry Andric   MIBHI->getOperand(4).setIsKill();
15890b57cec5SDimitry Andric 
15900b57cec5SDimitry Andric   MI.eraseFromParent();
15910b57cec5SDimitry Andric   return true;
15920b57cec5SDimitry Andric }
15930b57cec5SDimitry Andric 
159404eeddc0SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)159504eeddc0SDimitry Andric bool AVRExpandPseudo::expand<AVR::LSLWHiRd>(Block &MBB, BlockIt MBBI) {
159604eeddc0SDimitry Andric   MachineInstr &MI = *MBBI;
159704eeddc0SDimitry Andric   Register DstLoReg, DstHiReg;
159804eeddc0SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
159904eeddc0SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
160004eeddc0SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
160104eeddc0SDimitry Andric   bool ImpIsDead = MI.getOperand(2).isDead();
160204eeddc0SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
160304eeddc0SDimitry Andric 
160404eeddc0SDimitry Andric   // add hireg, hireg <==> lsl hireg
160504eeddc0SDimitry Andric   auto MILSL =
160604eeddc0SDimitry Andric       buildMI(MBB, MBBI, AVR::ADDRdRr)
160781ad6265SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
160804eeddc0SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill))
160904eeddc0SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill));
161004eeddc0SDimitry Andric 
161104eeddc0SDimitry Andric   if (ImpIsDead)
161204eeddc0SDimitry Andric     MILSL->getOperand(3).setIsDead();
161304eeddc0SDimitry Andric 
161404eeddc0SDimitry Andric   MI.eraseFromParent();
161504eeddc0SDimitry Andric   return true;
161604eeddc0SDimitry Andric }
161704eeddc0SDimitry Andric 
expandLSLW4Rd(Block & MBB,BlockIt MBBI)1618fe6060f1SDimitry Andric bool AVRExpandPseudo::expandLSLW4Rd(Block &MBB, BlockIt MBBI) {
1619fe6060f1SDimitry Andric   MachineInstr &MI = *MBBI;
1620fe6060f1SDimitry Andric   Register DstLoReg, DstHiReg;
1621fe6060f1SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
1622fe6060f1SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
1623fe6060f1SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
1624fe6060f1SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
1625fe6060f1SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1626fe6060f1SDimitry Andric 
1627fe6060f1SDimitry Andric   // swap Rh
1628fe6060f1SDimitry Andric   // swap Rl
1629fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::SWAPRd)
1630fe6060f1SDimitry Andric       .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
163181ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Kill);
1632fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::SWAPRd)
1633fe6060f1SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
163481ad6265SDimitry Andric       .addReg(DstLoReg, RegState::Kill);
1635fe6060f1SDimitry Andric 
1636fe6060f1SDimitry Andric   // andi Rh, 0xf0
1637fe6060f1SDimitry Andric   auto MI0 =
1638fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::ANDIRdK)
1639fe6060f1SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
164081ad6265SDimitry Andric           .addReg(DstHiReg, RegState::Kill)
1641fe6060f1SDimitry Andric           .addImm(0xf0);
1642fe6060f1SDimitry Andric   // SREG is implicitly dead.
1643fe6060f1SDimitry Andric   MI0->getOperand(3).setIsDead();
1644fe6060f1SDimitry Andric 
1645fe6060f1SDimitry Andric   // eor Rh, Rl
1646fe6060f1SDimitry Andric   auto MI1 =
1647fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::EORRdRr)
1648fe6060f1SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
164981ad6265SDimitry Andric           .addReg(DstHiReg, RegState::Kill)
1650fe6060f1SDimitry Andric           .addReg(DstLoReg);
1651fe6060f1SDimitry Andric   // SREG is implicitly dead.
1652fe6060f1SDimitry Andric   MI1->getOperand(3).setIsDead();
1653fe6060f1SDimitry Andric 
1654fe6060f1SDimitry Andric   // andi Rl, 0xf0
1655fe6060f1SDimitry Andric   auto MI2 =
1656fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::ANDIRdK)
1657fe6060f1SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1658fe6060f1SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill))
1659fe6060f1SDimitry Andric           .addImm(0xf0);
1660fe6060f1SDimitry Andric   // SREG is implicitly dead.
1661fe6060f1SDimitry Andric   MI2->getOperand(3).setIsDead();
1662fe6060f1SDimitry Andric 
1663fe6060f1SDimitry Andric   // eor Rh, Rl
1664fe6060f1SDimitry Andric   auto MI3 =
1665fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::EORRdRr)
1666fe6060f1SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1667fe6060f1SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill))
1668fe6060f1SDimitry Andric           .addReg(DstLoReg);
1669fe6060f1SDimitry Andric   if (ImpIsDead)
1670fe6060f1SDimitry Andric     MI3->getOperand(3).setIsDead();
1671fe6060f1SDimitry Andric 
1672fe6060f1SDimitry Andric   MI.eraseFromParent();
1673fe6060f1SDimitry Andric   return true;
1674fe6060f1SDimitry Andric }
1675fe6060f1SDimitry Andric 
expandLSLW8Rd(Block & MBB,BlockIt MBBI)1676fe6060f1SDimitry Andric bool AVRExpandPseudo::expandLSLW8Rd(Block &MBB, BlockIt MBBI) {
1677fe6060f1SDimitry Andric   MachineInstr &MI = *MBBI;
1678fe6060f1SDimitry Andric   Register DstLoReg, DstHiReg;
1679fe6060f1SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
1680fe6060f1SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
1681fe6060f1SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
1682fe6060f1SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
1683fe6060f1SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1684fe6060f1SDimitry Andric 
1685fe6060f1SDimitry Andric   // mov Rh, Rl
1686fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::MOVRdRr)
1687fe6060f1SDimitry Andric       .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1688fe6060f1SDimitry Andric       .addReg(DstLoReg);
1689fe6060f1SDimitry Andric 
1690fe6060f1SDimitry Andric   // clr Rl
1691fe6060f1SDimitry Andric   auto MIBLO =
1692fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::EORRdRr)
1693fe6060f1SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1694fe6060f1SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill))
1695fe6060f1SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill));
1696fe6060f1SDimitry Andric   if (ImpIsDead)
1697fe6060f1SDimitry Andric     MIBLO->getOperand(3).setIsDead();
1698fe6060f1SDimitry Andric 
1699fe6060f1SDimitry Andric   MI.eraseFromParent();
1700fe6060f1SDimitry Andric   return true;
1701fe6060f1SDimitry Andric }
1702fe6060f1SDimitry Andric 
expandLSLW12Rd(Block & MBB,BlockIt MBBI)1703fe6060f1SDimitry Andric bool AVRExpandPseudo::expandLSLW12Rd(Block &MBB, BlockIt MBBI) {
1704fe6060f1SDimitry Andric   MachineInstr &MI = *MBBI;
1705fe6060f1SDimitry Andric   Register DstLoReg, DstHiReg;
1706fe6060f1SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
1707fe6060f1SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
1708fe6060f1SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
1709fe6060f1SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
1710fe6060f1SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1711fe6060f1SDimitry Andric 
1712fe6060f1SDimitry Andric   // mov Rh, Rl
1713fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::MOVRdRr)
1714fe6060f1SDimitry Andric       .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1715fe6060f1SDimitry Andric       .addReg(DstLoReg);
1716fe6060f1SDimitry Andric 
1717fe6060f1SDimitry Andric   // swap Rh
1718fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::SWAPRd)
1719fe6060f1SDimitry Andric       .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
172081ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Kill);
1721fe6060f1SDimitry Andric 
1722fe6060f1SDimitry Andric   // andi Rh, 0xf0
1723fe6060f1SDimitry Andric   auto MI0 =
1724fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::ANDIRdK)
1725fe6060f1SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1726fe6060f1SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill))
1727fe6060f1SDimitry Andric           .addImm(0xf0);
1728fe6060f1SDimitry Andric   // SREG is implicitly dead.
1729fe6060f1SDimitry Andric   MI0->getOperand(3).setIsDead();
1730fe6060f1SDimitry Andric 
1731fe6060f1SDimitry Andric   // clr Rl
1732fe6060f1SDimitry Andric   auto MI1 =
1733fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::EORRdRr)
1734fe6060f1SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1735fe6060f1SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill))
1736fe6060f1SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill));
1737fe6060f1SDimitry Andric   if (ImpIsDead)
1738fe6060f1SDimitry Andric     MI1->getOperand(3).setIsDead();
1739fe6060f1SDimitry Andric 
1740fe6060f1SDimitry Andric   MI.eraseFromParent();
1741fe6060f1SDimitry Andric   return true;
1742fe6060f1SDimitry Andric }
1743fe6060f1SDimitry Andric 
1744fe6060f1SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)1745fe6060f1SDimitry Andric bool AVRExpandPseudo::expand<AVR::LSLWNRd>(Block &MBB, BlockIt MBBI) {
1746fe6060f1SDimitry Andric   MachineInstr &MI = *MBBI;
1747fe6060f1SDimitry Andric   unsigned Imm = MI.getOperand(2).getImm();
1748fe6060f1SDimitry Andric   switch (Imm) {
1749fe6060f1SDimitry Andric   case 4:
1750fe6060f1SDimitry Andric     return expandLSLW4Rd(MBB, MBBI);
1751fe6060f1SDimitry Andric   case 8:
1752fe6060f1SDimitry Andric     return expandLSLW8Rd(MBB, MBBI);
1753fe6060f1SDimitry Andric   case 12:
1754fe6060f1SDimitry Andric     return expandLSLW12Rd(MBB, MBBI);
1755fe6060f1SDimitry Andric   default:
1756fe6060f1SDimitry Andric     llvm_unreachable("unimplemented lslwn");
1757fe6060f1SDimitry Andric     return false;
1758fe6060f1SDimitry Andric   }
1759fe6060f1SDimitry Andric }
1760fe6060f1SDimitry Andric 
17610b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)17620b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::LSRWRd>(Block &MBB, BlockIt MBBI) {
17630b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
17645ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
17655ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
17660b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
17670b57cec5SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
17680b57cec5SDimitry Andric   bool ImpIsDead = MI.getOperand(2).isDead();
17695ffd83dbSDimitry Andric   unsigned OpLo = AVR::RORRd;
17705ffd83dbSDimitry Andric   unsigned OpHi = AVR::LSRRd;
17710b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
17720b57cec5SDimitry Andric 
17730b57cec5SDimitry Andric   // High part
17740b57cec5SDimitry Andric   buildMI(MBB, MBBI, OpHi)
17750b57cec5SDimitry Andric       .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
17760b57cec5SDimitry Andric       .addReg(DstHiReg, getKillRegState(DstIsKill));
17770b57cec5SDimitry Andric 
1778349cc55cSDimitry Andric   auto MIBLO =
1779349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpLo)
17800b57cec5SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
17810b57cec5SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill));
17820b57cec5SDimitry Andric 
17830b57cec5SDimitry Andric   if (ImpIsDead)
17840b57cec5SDimitry Andric     MIBLO->getOperand(2).setIsDead();
17850b57cec5SDimitry Andric 
17860b57cec5SDimitry Andric   // SREG is always implicitly killed
17870b57cec5SDimitry Andric   MIBLO->getOperand(3).setIsKill();
17880b57cec5SDimitry Andric 
17890b57cec5SDimitry Andric   MI.eraseFromParent();
17900b57cec5SDimitry Andric   return true;
17910b57cec5SDimitry Andric }
17920b57cec5SDimitry Andric 
179304eeddc0SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)179404eeddc0SDimitry Andric bool AVRExpandPseudo::expand<AVR::LSRWLoRd>(Block &MBB, BlockIt MBBI) {
179504eeddc0SDimitry Andric   MachineInstr &MI = *MBBI;
179604eeddc0SDimitry Andric   Register DstLoReg, DstHiReg;
179704eeddc0SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
179804eeddc0SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
179904eeddc0SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
180004eeddc0SDimitry Andric   bool ImpIsDead = MI.getOperand(2).isDead();
180104eeddc0SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
180204eeddc0SDimitry Andric 
180304eeddc0SDimitry Andric   // lsr loreg
180404eeddc0SDimitry Andric   auto MILSR =
180504eeddc0SDimitry Andric       buildMI(MBB, MBBI, AVR::LSRRd)
180604eeddc0SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
180704eeddc0SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill));
180804eeddc0SDimitry Andric 
180904eeddc0SDimitry Andric   if (ImpIsDead)
181004eeddc0SDimitry Andric     MILSR->getOperand(2).setIsDead();
181104eeddc0SDimitry Andric 
181204eeddc0SDimitry Andric   MI.eraseFromParent();
181304eeddc0SDimitry Andric   return true;
181404eeddc0SDimitry Andric }
181504eeddc0SDimitry Andric 
expandLSRW4Rd(Block & MBB,BlockIt MBBI)1816fe6060f1SDimitry Andric bool AVRExpandPseudo::expandLSRW4Rd(Block &MBB, BlockIt MBBI) {
1817fe6060f1SDimitry Andric   MachineInstr &MI = *MBBI;
1818fe6060f1SDimitry Andric   Register DstLoReg, DstHiReg;
1819fe6060f1SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
1820fe6060f1SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
1821fe6060f1SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
1822fe6060f1SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
1823fe6060f1SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1824fe6060f1SDimitry Andric 
1825fe6060f1SDimitry Andric   // swap Rh
1826fe6060f1SDimitry Andric   // swap Rl
1827fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::SWAPRd)
1828fe6060f1SDimitry Andric       .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
182981ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Kill);
1830fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::SWAPRd)
1831fe6060f1SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
183281ad6265SDimitry Andric       .addReg(DstLoReg, RegState::Kill);
1833fe6060f1SDimitry Andric 
1834fe6060f1SDimitry Andric   // andi Rl, 0xf
1835fe6060f1SDimitry Andric   auto MI0 =
1836fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::ANDIRdK)
1837fe6060f1SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
183881ad6265SDimitry Andric           .addReg(DstLoReg, RegState::Kill)
1839fe6060f1SDimitry Andric           .addImm(0xf);
1840fe6060f1SDimitry Andric   // SREG is implicitly dead.
1841fe6060f1SDimitry Andric   MI0->getOperand(3).setIsDead();
1842fe6060f1SDimitry Andric 
1843fe6060f1SDimitry Andric   // eor Rl, Rh
1844fe6060f1SDimitry Andric   auto MI1 =
1845fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::EORRdRr)
1846fe6060f1SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
184781ad6265SDimitry Andric           .addReg(DstLoReg, RegState::Kill)
1848fe6060f1SDimitry Andric           .addReg(DstHiReg);
1849fe6060f1SDimitry Andric   // SREG is implicitly dead.
1850fe6060f1SDimitry Andric   MI1->getOperand(3).setIsDead();
1851fe6060f1SDimitry Andric 
1852fe6060f1SDimitry Andric   // andi Rh, 0xf
1853fe6060f1SDimitry Andric   auto MI2 =
1854fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::ANDIRdK)
1855fe6060f1SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1856fe6060f1SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill))
1857fe6060f1SDimitry Andric           .addImm(0xf);
1858fe6060f1SDimitry Andric   // SREG is implicitly dead.
1859fe6060f1SDimitry Andric   MI2->getOperand(3).setIsDead();
1860fe6060f1SDimitry Andric 
1861fe6060f1SDimitry Andric   // eor Rl, Rh
1862fe6060f1SDimitry Andric   auto MI3 =
1863fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::EORRdRr)
1864fe6060f1SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1865fe6060f1SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill))
1866fe6060f1SDimitry Andric           .addReg(DstHiReg);
1867fe6060f1SDimitry Andric   if (ImpIsDead)
1868fe6060f1SDimitry Andric     MI3->getOperand(3).setIsDead();
1869fe6060f1SDimitry Andric 
1870fe6060f1SDimitry Andric   MI.eraseFromParent();
1871fe6060f1SDimitry Andric   return true;
1872fe6060f1SDimitry Andric }
1873fe6060f1SDimitry Andric 
expandLSRW8Rd(Block & MBB,BlockIt MBBI)1874fe6060f1SDimitry Andric bool AVRExpandPseudo::expandLSRW8Rd(Block &MBB, BlockIt MBBI) {
1875fe6060f1SDimitry Andric   MachineInstr &MI = *MBBI;
1876fe6060f1SDimitry Andric   Register DstLoReg, DstHiReg;
1877fe6060f1SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
1878fe6060f1SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
1879fe6060f1SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
1880fe6060f1SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
1881fe6060f1SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1882fe6060f1SDimitry Andric 
1883fe6060f1SDimitry Andric   // Move upper byte to lower byte.
1884fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::MOVRdRr)
1885fe6060f1SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1886fe6060f1SDimitry Andric       .addReg(DstHiReg);
1887fe6060f1SDimitry Andric 
1888fe6060f1SDimitry Andric   // Clear upper byte.
1889fe6060f1SDimitry Andric   auto MIBHI =
1890fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::EORRdRr)
1891fe6060f1SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1892fe6060f1SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill))
1893fe6060f1SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill));
1894fe6060f1SDimitry Andric   if (ImpIsDead)
1895fe6060f1SDimitry Andric     MIBHI->getOperand(3).setIsDead();
1896fe6060f1SDimitry Andric 
1897fe6060f1SDimitry Andric   MI.eraseFromParent();
1898fe6060f1SDimitry Andric   return true;
1899fe6060f1SDimitry Andric }
1900fe6060f1SDimitry Andric 
expandLSRW12Rd(Block & MBB,BlockIt MBBI)1901fe6060f1SDimitry Andric bool AVRExpandPseudo::expandLSRW12Rd(Block &MBB, BlockIt MBBI) {
1902fe6060f1SDimitry Andric   MachineInstr &MI = *MBBI;
1903fe6060f1SDimitry Andric   Register DstLoReg, DstHiReg;
1904fe6060f1SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
1905fe6060f1SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
1906fe6060f1SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
1907fe6060f1SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
1908fe6060f1SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1909fe6060f1SDimitry Andric 
1910fe6060f1SDimitry Andric   // Move upper byte to lower byte.
1911fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::MOVRdRr)
1912fe6060f1SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1913fe6060f1SDimitry Andric       .addReg(DstHiReg);
1914fe6060f1SDimitry Andric 
1915fe6060f1SDimitry Andric   // swap Rl
1916fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::SWAPRd)
1917fe6060f1SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
191881ad6265SDimitry Andric       .addReg(DstLoReg, RegState::Kill);
1919fe6060f1SDimitry Andric 
1920fe6060f1SDimitry Andric   // andi Rl, 0xf
1921fe6060f1SDimitry Andric   auto MI0 =
1922fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::ANDIRdK)
1923fe6060f1SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1924fe6060f1SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill))
1925fe6060f1SDimitry Andric           .addImm(0xf);
1926fe6060f1SDimitry Andric   // SREG is implicitly dead.
1927fe6060f1SDimitry Andric   MI0->getOperand(3).setIsDead();
1928fe6060f1SDimitry Andric 
1929fe6060f1SDimitry Andric   // Clear upper byte.
1930fe6060f1SDimitry Andric   auto MIBHI =
1931fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::EORRdRr)
1932fe6060f1SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1933fe6060f1SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill))
1934fe6060f1SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill));
1935fe6060f1SDimitry Andric   if (ImpIsDead)
1936fe6060f1SDimitry Andric     MIBHI->getOperand(3).setIsDead();
1937fe6060f1SDimitry Andric 
1938fe6060f1SDimitry Andric   MI.eraseFromParent();
1939fe6060f1SDimitry Andric   return true;
1940fe6060f1SDimitry Andric }
1941fe6060f1SDimitry Andric 
1942fe6060f1SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)1943fe6060f1SDimitry Andric bool AVRExpandPseudo::expand<AVR::LSRWNRd>(Block &MBB, BlockIt MBBI) {
1944fe6060f1SDimitry Andric   MachineInstr &MI = *MBBI;
1945fe6060f1SDimitry Andric   unsigned Imm = MI.getOperand(2).getImm();
1946fe6060f1SDimitry Andric   switch (Imm) {
1947fe6060f1SDimitry Andric   case 4:
1948fe6060f1SDimitry Andric     return expandLSRW4Rd(MBB, MBBI);
1949fe6060f1SDimitry Andric   case 8:
1950fe6060f1SDimitry Andric     return expandLSRW8Rd(MBB, MBBI);
1951fe6060f1SDimitry Andric   case 12:
1952fe6060f1SDimitry Andric     return expandLSRW12Rd(MBB, MBBI);
1953fe6060f1SDimitry Andric   default:
1954fe6060f1SDimitry Andric     llvm_unreachable("unimplemented lsrwn");
1955fe6060f1SDimitry Andric     return false;
1956fe6060f1SDimitry Andric   }
1957fe6060f1SDimitry Andric }
1958fe6060f1SDimitry Andric 
19590b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)19600b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::RORWRd>(Block &MBB, BlockIt MBBI) {
19610b57cec5SDimitry Andric   llvm_unreachable("RORW unimplemented");
19620b57cec5SDimitry Andric   return false;
19630b57cec5SDimitry Andric }
19640b57cec5SDimitry Andric 
19650b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)19660b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::ROLWRd>(Block &MBB, BlockIt MBBI) {
19670b57cec5SDimitry Andric   llvm_unreachable("ROLW unimplemented");
19680b57cec5SDimitry Andric   return false;
19690b57cec5SDimitry Andric }
19700b57cec5SDimitry Andric 
19710b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)19720b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::ASRWRd>(Block &MBB, BlockIt MBBI) {
19730b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
19745ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
19755ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
19760b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
19770b57cec5SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
19780b57cec5SDimitry Andric   bool ImpIsDead = MI.getOperand(2).isDead();
19795ffd83dbSDimitry Andric   unsigned OpLo = AVR::RORRd;
19805ffd83dbSDimitry Andric   unsigned OpHi = AVR::ASRRd;
19810b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
19820b57cec5SDimitry Andric 
19830b57cec5SDimitry Andric   // High part
19840b57cec5SDimitry Andric   buildMI(MBB, MBBI, OpHi)
19850b57cec5SDimitry Andric       .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
19860b57cec5SDimitry Andric       .addReg(DstHiReg, getKillRegState(DstIsKill));
19870b57cec5SDimitry Andric 
1988349cc55cSDimitry Andric   auto MIBLO =
1989349cc55cSDimitry Andric       buildMI(MBB, MBBI, OpLo)
19900b57cec5SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
19910b57cec5SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill));
19920b57cec5SDimitry Andric 
19930b57cec5SDimitry Andric   if (ImpIsDead)
19940b57cec5SDimitry Andric     MIBLO->getOperand(2).setIsDead();
19950b57cec5SDimitry Andric 
19960b57cec5SDimitry Andric   // SREG is always implicitly killed
19970b57cec5SDimitry Andric   MIBLO->getOperand(3).setIsKill();
19980b57cec5SDimitry Andric 
19990b57cec5SDimitry Andric   MI.eraseFromParent();
20000b57cec5SDimitry Andric   return true;
20010b57cec5SDimitry Andric }
20020b57cec5SDimitry Andric 
200304eeddc0SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)200404eeddc0SDimitry Andric bool AVRExpandPseudo::expand<AVR::ASRWLoRd>(Block &MBB, BlockIt MBBI) {
200504eeddc0SDimitry Andric   MachineInstr &MI = *MBBI;
200604eeddc0SDimitry Andric   Register DstLoReg, DstHiReg;
200704eeddc0SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
200804eeddc0SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
200904eeddc0SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
201004eeddc0SDimitry Andric   bool ImpIsDead = MI.getOperand(2).isDead();
201104eeddc0SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
201204eeddc0SDimitry Andric 
201304eeddc0SDimitry Andric   // asr loreg
201404eeddc0SDimitry Andric   auto MIASR =
201504eeddc0SDimitry Andric       buildMI(MBB, MBBI, AVR::ASRRd)
201604eeddc0SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
201704eeddc0SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill));
201804eeddc0SDimitry Andric 
201904eeddc0SDimitry Andric   if (ImpIsDead)
202004eeddc0SDimitry Andric     MIASR->getOperand(2).setIsDead();
202104eeddc0SDimitry Andric 
202204eeddc0SDimitry Andric   MI.eraseFromParent();
202304eeddc0SDimitry Andric   return true;
202404eeddc0SDimitry Andric }
202504eeddc0SDimitry Andric 
expandASRW7Rd(Block & MBB,BlockIt MBBI)202681ad6265SDimitry Andric bool AVRExpandPseudo::expandASRW7Rd(Block &MBB, BlockIt MBBI) {
202781ad6265SDimitry Andric   MachineInstr &MI = *MBBI;
202881ad6265SDimitry Andric   Register DstLoReg, DstHiReg;
202981ad6265SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
203081ad6265SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
203181ad6265SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
203281ad6265SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
203381ad6265SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
203481ad6265SDimitry Andric 
203581ad6265SDimitry Andric   // lsl r24
203681ad6265SDimitry Andric   // mov r24,r25
203781ad6265SDimitry Andric   // rol r24
203881ad6265SDimitry Andric   // sbc r25,r25
203981ad6265SDimitry Andric 
204081ad6265SDimitry Andric   // lsl r24 <=> add r24, r24
204181ad6265SDimitry Andric   buildMI(MBB, MBBI, AVR::ADDRdRr)
204281ad6265SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
204381ad6265SDimitry Andric       .addReg(DstLoReg, RegState::Kill)
204481ad6265SDimitry Andric       .addReg(DstLoReg, RegState::Kill);
204581ad6265SDimitry Andric 
204681ad6265SDimitry Andric   // mov r24, r25
204781ad6265SDimitry Andric   buildMI(MBB, MBBI, AVR::MOVRdRr)
204881ad6265SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
204981ad6265SDimitry Andric       .addReg(DstHiReg);
205081ad6265SDimitry Andric 
205181ad6265SDimitry Andric   // rol r24 <=> adc r24, r24
205281ad6265SDimitry Andric   buildMI(MBB, MBBI, AVR::ADCRdRr)
205381ad6265SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
205481ad6265SDimitry Andric       .addReg(DstLoReg, getKillRegState(DstIsKill))
205581ad6265SDimitry Andric       .addReg(DstLoReg, getKillRegState(DstIsKill));
205681ad6265SDimitry Andric 
205781ad6265SDimitry Andric   // sbc r25, r25
205881ad6265SDimitry Andric   auto MISBC =
205981ad6265SDimitry Andric       buildMI(MBB, MBBI, AVR::SBCRdRr)
206081ad6265SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
206181ad6265SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill))
206281ad6265SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill));
206381ad6265SDimitry Andric 
206481ad6265SDimitry Andric   if (ImpIsDead)
206581ad6265SDimitry Andric     MISBC->getOperand(3).setIsDead();
206681ad6265SDimitry Andric   // SREG is always implicitly killed
206781ad6265SDimitry Andric   MISBC->getOperand(4).setIsKill();
206881ad6265SDimitry Andric 
206981ad6265SDimitry Andric   MI.eraseFromParent();
207081ad6265SDimitry Andric   return true;
207181ad6265SDimitry Andric }
207281ad6265SDimitry Andric 
expandASRW8Rd(Block & MBB,BlockIt MBBI)2073fe6060f1SDimitry Andric bool AVRExpandPseudo::expandASRW8Rd(Block &MBB, BlockIt MBBI) {
2074fe6060f1SDimitry Andric   MachineInstr &MI = *MBBI;
2075fe6060f1SDimitry Andric   Register DstLoReg, DstHiReg;
2076fe6060f1SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
2077fe6060f1SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
2078fe6060f1SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
2079fe6060f1SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
2080fe6060f1SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
2081fe6060f1SDimitry Andric 
2082fe6060f1SDimitry Andric   // Move upper byte to lower byte.
2083fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::MOVRdRr)
2084fe6060f1SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
2085fe6060f1SDimitry Andric       .addReg(DstHiReg);
2086fe6060f1SDimitry Andric 
2087fe6060f1SDimitry Andric   // Move the sign bit to the C flag.
2088fe6060f1SDimitry Andric   buildMI(MBB, MBBI, AVR::ADDRdRr)
208981ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
209081ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Kill)
209181ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Kill);
2092fe6060f1SDimitry Andric 
2093fe6060f1SDimitry Andric   // Set upper byte to 0 or -1.
2094fe6060f1SDimitry Andric   auto MIBHI =
2095fe6060f1SDimitry Andric       buildMI(MBB, MBBI, AVR::SBCRdRr)
2096fe6060f1SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
2097fe6060f1SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill))
2098fe6060f1SDimitry Andric           .addReg(DstHiReg, getKillRegState(DstIsKill));
209981ad6265SDimitry Andric 
2100fe6060f1SDimitry Andric   if (ImpIsDead)
2101fe6060f1SDimitry Andric     MIBHI->getOperand(3).setIsDead();
210281ad6265SDimitry Andric   // SREG is always implicitly killed
210381ad6265SDimitry Andric   MIBHI->getOperand(4).setIsKill();
210481ad6265SDimitry Andric 
210581ad6265SDimitry Andric   MI.eraseFromParent();
210681ad6265SDimitry Andric   return true;
210781ad6265SDimitry Andric }
expandASRW14Rd(Block & MBB,BlockIt MBBI)210881ad6265SDimitry Andric bool AVRExpandPseudo::expandASRW14Rd(Block &MBB, BlockIt MBBI) {
210981ad6265SDimitry Andric   MachineInstr &MI = *MBBI;
211081ad6265SDimitry Andric   Register DstLoReg, DstHiReg;
211181ad6265SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
211281ad6265SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
211381ad6265SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
211481ad6265SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
211581ad6265SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
211681ad6265SDimitry Andric 
211781ad6265SDimitry Andric   // lsl r25
211881ad6265SDimitry Andric   // sbc r24, r24
211981ad6265SDimitry Andric   // lsl r25
212081ad6265SDimitry Andric   // mov r25, r24
212181ad6265SDimitry Andric   // rol r24
212281ad6265SDimitry Andric 
212381ad6265SDimitry Andric   // lsl r25 <=> add r25, r25
212481ad6265SDimitry Andric   buildMI(MBB, MBBI, AVR::ADDRdRr)
212581ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
212681ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Kill)
212781ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Kill);
212881ad6265SDimitry Andric 
212981ad6265SDimitry Andric   // sbc r24, r24
213081ad6265SDimitry Andric   buildMI(MBB, MBBI, AVR::SBCRdRr)
213181ad6265SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
213281ad6265SDimitry Andric       .addReg(DstLoReg, RegState::Kill)
213381ad6265SDimitry Andric       .addReg(DstLoReg, RegState::Kill);
213481ad6265SDimitry Andric 
213581ad6265SDimitry Andric   // lsl r25 <=> add r25, r25
213681ad6265SDimitry Andric   buildMI(MBB, MBBI, AVR::ADDRdRr)
213781ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
213881ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Kill)
213981ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Kill);
214081ad6265SDimitry Andric 
214181ad6265SDimitry Andric   // mov r25, r24
214281ad6265SDimitry Andric   buildMI(MBB, MBBI, AVR::MOVRdRr)
214381ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
214481ad6265SDimitry Andric       .addReg(DstLoReg);
214581ad6265SDimitry Andric 
214681ad6265SDimitry Andric   // rol r24 <=> adc r24, r24
214781ad6265SDimitry Andric   auto MIROL =
214881ad6265SDimitry Andric       buildMI(MBB, MBBI, AVR::ADCRdRr)
214981ad6265SDimitry Andric           .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
215081ad6265SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill))
215181ad6265SDimitry Andric           .addReg(DstLoReg, getKillRegState(DstIsKill));
215281ad6265SDimitry Andric 
215381ad6265SDimitry Andric   if (ImpIsDead)
215481ad6265SDimitry Andric     MIROL->getOperand(3).setIsDead();
215581ad6265SDimitry Andric   // SREG is always implicitly killed
215681ad6265SDimitry Andric   MIROL->getOperand(4).setIsKill();
215781ad6265SDimitry Andric 
215881ad6265SDimitry Andric   MI.eraseFromParent();
215981ad6265SDimitry Andric   return false;
216081ad6265SDimitry Andric }
216181ad6265SDimitry Andric 
expandASRW15Rd(Block & MBB,BlockIt MBBI)216281ad6265SDimitry Andric bool AVRExpandPseudo::expandASRW15Rd(Block &MBB, BlockIt MBBI) {
216381ad6265SDimitry Andric   MachineInstr &MI = *MBBI;
216481ad6265SDimitry Andric   Register DstLoReg, DstHiReg;
216581ad6265SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
216681ad6265SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
216781ad6265SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
216881ad6265SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
216981ad6265SDimitry Andric 
217081ad6265SDimitry Andric   // lsl r25
217181ad6265SDimitry Andric   // sbc r25, r25
217281ad6265SDimitry Andric   // mov r24, r25
217381ad6265SDimitry Andric 
217481ad6265SDimitry Andric   // lsl r25 <=> add r25, r25
217581ad6265SDimitry Andric   buildMI(MBB, MBBI, AVR::ADDRdRr)
217681ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Define)
217781ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Kill)
217881ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Kill);
217981ad6265SDimitry Andric 
218081ad6265SDimitry Andric   // sbc r25, r25
218181ad6265SDimitry Andric   auto MISBC =
218281ad6265SDimitry Andric       buildMI(MBB, MBBI, AVR::SBCRdRr)
218381ad6265SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
218481ad6265SDimitry Andric           .addReg(DstHiReg, RegState::Kill)
218581ad6265SDimitry Andric           .addReg(DstHiReg, RegState::Kill);
218681ad6265SDimitry Andric   if (ImpIsDead)
218781ad6265SDimitry Andric     MISBC->getOperand(3).setIsDead();
218881ad6265SDimitry Andric   // SREG is always implicitly killed
218981ad6265SDimitry Andric   MISBC->getOperand(4).setIsKill();
219081ad6265SDimitry Andric 
219181ad6265SDimitry Andric   // mov r24, r25
219281ad6265SDimitry Andric   buildMI(MBB, MBBI, AVR::MOVRdRr)
219381ad6265SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
219481ad6265SDimitry Andric       .addReg(DstHiReg);
2195fe6060f1SDimitry Andric 
2196fe6060f1SDimitry Andric   MI.eraseFromParent();
2197fe6060f1SDimitry Andric   return true;
2198fe6060f1SDimitry Andric }
2199fe6060f1SDimitry Andric 
2200e8d8bef9SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)2201fe6060f1SDimitry Andric bool AVRExpandPseudo::expand<AVR::ASRWNRd>(Block &MBB, BlockIt MBBI) {
2202fe6060f1SDimitry Andric   MachineInstr &MI = *MBBI;
2203fe6060f1SDimitry Andric   unsigned Imm = MI.getOperand(2).getImm();
2204fe6060f1SDimitry Andric   switch (Imm) {
220581ad6265SDimitry Andric   case 7:
220681ad6265SDimitry Andric     return expandASRW7Rd(MBB, MBBI);
2207fe6060f1SDimitry Andric   case 8:
2208fe6060f1SDimitry Andric     return expandASRW8Rd(MBB, MBBI);
220981ad6265SDimitry Andric   case 14:
221081ad6265SDimitry Andric     return expandASRW14Rd(MBB, MBBI);
221181ad6265SDimitry Andric   case 15:
221281ad6265SDimitry Andric     return expandASRW15Rd(MBB, MBBI);
2213fe6060f1SDimitry Andric   default:
2214fe6060f1SDimitry Andric     llvm_unreachable("unimplemented asrwn");
2215fe6060f1SDimitry Andric     return false;
2216fe6060f1SDimitry Andric   }
2217fe6060f1SDimitry Andric }
2218fe6060f1SDimitry Andric 
expandLSLB7Rd(Block & MBB,BlockIt MBBI)2219fe6060f1SDimitry Andric bool AVRExpandPseudo::expandLSLB7Rd(Block &MBB, BlockIt MBBI) {
2220e8d8bef9SDimitry Andric   MachineInstr &MI = *MBBI;
2221e8d8bef9SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
2222e8d8bef9SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
2223e8d8bef9SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
2224fe6060f1SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
2225e8d8bef9SDimitry Andric 
2226e8d8bef9SDimitry Andric   // ror r24
2227e8d8bef9SDimitry Andric   // clr r24
2228e8d8bef9SDimitry Andric   // ror r24
2229e8d8bef9SDimitry Andric 
2230e8d8bef9SDimitry Andric   buildMI(MBB, MBBI, AVR::RORRd)
2231e8d8bef9SDimitry Andric       .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
223281ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill)
2233349cc55cSDimitry Andric       ->getOperand(3)
2234349cc55cSDimitry Andric       .setIsUndef(true);
2235e8d8bef9SDimitry Andric 
2236e8d8bef9SDimitry Andric   buildMI(MBB, MBBI, AVR::EORRdRr)
2237e8d8bef9SDimitry Andric       .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
223881ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill)
223981ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill);
2240e8d8bef9SDimitry Andric 
2241e8d8bef9SDimitry Andric   auto MIRRC =
2242e8d8bef9SDimitry Andric       buildMI(MBB, MBBI, AVR::RORRd)
2243e8d8bef9SDimitry Andric           .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
2244e8d8bef9SDimitry Andric           .addReg(DstReg, getKillRegState(DstIsKill));
2245e8d8bef9SDimitry Andric 
2246e8d8bef9SDimitry Andric   if (ImpIsDead)
2247e8d8bef9SDimitry Andric     MIRRC->getOperand(2).setIsDead();
2248e8d8bef9SDimitry Andric 
2249e8d8bef9SDimitry Andric   // SREG is always implicitly killed
2250e8d8bef9SDimitry Andric   MIRRC->getOperand(3).setIsKill();
2251e8d8bef9SDimitry Andric 
2252e8d8bef9SDimitry Andric   MI.eraseFromParent();
2253e8d8bef9SDimitry Andric   return true;
2254e8d8bef9SDimitry Andric }
2255e8d8bef9SDimitry Andric 
2256e8d8bef9SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)2257fe6060f1SDimitry Andric bool AVRExpandPseudo::expand<AVR::LSLBNRd>(Block &MBB, BlockIt MBBI) {
2258fe6060f1SDimitry Andric   MachineInstr &MI = *MBBI;
2259fe6060f1SDimitry Andric   unsigned Imm = MI.getOperand(2).getImm();
2260fe6060f1SDimitry Andric   switch (Imm) {
2261fe6060f1SDimitry Andric   case 7:
2262fe6060f1SDimitry Andric     return expandLSLB7Rd(MBB, MBBI);
2263fe6060f1SDimitry Andric   default:
2264fe6060f1SDimitry Andric     llvm_unreachable("unimplemented lslbn");
2265fe6060f1SDimitry Andric     return false;
2266fe6060f1SDimitry Andric   }
2267fe6060f1SDimitry Andric }
2268fe6060f1SDimitry Andric 
expandLSRB7Rd(Block & MBB,BlockIt MBBI)2269fe6060f1SDimitry Andric bool AVRExpandPseudo::expandLSRB7Rd(Block &MBB, BlockIt MBBI) {
2270e8d8bef9SDimitry Andric   MachineInstr &MI = *MBBI;
2271e8d8bef9SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
2272e8d8bef9SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
2273e8d8bef9SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
2274fe6060f1SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
2275e8d8bef9SDimitry Andric 
2276e8d8bef9SDimitry Andric   // rol r24
2277e8d8bef9SDimitry Andric   // clr r24
2278e8d8bef9SDimitry Andric   // rol r24
2279e8d8bef9SDimitry Andric 
2280e8d8bef9SDimitry Andric   buildMI(MBB, MBBI, AVR::ADCRdRr)
2281e8d8bef9SDimitry Andric       .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
228281ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill)
228381ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill)
2284349cc55cSDimitry Andric       ->getOperand(4)
2285349cc55cSDimitry Andric       .setIsUndef(true);
2286e8d8bef9SDimitry Andric 
2287e8d8bef9SDimitry Andric   buildMI(MBB, MBBI, AVR::EORRdRr)
2288e8d8bef9SDimitry Andric       .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
228981ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill)
229081ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill);
2291e8d8bef9SDimitry Andric 
2292e8d8bef9SDimitry Andric   auto MIRRC =
2293e8d8bef9SDimitry Andric       buildMI(MBB, MBBI, AVR::ADCRdRr)
2294e8d8bef9SDimitry Andric           .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
2295e8d8bef9SDimitry Andric           .addReg(DstReg, getKillRegState(DstIsKill))
2296e8d8bef9SDimitry Andric           .addReg(DstReg, getKillRegState(DstIsKill));
2297e8d8bef9SDimitry Andric 
2298e8d8bef9SDimitry Andric   if (ImpIsDead)
2299e8d8bef9SDimitry Andric     MIRRC->getOperand(3).setIsDead();
2300e8d8bef9SDimitry Andric 
2301e8d8bef9SDimitry Andric   // SREG is always implicitly killed
2302e8d8bef9SDimitry Andric   MIRRC->getOperand(4).setIsKill();
2303e8d8bef9SDimitry Andric 
2304e8d8bef9SDimitry Andric   MI.eraseFromParent();
2305e8d8bef9SDimitry Andric   return true;
2306e8d8bef9SDimitry Andric }
2307e8d8bef9SDimitry Andric 
2308e8d8bef9SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)2309fe6060f1SDimitry Andric bool AVRExpandPseudo::expand<AVR::LSRBNRd>(Block &MBB, BlockIt MBBI) {
2310fe6060f1SDimitry Andric   MachineInstr &MI = *MBBI;
2311fe6060f1SDimitry Andric   unsigned Imm = MI.getOperand(2).getImm();
2312fe6060f1SDimitry Andric   switch (Imm) {
2313fe6060f1SDimitry Andric   case 7:
2314fe6060f1SDimitry Andric     return expandLSRB7Rd(MBB, MBBI);
2315fe6060f1SDimitry Andric   default:
2316fe6060f1SDimitry Andric     llvm_unreachable("unimplemented lsrbn");
2317fe6060f1SDimitry Andric     return false;
2318fe6060f1SDimitry Andric   }
2319fe6060f1SDimitry Andric }
2320fe6060f1SDimitry Andric 
expandASRB6Rd(Block & MBB,BlockIt MBBI)232104eeddc0SDimitry Andric bool AVRExpandPseudo::expandASRB6Rd(Block &MBB, BlockIt MBBI) {
232204eeddc0SDimitry Andric   MachineInstr &MI = *MBBI;
232304eeddc0SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
232404eeddc0SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
232504eeddc0SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
232604eeddc0SDimitry Andric 
232704eeddc0SDimitry Andric   // bst r24, 6
232804eeddc0SDimitry Andric   // lsl r24
232904eeddc0SDimitry Andric   // sbc r24, r24
233004eeddc0SDimitry Andric   // bld r24, 0
233104eeddc0SDimitry Andric 
233204eeddc0SDimitry Andric   buildMI(MBB, MBBI, AVR::BST)
233304eeddc0SDimitry Andric       .addReg(DstReg)
233404eeddc0SDimitry Andric       .addImm(6)
233504eeddc0SDimitry Andric       ->getOperand(2)
233604eeddc0SDimitry Andric       .setIsUndef(true);
233704eeddc0SDimitry Andric 
233804eeddc0SDimitry Andric   buildMI(MBB, MBBI, AVR::ADDRdRr) // LSL Rd <==> ADD Rd, Rd
233904eeddc0SDimitry Andric       .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
234081ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill)
234181ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill);
234204eeddc0SDimitry Andric 
234304eeddc0SDimitry Andric   buildMI(MBB, MBBI, AVR::SBCRdRr)
234404eeddc0SDimitry Andric       .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
234581ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill)
234681ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill);
234704eeddc0SDimitry Andric 
234804eeddc0SDimitry Andric   buildMI(MBB, MBBI, AVR::BLD)
234904eeddc0SDimitry Andric       .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
235004eeddc0SDimitry Andric       .addReg(DstReg, getKillRegState(DstIsKill))
235104eeddc0SDimitry Andric       .addImm(0)
235204eeddc0SDimitry Andric       ->getOperand(3)
235304eeddc0SDimitry Andric       .setIsKill();
235404eeddc0SDimitry Andric 
235504eeddc0SDimitry Andric   MI.eraseFromParent();
235604eeddc0SDimitry Andric   return true;
235704eeddc0SDimitry Andric }
235804eeddc0SDimitry Andric 
expandASRB7Rd(Block & MBB,BlockIt MBBI)2359fe6060f1SDimitry Andric bool AVRExpandPseudo::expandASRB7Rd(Block &MBB, BlockIt MBBI) {
2360e8d8bef9SDimitry Andric   MachineInstr &MI = *MBBI;
2361e8d8bef9SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
2362e8d8bef9SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
2363e8d8bef9SDimitry Andric   bool DstIsKill = MI.getOperand(1).isKill();
2364fe6060f1SDimitry Andric   bool ImpIsDead = MI.getOperand(3).isDead();
2365e8d8bef9SDimitry Andric 
2366e8d8bef9SDimitry Andric   // lsl r24
2367e8d8bef9SDimitry Andric   // sbc r24, r24
2368e8d8bef9SDimitry Andric 
2369e8d8bef9SDimitry Andric   buildMI(MBB, MBBI, AVR::ADDRdRr)
2370e8d8bef9SDimitry Andric       .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
237181ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill)
237281ad6265SDimitry Andric       .addReg(DstReg, RegState::Kill);
2373e8d8bef9SDimitry Andric 
2374349cc55cSDimitry Andric   auto MIRRC =
2375349cc55cSDimitry Andric       buildMI(MBB, MBBI, AVR::SBCRdRr)
2376e8d8bef9SDimitry Andric           .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
2377e8d8bef9SDimitry Andric           .addReg(DstReg, getKillRegState(DstIsKill))
2378e8d8bef9SDimitry Andric           .addReg(DstReg, getKillRegState(DstIsKill));
2379e8d8bef9SDimitry Andric 
2380e8d8bef9SDimitry Andric   if (ImpIsDead)
2381e8d8bef9SDimitry Andric     MIRRC->getOperand(3).setIsDead();
2382e8d8bef9SDimitry Andric 
2383e8d8bef9SDimitry Andric   // SREG is always implicitly killed
2384e8d8bef9SDimitry Andric   MIRRC->getOperand(4).setIsKill();
2385e8d8bef9SDimitry Andric 
2386e8d8bef9SDimitry Andric   MI.eraseFromParent();
2387e8d8bef9SDimitry Andric   return true;
2388e8d8bef9SDimitry Andric }
2389e8d8bef9SDimitry Andric 
2390fe6060f1SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)2391fe6060f1SDimitry Andric bool AVRExpandPseudo::expand<AVR::ASRBNRd>(Block &MBB, BlockIt MBBI) {
2392fe6060f1SDimitry Andric   MachineInstr &MI = *MBBI;
2393fe6060f1SDimitry Andric   unsigned Imm = MI.getOperand(2).getImm();
2394fe6060f1SDimitry Andric   switch (Imm) {
239504eeddc0SDimitry Andric   case 6:
239604eeddc0SDimitry Andric     return expandASRB6Rd(MBB, MBBI);
2397fe6060f1SDimitry Andric   case 7:
2398fe6060f1SDimitry Andric     return expandASRB7Rd(MBB, MBBI);
2399fe6060f1SDimitry Andric   default:
2400fe6060f1SDimitry Andric     llvm_unreachable("unimplemented asrbn");
2401fe6060f1SDimitry Andric     return false;
2402fe6060f1SDimitry Andric   }
2403fe6060f1SDimitry Andric }
2404fe6060f1SDimitry Andric 
expand(Block & MBB,BlockIt MBBI)24050b57cec5SDimitry Andric template <> bool AVRExpandPseudo::expand<AVR::SEXT>(Block &MBB, BlockIt MBBI) {
24060b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
24075ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
24080b57cec5SDimitry Andric   // sext R17:R16, R17
24090b57cec5SDimitry Andric   // mov     r16, r17
24100b57cec5SDimitry Andric   // lsl     r17
24110b57cec5SDimitry Andric   // sbc     r17, r17
24120b57cec5SDimitry Andric   // sext R17:R16, R13
24130b57cec5SDimitry Andric   // mov     r16, r13
24140b57cec5SDimitry Andric   // mov     r17, r13
24150b57cec5SDimitry Andric   // lsl     r17
24160b57cec5SDimitry Andric   // sbc     r17, r17
24170b57cec5SDimitry Andric   // sext R17:R16, R16
24180b57cec5SDimitry Andric   // mov     r17, r16
24190b57cec5SDimitry Andric   // lsl     r17
24200b57cec5SDimitry Andric   // sbc     r17, r17
24215ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
24225ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
24230b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
24240b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
24250b57cec5SDimitry Andric   bool ImpIsDead = MI.getOperand(2).isDead();
24260b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
24270b57cec5SDimitry Andric 
242881ad6265SDimitry Andric   if (SrcReg != DstLoReg)
2429349cc55cSDimitry Andric     buildMI(MBB, MBBI, AVR::MOVRdRr)
24300b57cec5SDimitry Andric         .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
24310b57cec5SDimitry Andric         .addReg(SrcReg);
24320b57cec5SDimitry Andric 
24330b57cec5SDimitry Andric   if (SrcReg != DstHiReg) {
243481ad6265SDimitry Andric     auto MOV = buildMI(MBB, MBBI, AVR::MOVRdRr)
24350b57cec5SDimitry Andric                    .addReg(DstHiReg, RegState::Define)
243681ad6265SDimitry Andric                    .addReg(SrcReg);
243781ad6265SDimitry Andric     if (SrcReg != DstLoReg && SrcIsKill)
243881ad6265SDimitry Andric       MOV->getOperand(1).setIsKill();
24390b57cec5SDimitry Andric   }
24400b57cec5SDimitry Andric 
24410b57cec5SDimitry Andric   buildMI(MBB, MBBI, AVR::ADDRdRr) // LSL Rd <==> ADD Rd, Rr
24420b57cec5SDimitry Andric       .addReg(DstHiReg, RegState::Define)
244381ad6265SDimitry Andric       .addReg(DstHiReg, RegState::Kill)
24440b57cec5SDimitry Andric       .addReg(DstHiReg, RegState::Kill);
24450b57cec5SDimitry Andric 
2446349cc55cSDimitry Andric   auto SBC =
2447349cc55cSDimitry Andric       buildMI(MBB, MBBI, AVR::SBCRdRr)
24480b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
24490b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Kill)
24500b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Kill);
24510b57cec5SDimitry Andric 
24520b57cec5SDimitry Andric   if (ImpIsDead)
24530b57cec5SDimitry Andric     SBC->getOperand(3).setIsDead();
24540b57cec5SDimitry Andric 
24550b57cec5SDimitry Andric   // SREG is always implicitly killed
24560b57cec5SDimitry Andric   SBC->getOperand(4).setIsKill();
24570b57cec5SDimitry Andric 
24580b57cec5SDimitry Andric   MI.eraseFromParent();
24590b57cec5SDimitry Andric   return true;
24600b57cec5SDimitry Andric }
24610b57cec5SDimitry Andric 
expand(Block & MBB,BlockIt MBBI)24620b57cec5SDimitry Andric template <> bool AVRExpandPseudo::expand<AVR::ZEXT>(Block &MBB, BlockIt MBBI) {
24630b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
24645ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
24650b57cec5SDimitry Andric   // zext R25:R24, R20
24660b57cec5SDimitry Andric   // mov      R24, R20
24670b57cec5SDimitry Andric   // eor      R25, R25
24680b57cec5SDimitry Andric   // zext R25:R24, R24
24690b57cec5SDimitry Andric   // eor      R25, R25
24700b57cec5SDimitry Andric   // zext R25:R24, R25
24710b57cec5SDimitry Andric   // mov      R24, R25
24720b57cec5SDimitry Andric   // eor      R25, R25
24735ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
24745ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
24750b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
24760b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
24770b57cec5SDimitry Andric   bool ImpIsDead = MI.getOperand(2).isDead();
24780b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
24790b57cec5SDimitry Andric 
24800b57cec5SDimitry Andric   if (SrcReg != DstLoReg) {
24810b57cec5SDimitry Andric     buildMI(MBB, MBBI, AVR::MOVRdRr)
24820b57cec5SDimitry Andric         .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
24830b57cec5SDimitry Andric         .addReg(SrcReg, getKillRegState(SrcIsKill));
24840b57cec5SDimitry Andric   }
24850b57cec5SDimitry Andric 
2486349cc55cSDimitry Andric   auto EOR =
2487349cc55cSDimitry Andric       buildMI(MBB, MBBI, AVR::EORRdRr)
24880b57cec5SDimitry Andric           .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
2489fe6060f1SDimitry Andric           .addReg(DstHiReg, RegState::Kill | RegState::Undef)
2490fe6060f1SDimitry Andric           .addReg(DstHiReg, RegState::Kill | RegState::Undef);
24910b57cec5SDimitry Andric 
24920b57cec5SDimitry Andric   if (ImpIsDead)
24930b57cec5SDimitry Andric     EOR->getOperand(3).setIsDead();
24940b57cec5SDimitry Andric 
24950b57cec5SDimitry Andric   MI.eraseFromParent();
24960b57cec5SDimitry Andric   return true;
24970b57cec5SDimitry Andric }
24980b57cec5SDimitry Andric 
24990b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)25000b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::SPREAD>(Block &MBB, BlockIt MBBI) {
25010b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
25025ffd83dbSDimitry Andric   Register DstLoReg, DstHiReg;
25035ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
25040b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
25050b57cec5SDimitry Andric   unsigned Flags = MI.getFlags();
25065ffd83dbSDimitry Andric   unsigned OpLo = AVR::INRdA;
25075ffd83dbSDimitry Andric   unsigned OpHi = AVR::INRdA;
25080b57cec5SDimitry Andric   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
25090b57cec5SDimitry Andric 
25100b57cec5SDimitry Andric   // Low part
25110b57cec5SDimitry Andric   buildMI(MBB, MBBI, OpLo)
25120b57cec5SDimitry Andric       .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
25130b57cec5SDimitry Andric       .addImm(0x3d)
25140b57cec5SDimitry Andric       .setMIFlags(Flags);
25150b57cec5SDimitry Andric 
25160b57cec5SDimitry Andric   // High part
25170b57cec5SDimitry Andric   buildMI(MBB, MBBI, OpHi)
25180b57cec5SDimitry Andric       .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
25190b57cec5SDimitry Andric       .addImm(0x3e)
25200b57cec5SDimitry Andric       .setMIFlags(Flags);
25210b57cec5SDimitry Andric 
25220b57cec5SDimitry Andric   MI.eraseFromParent();
25230b57cec5SDimitry Andric   return true;
25240b57cec5SDimitry Andric }
25250b57cec5SDimitry Andric 
25260b57cec5SDimitry Andric template <>
expand(Block & MBB,BlockIt MBBI)25270b57cec5SDimitry Andric bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
252881ad6265SDimitry Andric   const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
25290b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
25305ffd83dbSDimitry Andric   Register SrcLoReg, SrcHiReg;
25315ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
25320b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(1).isKill();
25330b57cec5SDimitry Andric   unsigned Flags = MI.getFlags();
25340b57cec5SDimitry Andric   TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
25350b57cec5SDimitry Andric 
25360b57cec5SDimitry Andric   buildMI(MBB, MBBI, AVR::INRdA)
2537bdd1243dSDimitry Andric       .addReg(STI.getTmpRegister(), RegState::Define)
253881ad6265SDimitry Andric       .addImm(STI.getIORegSREG())
25390b57cec5SDimitry Andric       .setMIFlags(Flags);
25400b57cec5SDimitry Andric 
25410b57cec5SDimitry Andric   buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
25420b57cec5SDimitry Andric 
25430b57cec5SDimitry Andric   buildMI(MBB, MBBI, AVR::OUTARr)
25440b57cec5SDimitry Andric       .addImm(0x3e)
25450b57cec5SDimitry Andric       .addReg(SrcHiReg, getKillRegState(SrcIsKill))
25460b57cec5SDimitry Andric       .setMIFlags(Flags);
25470b57cec5SDimitry Andric 
25480b57cec5SDimitry Andric   buildMI(MBB, MBBI, AVR::OUTARr)
254981ad6265SDimitry Andric       .addImm(STI.getIORegSREG())
2550bdd1243dSDimitry Andric       .addReg(STI.getTmpRegister(), RegState::Kill)
25510b57cec5SDimitry Andric       .setMIFlags(Flags);
25520b57cec5SDimitry Andric 
25530b57cec5SDimitry Andric   buildMI(MBB, MBBI, AVR::OUTARr)
25540b57cec5SDimitry Andric       .addImm(0x3d)
25550b57cec5SDimitry Andric       .addReg(SrcLoReg, getKillRegState(SrcIsKill))
25560b57cec5SDimitry Andric       .setMIFlags(Flags);
25570b57cec5SDimitry Andric 
25580b57cec5SDimitry Andric   MI.eraseFromParent();
25590b57cec5SDimitry Andric   return true;
25600b57cec5SDimitry Andric }
25610b57cec5SDimitry Andric 
expandMI(Block & MBB,BlockIt MBBI)25620b57cec5SDimitry Andric bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
25630b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
25640b57cec5SDimitry Andric   int Opcode = MBBI->getOpcode();
25650b57cec5SDimitry Andric 
25660b57cec5SDimitry Andric #define EXPAND(Op)                                                             \
25670b57cec5SDimitry Andric   case Op:                                                                     \
25680b57cec5SDimitry Andric     return expand<Op>(MBB, MI)
25690b57cec5SDimitry Andric 
25700b57cec5SDimitry Andric   switch (Opcode) {
25710b57cec5SDimitry Andric     EXPAND(AVR::ADDWRdRr);
25720b57cec5SDimitry Andric     EXPAND(AVR::ADCWRdRr);
25730b57cec5SDimitry Andric     EXPAND(AVR::SUBWRdRr);
25740b57cec5SDimitry Andric     EXPAND(AVR::SUBIWRdK);
25750b57cec5SDimitry Andric     EXPAND(AVR::SBCWRdRr);
25760b57cec5SDimitry Andric     EXPAND(AVR::SBCIWRdK);
25770b57cec5SDimitry Andric     EXPAND(AVR::ANDWRdRr);
25780b57cec5SDimitry Andric     EXPAND(AVR::ANDIWRdK);
25790b57cec5SDimitry Andric     EXPAND(AVR::ORWRdRr);
25800b57cec5SDimitry Andric     EXPAND(AVR::ORIWRdK);
25810b57cec5SDimitry Andric     EXPAND(AVR::EORWRdRr);
25820b57cec5SDimitry Andric     EXPAND(AVR::COMWRd);
2583e8d8bef9SDimitry Andric     EXPAND(AVR::NEGWRd);
25840b57cec5SDimitry Andric     EXPAND(AVR::CPWRdRr);
25850b57cec5SDimitry Andric     EXPAND(AVR::CPCWRdRr);
25860b57cec5SDimitry Andric     EXPAND(AVR::LDIWRdK);
25870b57cec5SDimitry Andric     EXPAND(AVR::LDSWRdK);
25880b57cec5SDimitry Andric     EXPAND(AVR::LDWRdPtr);
25890b57cec5SDimitry Andric     EXPAND(AVR::LDWRdPtrPi);
25900b57cec5SDimitry Andric     EXPAND(AVR::LDWRdPtrPd);
25910b57cec5SDimitry Andric   case AVR::LDDWRdYQ: //: FIXME: remove this once PR13375 gets fixed
25920b57cec5SDimitry Andric     EXPAND(AVR::LDDWRdPtrQ);
2593*06c3fb27SDimitry Andric     EXPAND(AVR::LPMBRdZ);
25940b57cec5SDimitry Andric     EXPAND(AVR::LPMWRdZ);
25950b57cec5SDimitry Andric     EXPAND(AVR::LPMWRdZPi);
259604eeddc0SDimitry Andric     EXPAND(AVR::ELPMBRdZ);
259704eeddc0SDimitry Andric     EXPAND(AVR::ELPMWRdZ);
259804eeddc0SDimitry Andric     EXPAND(AVR::ELPMBRdZPi);
259904eeddc0SDimitry Andric     EXPAND(AVR::ELPMWRdZPi);
26000b57cec5SDimitry Andric     EXPAND(AVR::AtomicLoad8);
26010b57cec5SDimitry Andric     EXPAND(AVR::AtomicLoad16);
26020b57cec5SDimitry Andric     EXPAND(AVR::AtomicStore8);
26030b57cec5SDimitry Andric     EXPAND(AVR::AtomicStore16);
26040b57cec5SDimitry Andric     EXPAND(AVR::AtomicFence);
26050b57cec5SDimitry Andric     EXPAND(AVR::STSWKRr);
26060b57cec5SDimitry Andric     EXPAND(AVR::STWPtrRr);
26070b57cec5SDimitry Andric     EXPAND(AVR::STWPtrPiRr);
26080b57cec5SDimitry Andric     EXPAND(AVR::STWPtrPdRr);
26090b57cec5SDimitry Andric     EXPAND(AVR::STDWPtrQRr);
261081ad6265SDimitry Andric     EXPAND(AVR::STDSPQRr);
261181ad6265SDimitry Andric     EXPAND(AVR::STDWSPQRr);
26120b57cec5SDimitry Andric     EXPAND(AVR::INWRdA);
26130b57cec5SDimitry Andric     EXPAND(AVR::OUTWARr);
26140b57cec5SDimitry Andric     EXPAND(AVR::PUSHWRr);
26150b57cec5SDimitry Andric     EXPAND(AVR::POPWRd);
2616*06c3fb27SDimitry Andric     EXPAND(AVR::ROLBRdR1);
2617*06c3fb27SDimitry Andric     EXPAND(AVR::ROLBRdR17);
2618480093f4SDimitry Andric     EXPAND(AVR::RORBRd);
26190b57cec5SDimitry Andric     EXPAND(AVR::LSLWRd);
26200b57cec5SDimitry Andric     EXPAND(AVR::LSRWRd);
26210b57cec5SDimitry Andric     EXPAND(AVR::RORWRd);
26220b57cec5SDimitry Andric     EXPAND(AVR::ROLWRd);
26230b57cec5SDimitry Andric     EXPAND(AVR::ASRWRd);
262404eeddc0SDimitry Andric     EXPAND(AVR::LSLWHiRd);
262504eeddc0SDimitry Andric     EXPAND(AVR::LSRWLoRd);
262604eeddc0SDimitry Andric     EXPAND(AVR::ASRWLoRd);
2627fe6060f1SDimitry Andric     EXPAND(AVR::LSLWNRd);
2628fe6060f1SDimitry Andric     EXPAND(AVR::LSRWNRd);
2629fe6060f1SDimitry Andric     EXPAND(AVR::ASRWNRd);
2630fe6060f1SDimitry Andric     EXPAND(AVR::LSLBNRd);
2631fe6060f1SDimitry Andric     EXPAND(AVR::LSRBNRd);
2632fe6060f1SDimitry Andric     EXPAND(AVR::ASRBNRd);
26330b57cec5SDimitry Andric     EXPAND(AVR::SEXT);
26340b57cec5SDimitry Andric     EXPAND(AVR::ZEXT);
26350b57cec5SDimitry Andric     EXPAND(AVR::SPREAD);
26360b57cec5SDimitry Andric     EXPAND(AVR::SPWRITE);
26370b57cec5SDimitry Andric   }
26380b57cec5SDimitry Andric #undef EXPAND
26390b57cec5SDimitry Andric   return false;
26400b57cec5SDimitry Andric }
26410b57cec5SDimitry Andric 
26420b57cec5SDimitry Andric } // end of anonymous namespace
26430b57cec5SDimitry Andric 
2644349cc55cSDimitry Andric INITIALIZE_PASS(AVRExpandPseudo, "avr-expand-pseudo", AVR_EXPAND_PSEUDO_NAME,
2645349cc55cSDimitry Andric                 false, false)
26460b57cec5SDimitry Andric namespace llvm {
26470b57cec5SDimitry Andric 
createAVRExpandPseudoPass()26480b57cec5SDimitry Andric FunctionPass *createAVRExpandPseudoPass() { return new AVRExpandPseudo(); }
26490b57cec5SDimitry Andric 
26500b57cec5SDimitry Andric } // end of namespace llvm
2651