2009-05-03 14:57:15 +02:00
|
|
|
//===- MSP430RegisterInfo.cpp - MSP430 Register 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 the TargetRegisterInfo class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "msp430-reg-info"
|
|
|
|
|
|
|
|
#include "MSP430.h"
|
|
|
|
#include "MSP430RegisterInfo.h"
|
2009-05-03 15:07:54 +02:00
|
|
|
#include "MSP430TargetMachine.h"
|
2009-05-03 15:00:28 +02:00
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
2009-05-03 14:59:16 +02:00
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
2009-05-03 15:07:54 +02:00
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
2009-05-03 14:59:16 +02:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2009-05-03 15:00:28 +02:00
|
|
|
#include "llvm/Target/TargetOptions.h"
|
2009-05-03 14:57:15 +02:00
|
|
|
#include "llvm/ADT/BitVector.h"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
// FIXME: Provide proper call frame setup / destroy opcodes.
|
2009-05-03 15:07:54 +02:00
|
|
|
MSP430RegisterInfo::MSP430RegisterInfo(MSP430TargetMachine &tm,
|
|
|
|
const TargetInstrInfo &tii)
|
|
|
|
: MSP430GenRegisterInfo(MSP430::ADJCALLSTACKDOWN, MSP430::ADJCALLSTACKUP),
|
|
|
|
TM(tm), TII(tii) {
|
|
|
|
StackAlign = TM.getFrameInfo()->getStackAlignment();
|
|
|
|
}
|
2009-05-03 14:57:15 +02:00
|
|
|
|
|
|
|
const unsigned*
|
|
|
|
MSP430RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
2009-05-03 15:00:46 +02:00
|
|
|
static const unsigned CalleeSavedRegs[] = {
|
2009-05-03 15:05:22 +02:00
|
|
|
MSP430::FPW, MSP430::R5W, MSP430::R6W, MSP430::R7W,
|
|
|
|
MSP430::R8W, MSP430::R9W, MSP430::R10W, MSP430::R11W,
|
2009-05-03 15:00:46 +02:00
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
return CalleeSavedRegs;
|
2009-05-03 14:57:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const TargetRegisterClass* const*
|
|
|
|
MSP430RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
2009-05-03 15:00:46 +02:00
|
|
|
static const TargetRegisterClass * const CalleeSavedRegClasses[] = {
|
2009-05-03 15:02:04 +02:00
|
|
|
&MSP430::GR16RegClass, &MSP430::GR16RegClass,
|
|
|
|
&MSP430::GR16RegClass, &MSP430::GR16RegClass,
|
|
|
|
&MSP430::GR16RegClass, &MSP430::GR16RegClass,
|
|
|
|
&MSP430::GR16RegClass, &MSP430::GR16RegClass,
|
2009-05-03 15:00:46 +02:00
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
return CalleeSavedRegClasses;
|
2009-05-03 14:57:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
BitVector
|
|
|
|
MSP430RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
2009-05-03 15:00:11 +02:00
|
|
|
BitVector Reserved(getNumRegs());
|
|
|
|
|
|
|
|
// Mark 4 special registers as reserved.
|
2009-05-03 15:05:22 +02:00
|
|
|
Reserved.set(MSP430::PCW);
|
|
|
|
Reserved.set(MSP430::SPW);
|
|
|
|
Reserved.set(MSP430::SRW);
|
|
|
|
Reserved.set(MSP430::CGW);
|
2009-05-03 15:00:11 +02:00
|
|
|
|
|
|
|
// Mark frame pointer as reserved if needed.
|
|
|
|
if (hasFP(MF))
|
2009-05-03 15:05:22 +02:00
|
|
|
Reserved.set(MSP430::FPW);
|
2009-05-03 15:00:11 +02:00
|
|
|
|
|
|
|
return Reserved;
|
2009-05-03 14:57:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool MSP430RegisterInfo::hasFP(const MachineFunction &MF) const {
|
2009-05-03 15:00:28 +02:00
|
|
|
return NoFramePointerElim || MF.getFrameInfo()->hasVarSizedObjects();
|
2009-05-03 14:57:15 +02:00
|
|
|
}
|
|
|
|
|
2009-05-03 15:07:54 +02:00
|
|
|
bool MSP430RegisterInfo::hasReservedCallFrame(MachineFunction &MF) const {
|
|
|
|
return !MF.getFrameInfo()->hasVarSizedObjects();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MSP430RegisterInfo::
|
|
|
|
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I) const {
|
|
|
|
if (!hasReservedCallFrame(MF)) {
|
|
|
|
// If the stack pointer can be changed after prologue, turn the
|
|
|
|
// adjcallstackup instruction into a 'sub SPW, <amt>' and the
|
|
|
|
// adjcallstackdown instruction into 'add SPW, <amt>'
|
|
|
|
// TODO: consider using push / pop instead of sub + store / add
|
|
|
|
MachineInstr *Old = I;
|
|
|
|
uint64_t Amount = Old->getOperand(0).getImm();
|
|
|
|
if (Amount != 0) {
|
|
|
|
// We need to keep the stack aligned properly. To do this, we round the
|
|
|
|
// amount of space needed for the outgoing arguments up to the next
|
|
|
|
// alignment boundary.
|
|
|
|
Amount = (Amount+StackAlign-1)/StackAlign*StackAlign;
|
|
|
|
|
|
|
|
MachineInstr *New = 0;
|
|
|
|
if (Old->getOpcode() == getCallFrameSetupOpcode()) {
|
|
|
|
New = BuildMI(MF, Old->getDebugLoc(),
|
|
|
|
TII.get(MSP430::SUB16ri), MSP430::SPW)
|
|
|
|
.addReg(MSP430::SPW).addImm(Amount);
|
|
|
|
} else {
|
|
|
|
assert(Old->getOpcode() == getCallFrameDestroyOpcode());
|
|
|
|
// factor out the amount the callee already popped.
|
|
|
|
uint64_t CalleeAmt = Old->getOperand(1).getImm();
|
|
|
|
Amount -= CalleeAmt;
|
|
|
|
if (Amount)
|
|
|
|
New = BuildMI(MF, Old->getDebugLoc(),
|
|
|
|
TII.get(MSP430::ADD16ri), MSP430::SPW)
|
|
|
|
.addReg(MSP430::SPW).addImm(Amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (New) {
|
|
|
|
// The SRW implicit def is dead.
|
|
|
|
New->getOperand(3).setIsDead();
|
|
|
|
|
|
|
|
// Replace the pseudo instruction with a new instruction...
|
|
|
|
MBB.insert(I, New);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (I->getOpcode() == getCallFrameDestroyOpcode()) {
|
|
|
|
// If we are performing frame pointer elimination and if the callee pops
|
|
|
|
// something off the stack pointer, add it back.
|
|
|
|
if (uint64_t CalleeAmt = I->getOperand(1).getImm()) {
|
|
|
|
MachineInstr *Old = I;
|
|
|
|
MachineInstr *New =
|
|
|
|
BuildMI(MF, Old->getDebugLoc(), TII.get(MSP430::SUB16ri),
|
|
|
|
MSP430::SPW).addReg(MSP430::SPW).addImm(CalleeAmt);
|
|
|
|
// The SRW implicit def is dead.
|
|
|
|
New->getOperand(3).setIsDead();
|
|
|
|
|
|
|
|
MBB.insert(I, New);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MBB.erase(I);
|
|
|
|
}
|
|
|
|
|
2009-05-03 14:57:15 +02:00
|
|
|
void
|
|
|
|
MSP430RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|
|
|
int SPAdj, RegScavenger *RS) const {
|
|
|
|
assert(0 && "Not implemented yet!");
|
|
|
|
}
|
|
|
|
|
|
|
|
void MSP430RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
2009-05-03 15:01:04 +02:00
|
|
|
// Nothing here yet
|
2009-05-03 14:57:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void MSP430RegisterInfo::emitEpilogue(MachineFunction &MF,
|
|
|
|
MachineBasicBlock &MBB) const {
|
2009-05-03 15:01:04 +02:00
|
|
|
// Nothing here yet
|
2009-05-03 14:57:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned MSP430RegisterInfo::getRARegister() const {
|
|
|
|
assert(0 && "Not implemented yet!");
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned MSP430RegisterInfo::getFrameRegister(MachineFunction &MF) const {
|
|
|
|
assert(0 && "Not implemented yet!");
|
|
|
|
}
|
|
|
|
|
|
|
|
int MSP430RegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
|
|
|
|
assert(0 && "Not implemented yet!");
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "MSP430GenRegisterInfo.inc"
|