mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-09-01 04:29:57 +00:00
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123170 91177308-0d34-0410-b5e6-96231b3b80d8
246 lines
8.2 KiB
C++
246 lines
8.2 KiB
C++
//===- 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 "MSP430MachineFunctionInfo.h"
|
|
#include "MSP430RegisterInfo.h"
|
|
#include "MSP430TargetMachine.h"
|
|
#include "llvm/Function.h"
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
#include "llvm/Target/TargetOptions.h"
|
|
#include "llvm/ADT/BitVector.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
using namespace llvm;
|
|
|
|
// FIXME: Provide proper call frame setup / destroy opcodes.
|
|
MSP430RegisterInfo::MSP430RegisterInfo(MSP430TargetMachine &tm,
|
|
const TargetInstrInfo &tii)
|
|
: MSP430GenRegisterInfo(MSP430::ADJCALLSTACKDOWN, MSP430::ADJCALLSTACKUP),
|
|
TM(tm), TII(tii) {
|
|
StackAlign = TM.getFrameLowering()->getStackAlignment();
|
|
}
|
|
|
|
const unsigned*
|
|
MSP430RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
|
const TargetFrameLowering *TFI = MF->getTarget().getFrameLowering();
|
|
const Function* F = MF->getFunction();
|
|
static const unsigned CalleeSavedRegs[] = {
|
|
MSP430::FPW, MSP430::R5W, MSP430::R6W, MSP430::R7W,
|
|
MSP430::R8W, MSP430::R9W, MSP430::R10W, MSP430::R11W,
|
|
0
|
|
};
|
|
static const unsigned CalleeSavedRegsFP[] = {
|
|
MSP430::R5W, MSP430::R6W, MSP430::R7W,
|
|
MSP430::R8W, MSP430::R9W, MSP430::R10W, MSP430::R11W,
|
|
0
|
|
};
|
|
static const unsigned CalleeSavedRegsIntr[] = {
|
|
MSP430::FPW, MSP430::R5W, MSP430::R6W, MSP430::R7W,
|
|
MSP430::R8W, MSP430::R9W, MSP430::R10W, MSP430::R11W,
|
|
MSP430::R12W, MSP430::R13W, MSP430::R14W, MSP430::R15W,
|
|
0
|
|
};
|
|
static const unsigned CalleeSavedRegsIntrFP[] = {
|
|
MSP430::R5W, MSP430::R6W, MSP430::R7W,
|
|
MSP430::R8W, MSP430::R9W, MSP430::R10W, MSP430::R11W,
|
|
MSP430::R12W, MSP430::R13W, MSP430::R14W, MSP430::R15W,
|
|
0
|
|
};
|
|
|
|
if (TFI->hasFP(*MF))
|
|
return (F->getCallingConv() == CallingConv::MSP430_INTR ?
|
|
CalleeSavedRegsIntrFP : CalleeSavedRegsFP);
|
|
else
|
|
return (F->getCallingConv() == CallingConv::MSP430_INTR ?
|
|
CalleeSavedRegsIntr : CalleeSavedRegs);
|
|
|
|
}
|
|
|
|
BitVector MSP430RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
|
BitVector Reserved(getNumRegs());
|
|
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
|
|
|
|
// Mark 4 special registers as reserved.
|
|
Reserved.set(MSP430::PCW);
|
|
Reserved.set(MSP430::SPW);
|
|
Reserved.set(MSP430::SRW);
|
|
Reserved.set(MSP430::CGW);
|
|
|
|
// Mark frame pointer as reserved if needed.
|
|
if (TFI->hasFP(MF))
|
|
Reserved.set(MSP430::FPW);
|
|
|
|
return Reserved;
|
|
}
|
|
|
|
const TargetRegisterClass *
|
|
MSP430RegisterInfo::getPointerRegClass(unsigned Kind) const {
|
|
return &MSP430::GR16RegClass;
|
|
}
|
|
|
|
void MSP430RegisterInfo::
|
|
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator I) const {
|
|
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
|
|
|
|
if (!TFI->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);
|
|
}
|
|
|
|
void
|
|
MSP430RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|
int SPAdj, RegScavenger *RS) const {
|
|
assert(SPAdj == 0 && "Unexpected");
|
|
|
|
unsigned i = 0;
|
|
MachineInstr &MI = *II;
|
|
MachineBasicBlock &MBB = *MI.getParent();
|
|
MachineFunction &MF = *MBB.getParent();
|
|
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
|
|
DebugLoc dl = MI.getDebugLoc();
|
|
while (!MI.getOperand(i).isFI()) {
|
|
++i;
|
|
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
|
|
}
|
|
|
|
int FrameIndex = MI.getOperand(i).getIndex();
|
|
|
|
unsigned BasePtr = (TFI->hasFP(MF) ? MSP430::FPW : MSP430::SPW);
|
|
int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
|
|
|
|
// Skip the saved PC
|
|
Offset += 2;
|
|
|
|
if (!TFI->hasFP(MF))
|
|
Offset += MF.getFrameInfo()->getStackSize();
|
|
else
|
|
Offset += 2; // Skip the saved FPW
|
|
|
|
// Fold imm into offset
|
|
Offset += MI.getOperand(i+1).getImm();
|
|
|
|
if (MI.getOpcode() == MSP430::ADD16ri) {
|
|
// This is actually "load effective address" of the stack slot
|
|
// instruction. We have only two-address instructions, thus we need to
|
|
// expand it into mov + add
|
|
|
|
MI.setDesc(TII.get(MSP430::MOV16rr));
|
|
MI.getOperand(i).ChangeToRegister(BasePtr, false);
|
|
|
|
if (Offset == 0)
|
|
return;
|
|
|
|
// We need to materialize the offset via add instruction.
|
|
unsigned DstReg = MI.getOperand(0).getReg();
|
|
if (Offset < 0)
|
|
BuildMI(MBB, llvm::next(II), dl, TII.get(MSP430::SUB16ri), DstReg)
|
|
.addReg(DstReg).addImm(-Offset);
|
|
else
|
|
BuildMI(MBB, llvm::next(II), dl, TII.get(MSP430::ADD16ri), DstReg)
|
|
.addReg(DstReg).addImm(Offset);
|
|
|
|
return;
|
|
}
|
|
|
|
MI.getOperand(i).ChangeToRegister(BasePtr, false);
|
|
MI.getOperand(i+1).ChangeToImmediate(Offset);
|
|
}
|
|
|
|
void
|
|
MSP430RegisterInfo::processFunctionBeforeFrameFinalized(MachineFunction &MF)
|
|
const {
|
|
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
|
|
|
|
// Create a frame entry for the FPW register that must be saved.
|
|
if (TFI->hasFP(MF)) {
|
|
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(2, -4, true);
|
|
(void)FrameIdx;
|
|
assert(FrameIdx == MF.getFrameInfo()->getObjectIndexBegin() &&
|
|
"Slot for FPW register must be last in order to be found!");
|
|
}
|
|
}
|
|
|
|
unsigned MSP430RegisterInfo::getRARegister() const {
|
|
return MSP430::PCW;
|
|
}
|
|
|
|
unsigned MSP430RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
|
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
|
|
|
|
return TFI->hasFP(MF) ? MSP430::FPW : MSP430::SPW;
|
|
}
|
|
|
|
int MSP430RegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
|
|
llvm_unreachable("Not implemented yet!");
|
|
return 0;
|
|
}
|
|
|
|
#include "MSP430GenRegisterInfo.inc"
|