template <>
bool AVRExpandPseudo::expand<AVR::LPMWRdZ>(Block &MBB, BlockIt MBBI) {
- llvm_unreachable("wide LPM is unimplemented");
+ MachineInstr &MI = *MBBI;
+ unsigned OpLo, OpHi, DstLoReg, DstHiReg;
+ unsigned DstReg = MI.getOperand(0).getReg();
+ unsigned TmpReg = 0; // 0 for no temporary register
+ unsigned SrcReg = MI.getOperand(1).getReg();
+ bool SrcIsKill = MI.getOperand(1).isKill();
+ OpLo = AVR::LPMRdZPi;
+ OpHi = AVR::LPMRdZ;
+ TRI->splitReg(DstReg, DstLoReg, DstHiReg);
+
+ // Use a temporary register if src and dst registers are the same.
+ if (DstReg == SrcReg)
+ TmpReg = scavengeGPR8(MI);
+
+ unsigned CurDstLoReg = (DstReg == SrcReg) ? TmpReg : DstLoReg;
+ unsigned CurDstHiReg = (DstReg == SrcReg) ? TmpReg : DstHiReg;
+
+ // Load low byte.
+ auto MIBLO = buildMI(MBB, MBBI, OpLo)
+ .addReg(CurDstLoReg, RegState::Define)
+ .addReg(SrcReg);
+
+ // Push low byte onto stack if necessary.
+ if (TmpReg)
+ buildMI(MBB, MBBI, AVR::PUSHRr).addReg(TmpReg);
+
+ // Load high byte.
+ auto MIBHI = buildMI(MBB, MBBI, OpHi)
+ .addReg(CurDstHiReg, RegState::Define)
+ .addReg(SrcReg, getKillRegState(SrcIsKill));
+
+ if (TmpReg) {
+ // Move the high byte into the final destination.
+ buildMI(MBB, MBBI, AVR::MOVRdRr).addReg(DstHiReg).addReg(TmpReg);
+
+ // Move the low byte from the scratch space into the final destination.
+ buildMI(MBB, MBBI, AVR::POPRd).addReg(DstLoReg);
+ }
+
+ MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
+ MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
+
+ MI.eraseFromParent();
+ return true;
}
template <>