mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-22 07:32:48 +00:00
4f28c1c714
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123399 91177308-0d34-0410-b5e6-96231b3b80d8
224 lines
7.6 KiB
C++
224 lines
7.6 KiB
C++
//======-- MSP430FrameLowering.cpp - MSP430 Frame Information -------=========//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains the MSP430 implementation of TargetFrameLowering class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "MSP430FrameLowering.h"
|
|
#include "MSP430InstrInfo.h"
|
|
#include "MSP430MachineFunctionInfo.h"
|
|
#include "llvm/Function.h"
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/Target/TargetData.h"
|
|
#include "llvm/Target/TargetOptions.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
using namespace llvm;
|
|
|
|
bool MSP430FrameLowering::hasFP(const MachineFunction &MF) const {
|
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
|
|
return (DisableFramePointerElim(MF) ||
|
|
MF.getFrameInfo()->hasVarSizedObjects() ||
|
|
MFI->isFrameAddressTaken());
|
|
}
|
|
|
|
bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
|
|
return !MF.getFrameInfo()->hasVarSizedObjects();
|
|
}
|
|
|
|
void MSP430FrameLowering::emitPrologue(MachineFunction &MF) const {
|
|
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
|
|
const MSP430InstrInfo &TII =
|
|
*static_cast<const MSP430InstrInfo*>(MF.getTarget().getInstrInfo());
|
|
|
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
|
|
// Get the number of bytes to allocate from the FrameInfo.
|
|
uint64_t StackSize = MFI->getStackSize();
|
|
|
|
uint64_t NumBytes = 0;
|
|
if (hasFP(MF)) {
|
|
// Calculate required stack adjustment
|
|
uint64_t FrameSize = StackSize - 2;
|
|
NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
|
|
|
|
// Get the offset of the stack slot for the EBP register... which is
|
|
// guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
|
|
// Update the frame offset adjustment.
|
|
MFI->setOffsetAdjustment(-NumBytes);
|
|
|
|
// Save FPW into the appropriate stack slot...
|
|
BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
|
|
.addReg(MSP430::FPW, RegState::Kill);
|
|
|
|
// Update FPW with the new base value...
|
|
BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::FPW)
|
|
.addReg(MSP430::SPW);
|
|
|
|
// Mark the FramePtr as live-in in every block except the entry.
|
|
for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end();
|
|
I != E; ++I)
|
|
I->addLiveIn(MSP430::FPW);
|
|
|
|
} else
|
|
NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
|
|
|
|
// Skip the callee-saved push instructions.
|
|
while (MBBI != MBB.end() && (MBBI->getOpcode() == MSP430::PUSH16r))
|
|
++MBBI;
|
|
|
|
if (MBBI != MBB.end())
|
|
DL = MBBI->getDebugLoc();
|
|
|
|
if (NumBytes) { // adjust stack pointer: SPW -= numbytes
|
|
// If there is an SUB16ri of SPW immediately before this instruction, merge
|
|
// the two.
|
|
//NumBytes -= mergeSPUpdates(MBB, MBBI, true);
|
|
// If there is an ADD16ri or SUB16ri of SPW immediately after this
|
|
// instruction, merge the two instructions.
|
|
// mergeSPUpdatesDown(MBB, MBBI, &NumBytes);
|
|
|
|
if (NumBytes) {
|
|
MachineInstr *MI =
|
|
BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SPW)
|
|
.addReg(MSP430::SPW).addImm(NumBytes);
|
|
// The SRW implicit def is dead.
|
|
MI->getOperand(3).setIsDead();
|
|
}
|
|
}
|
|
}
|
|
|
|
void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
|
|
MachineBasicBlock &MBB) const {
|
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
|
|
const MSP430InstrInfo &TII =
|
|
*static_cast<const MSP430InstrInfo*>(MF.getTarget().getInstrInfo());
|
|
|
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
|
unsigned RetOpcode = MBBI->getOpcode();
|
|
DebugLoc DL = MBBI->getDebugLoc();
|
|
|
|
switch (RetOpcode) {
|
|
case MSP430::RET:
|
|
case MSP430::RETI: break; // These are ok
|
|
default:
|
|
llvm_unreachable("Can only insert epilog into returning blocks");
|
|
}
|
|
|
|
// Get the number of bytes to allocate from the FrameInfo
|
|
uint64_t StackSize = MFI->getStackSize();
|
|
unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
|
|
uint64_t NumBytes = 0;
|
|
|
|
if (hasFP(MF)) {
|
|
// Calculate required stack adjustment
|
|
uint64_t FrameSize = StackSize - 2;
|
|
NumBytes = FrameSize - CSSize;
|
|
|
|
// pop FPW.
|
|
BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::FPW);
|
|
} else
|
|
NumBytes = StackSize - CSSize;
|
|
|
|
// Skip the callee-saved pop instructions.
|
|
while (MBBI != MBB.begin()) {
|
|
MachineBasicBlock::iterator PI = prior(MBBI);
|
|
unsigned Opc = PI->getOpcode();
|
|
if (Opc != MSP430::POP16r && !PI->getDesc().isTerminator())
|
|
break;
|
|
--MBBI;
|
|
}
|
|
|
|
DL = MBBI->getDebugLoc();
|
|
|
|
// If there is an ADD16ri or SUB16ri of SPW immediately before this
|
|
// instruction, merge the two instructions.
|
|
//if (NumBytes || MFI->hasVarSizedObjects())
|
|
// mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
|
|
|
|
if (MFI->hasVarSizedObjects()) {
|
|
BuildMI(MBB, MBBI, DL,
|
|
TII.get(MSP430::MOV16rr), MSP430::SPW).addReg(MSP430::FPW);
|
|
if (CSSize) {
|
|
MachineInstr *MI =
|
|
BuildMI(MBB, MBBI, DL,
|
|
TII.get(MSP430::SUB16ri), MSP430::SPW)
|
|
.addReg(MSP430::SPW).addImm(CSSize);
|
|
// The SRW implicit def is dead.
|
|
MI->getOperand(3).setIsDead();
|
|
}
|
|
} else {
|
|
// adjust stack pointer back: SPW += numbytes
|
|
if (NumBytes) {
|
|
MachineInstr *MI =
|
|
BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SPW)
|
|
.addReg(MSP430::SPW).addImm(NumBytes);
|
|
// The SRW implicit def is dead.
|
|
MI->getOperand(3).setIsDead();
|
|
}
|
|
}
|
|
}
|
|
|
|
// FIXME: Can we eleminate these in favour of generic code?
|
|
bool
|
|
MSP430FrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MI,
|
|
const std::vector<CalleeSavedInfo> &CSI,
|
|
const TargetRegisterInfo *TRI) const {
|
|
if (CSI.empty())
|
|
return false;
|
|
|
|
DebugLoc DL;
|
|
if (MI != MBB.end()) DL = MI->getDebugLoc();
|
|
|
|
MachineFunction &MF = *MBB.getParent();
|
|
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
|
|
MSP430MachineFunctionInfo *MFI = MF.getInfo<MSP430MachineFunctionInfo>();
|
|
MFI->setCalleeSavedFrameSize(CSI.size() * 2);
|
|
|
|
for (unsigned i = CSI.size(); i != 0; --i) {
|
|
unsigned Reg = CSI[i-1].getReg();
|
|
// Add the callee-saved register as live-in. It's killed at the spill.
|
|
MBB.addLiveIn(Reg);
|
|
BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
|
|
.addReg(Reg, RegState::Kill);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
MSP430FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MI,
|
|
const std::vector<CalleeSavedInfo> &CSI,
|
|
const TargetRegisterInfo *TRI) const {
|
|
if (CSI.empty())
|
|
return false;
|
|
|
|
DebugLoc DL;
|
|
if (MI != MBB.end()) DL = MI->getDebugLoc();
|
|
|
|
MachineFunction &MF = *MBB.getParent();
|
|
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
|
|
|
|
for (unsigned i = 0, e = CSI.size(); i != e; ++i)
|
|
BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), CSI[i].getReg());
|
|
|
|
return true;
|
|
}
|