| //===- 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" |
| #include "MSP430GenRegisterDesc.inc" |
| #include "MSP430GenRegisterInfo.inc" |
| |
| using namespace llvm; |
| |
| // FIXME: Provide proper call frame setup / destroy opcodes. |
| MSP430RegisterInfo::MSP430RegisterInfo(MSP430TargetMachine &tm, |
| const TargetInstrInfo &tii) |
| : MSP430GenRegisterInfo(MSP430RegDesc, MSP430RegInfoDesc, |
| 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 with subregisters as reserved. |
| Reserved.set(MSP430::PCB); |
| Reserved.set(MSP430::SPB); |
| Reserved.set(MSP430::SRB); |
| Reserved.set(MSP430::CGB); |
| 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; |
| } |
| |
| int MSP430RegisterInfo::getLLVMRegNum(unsigned RegNum, bool isEH) const { |
| llvm_unreachable("Not implemented yet!"); |
| return 0; |
| } |