summaryrefslogtreecommitdiff
path: root/lib/Target/AVR/AVRFrameLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/AVR/AVRFrameLowering.cpp')
-rw-r--r--lib/Target/AVR/AVRFrameLowering.cpp28
1 files changed, 19 insertions, 9 deletions
diff --git a/lib/Target/AVR/AVRFrameLowering.cpp b/lib/Target/AVR/AVRFrameLowering.cpp
index ab42a7aa99011..25232d2e47e13 100644
--- a/lib/Target/AVR/AVRFrameLowering.cpp
+++ b/lib/Target/AVR/AVRFrameLowering.cpp
@@ -57,6 +57,7 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
const AVRInstrInfo &TII = *STI.getInstrInfo();
+ bool HasFP = hasFP(MF);
// Interrupt handlers re-enable interrupts in function entry.
if (CallConv == CallingConv::AVR_INTR) {
@@ -65,6 +66,13 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
.setMIFlag(MachineInstr::FrameSetup);
}
+ // Save the frame pointer if we have one.
+ if (HasFP) {
+ BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr))
+ .addReg(AVR::R29R28, RegState::Kill)
+ .setMIFlag(MachineInstr::FrameSetup);
+ }
+
// Emit special prologue code to save R1, R0 and SREG in interrupt/signal
// handlers before saving any other registers.
if (CallConv == CallingConv::AVR_INTR ||
@@ -72,6 +80,7 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr))
.addReg(AVR::R1R0, RegState::Kill)
.setMIFlag(MachineInstr::FrameSetup);
+
BuildMI(MBB, MBBI, DL, TII.get(AVR::INRdA), AVR::R0)
.addImm(0x3f)
.setMIFlag(MachineInstr::FrameSetup);
@@ -86,7 +95,7 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
}
// Early exit if the frame pointer is not needed in this function.
- if (!hasFP(MF)) {
+ if (!HasFP) {
return;
}
@@ -165,6 +174,9 @@ void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
BuildMI(MBB, MBBI, DL, TII.get(AVR::POPWRd), AVR::R1R0);
}
+ if (hasFP(MF))
+ BuildMI(MBB, MBBI, DL, TII.get(AVR::POPWRd), AVR::R29R28);
+
// Early exit if there is no need to restore the frame pointer.
if (!FrameSize) {
return;
@@ -216,8 +228,9 @@ void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
bool AVRFrameLowering::hasFP(const MachineFunction &MF) const {
const AVRMachineFunctionInfo *FuncInfo = MF.getInfo<AVRMachineFunctionInfo>();
- return (FuncInfo->getHasSpills() || FuncInfo->getHasAllocas() ||
- FuncInfo->getHasStackArgs());
+ // TODO: We do not always need a frame pointer.
+ // This can be optimised.
+ return true;
}
bool AVRFrameLowering::spillCalleeSavedRegisters(
@@ -407,12 +420,9 @@ void AVRFrameLowering::determineCalleeSaves(MachineFunction &MF,
RegScavenger *RS) const {
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
- // Spill register Y when it is used as the frame pointer.
- if (hasFP(MF)) {
- SavedRegs.set(AVR::R29R28);
- SavedRegs.set(AVR::R29);
- SavedRegs.set(AVR::R28);
- }
+ // If we have a frame pointer, the Y register needs to be saved as well.
+ // We don't do that here however - the prologue and epilogue generation
+ // code will handle it specially.
}
/// The frame analyzer pass.
///