diff options
author | Dylan McKay <me@dylanmckay.io> | 2017-10-15 01:31:06 +0300 |
---|---|---|
committer | Dylan McKay <me@dylanmckay.io> | 2017-10-15 01:31:06 +0300 |
commit | 5945e5f25b09d882407b949778247155db64f81a (patch) | |
tree | 11ff91f17fc666772cb597a681e671393381487c | |
parent | c201f2417a3f78ab63e0c1a12855e7ea74aa7f69 (diff) |
Merging r314898:
------------------------------------------------------------------------
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.
------------------------------------------------------------------------
llvm-svn: 315836
-rw-r--r-- | llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp index 9969fda3a56a..d6f85edae47c 100644 --- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp @@ -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 <> |