Merging r314898:
authorDylan McKay <me@dylanmckay.io>
Sat, 14 Oct 2017 22:31:06 +0000 (22:31 +0000)
committerDylan McKay <me@dylanmckay.io>
Sat, 14 Oct 2017 22:31:06 +0000 (22:31 +0000)
------------------------------------------------------------------------
r314898 | dylanmckay | 2017-10-04 23:37:22 +1300 (Wed, 04 Oct 2017) | 6 lines

[AVR] Implement LPMWRdZ pseudo-instruction's expansion.

FIXME: implementation is mostly copy-pasted from LDWRdPtr, so we should
refactor a bit and unify the two

Patch by Gerdo Erdi.
------------------------------------------------------------------------

git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_50@315836 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/AVR/AVRExpandPseudoInsts.cpp

index 9969fda3a56a99e4978ecffbdd5697a895339acc..d6f85edae47c5a09a20e503724abae4118dc853b 100644 (file)
@@ -743,7 +743,50 @@ bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
 
 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 <>