X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FMSP430%2FMSP430InstrInfo.cpp;h=7a0b00ae366dfc020fbfde71c3e333065e372fc2;hb=e7082383732df492d8fabd17c31300db08de7627;hp=d644e63adeefa9ad40e928f56f8a23c5c8530211;hpb=f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8;p=oota-llvm.git diff --git a/lib/Target/MSP430/MSP430InstrInfo.cpp b/lib/Target/MSP430/MSP430InstrInfo.cpp index d644e63adee..7a0b00ae366 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.cpp +++ b/lib/Target/MSP430/MSP430InstrInfo.cpp @@ -1,4 +1,4 @@ -//===- MSP430InstrInfo.cpp - MSP430 Instruction Information ---------------===// +//===-- MSP430InstrInfo.cpp - MSP430 Instruction Information --------------===// // // The LLVM Compiler Infrastructure // @@ -11,18 +11,319 @@ // //===----------------------------------------------------------------------===// -#include "MSP430.h" #include "MSP430InstrInfo.h" +#include "MSP430.h" +#include "MSP430MachineFunctionInfo.h" #include "MSP430TargetMachine.h" -#include "MSP430GenInstrInfo.inc" -#include "llvm/Function.h" -#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/IR/Function.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" +#define GET_INSTRINFO_CTOR_DTOR +#include "MSP430GenInstrInfo.inc" using namespace llvm; +// Pin the vtable to this file. +void MSP430InstrInfo::anchor() {} + MSP430InstrInfo::MSP430InstrInfo(MSP430TargetMachine &tm) - : TargetInstrInfoImpl(MSP430Insts, array_lengthof(MSP430Insts)), - RI(*this), TM(tm) {} + : MSP430GenInstrInfo(MSP430::ADJCALLSTACKDOWN, MSP430::ADJCALLSTACKUP), + RI(tm) {} + +void MSP430InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, bool isKill, int FrameIdx, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + DebugLoc DL; + if (MI != MBB.end()) DL = MI->getDebugLoc(); + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + + MachineMemOperand *MMO = + MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIdx), + MachineMemOperand::MOStore, + MFI.getObjectSize(FrameIdx), + MFI.getObjectAlignment(FrameIdx)); + + if (RC == &MSP430::GR16RegClass) + BuildMI(MBB, MI, DL, get(MSP430::MOV16mr)) + .addFrameIndex(FrameIdx).addImm(0) + .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); + else if (RC == &MSP430::GR8RegClass) + BuildMI(MBB, MI, DL, get(MSP430::MOV8mr)) + .addFrameIndex(FrameIdx).addImm(0) + .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); + else + llvm_unreachable("Cannot store this register to stack slot!"); +} + +void MSP430InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, int FrameIdx, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const{ + DebugLoc DL; + if (MI != MBB.end()) DL = MI->getDebugLoc(); + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + + MachineMemOperand *MMO = + MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIdx), + MachineMemOperand::MOLoad, + MFI.getObjectSize(FrameIdx), + MFI.getObjectAlignment(FrameIdx)); + + if (RC == &MSP430::GR16RegClass) + BuildMI(MBB, MI, DL, get(MSP430::MOV16rm)) + .addReg(DestReg).addFrameIndex(FrameIdx).addImm(0).addMemOperand(MMO); + else if (RC == &MSP430::GR8RegClass) + BuildMI(MBB, MI, DL, get(MSP430::MOV8rm)) + .addReg(DestReg).addFrameIndex(FrameIdx).addImm(0).addMemOperand(MMO); + else + llvm_unreachable("Cannot store this register to stack slot!"); +} + +void MSP430InstrInfo::copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, DebugLoc DL, + unsigned DestReg, unsigned SrcReg, + bool KillSrc) const { + unsigned Opc; + if (MSP430::GR16RegClass.contains(DestReg, SrcReg)) + Opc = MSP430::MOV16rr; + else if (MSP430::GR8RegClass.contains(DestReg, SrcReg)) + Opc = MSP430::MOV8rr; + else + llvm_unreachable("Impossible reg-to-reg copy"); + + BuildMI(MBB, I, DL, get(Opc), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); +} + +unsigned MSP430InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator I = MBB.end(); + unsigned Count = 0; + + while (I != MBB.begin()) { + --I; + if (I->isDebugValue()) + continue; + if (I->getOpcode() != MSP430::JMP && + I->getOpcode() != MSP430::JCC && + I->getOpcode() != MSP430::Br && + I->getOpcode() != MSP430::Bm) + break; + // Remove the branch. + I->eraseFromParent(); + I = MBB.end(); + ++Count; + } + + return Count; +} + +bool MSP430InstrInfo:: +ReverseBranchCondition(SmallVectorImpl &Cond) const { + assert(Cond.size() == 1 && "Invalid Xbranch condition!"); + + MSP430CC::CondCodes CC = static_cast(Cond[0].getImm()); + + switch (CC) { + default: llvm_unreachable("Invalid branch condition!"); + case MSP430CC::COND_E: + CC = MSP430CC::COND_NE; + break; + case MSP430CC::COND_NE: + CC = MSP430CC::COND_E; + break; + case MSP430CC::COND_L: + CC = MSP430CC::COND_GE; + break; + case MSP430CC::COND_GE: + CC = MSP430CC::COND_L; + break; + case MSP430CC::COND_HS: + CC = MSP430CC::COND_LO; + break; + case MSP430CC::COND_LO: + CC = MSP430CC::COND_HS; + break; + } + + Cond[0].setImm(CC); + return false; +} + +bool MSP430InstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { + if (!MI->isTerminator()) return false; + + // Conditional branch is a special case. + if (MI->isBranch() && !MI->isBarrier()) + return true; + if (!MI->isPredicable()) + return true; + return !isPredicated(MI); +} + +bool MSP430InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const { + // Start from the bottom of the block and work up, examining the + // terminator instructions. + MachineBasicBlock::iterator I = MBB.end(); + while (I != MBB.begin()) { + --I; + if (I->isDebugValue()) + continue; + + // Working from the bottom, when we see a non-terminator + // instruction, we're done. + if (!isUnpredicatedTerminator(I)) + break; + + // A terminator that isn't a branch can't easily be handled + // by this analysis. + if (!I->isBranch()) + return true; + + // Cannot handle indirect branches. + if (I->getOpcode() == MSP430::Br || + I->getOpcode() == MSP430::Bm) + return true; + + // Handle unconditional branches. + if (I->getOpcode() == MSP430::JMP) { + if (!AllowModify) { + TBB = I->getOperand(0).getMBB(); + continue; + } + + // If the block has any instructions after a JMP, delete them. + while (llvm::next(I) != MBB.end()) + llvm::next(I)->eraseFromParent(); + Cond.clear(); + FBB = 0; + + // Delete the JMP if it's equivalent to a fall-through. + if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { + TBB = 0; + I->eraseFromParent(); + I = MBB.end(); + continue; + } + + // TBB is used to indicate the unconditinal destination. + TBB = I->getOperand(0).getMBB(); + continue; + } + + // Handle conditional branches. + assert(I->getOpcode() == MSP430::JCC && "Invalid conditional branch"); + MSP430CC::CondCodes BranchCode = + static_cast(I->getOperand(1).getImm()); + if (BranchCode == MSP430CC::COND_INVALID) + return true; // Can't handle weird stuff. + + // Working from the bottom, handle the first conditional branch. + if (Cond.empty()) { + FBB = TBB; + TBB = I->getOperand(0).getMBB(); + Cond.push_back(MachineOperand::CreateImm(BranchCode)); + continue; + } + + // Handle subsequent conditional branches. Only handle the case where all + // conditional branches branch to the same destination. + assert(Cond.size() == 1); + assert(TBB); + + // Only handle the case where all conditional branches branch to + // the same destination. + if (TBB != I->getOperand(0).getMBB()) + return true; + + MSP430CC::CondCodes OldBranchCode = (MSP430CC::CondCodes)Cond[0].getImm(); + // If the conditions are the same, we can leave them alone. + if (OldBranchCode == BranchCode) + continue; + + return true; + } + + return false; +} + +unsigned +MSP430InstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond, + DebugLoc DL) const { + // Shouldn't be a fall through. + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + assert((Cond.size() == 1 || Cond.size() == 0) && + "MSP430 branch conditions have one component!"); + + if (Cond.empty()) { + // Unconditional branch? + assert(!FBB && "Unconditional branch with multiple successors!"); + BuildMI(&MBB, DL, get(MSP430::JMP)).addMBB(TBB); + return 1; + } + + // Conditional branch. + unsigned Count = 0; + BuildMI(&MBB, DL, get(MSP430::JCC)).addMBB(TBB).addImm(Cond[0].getImm()); + ++Count; + + if (FBB) { + // Two-way Conditional branch. Insert the second branch. + BuildMI(&MBB, DL, get(MSP430::JMP)).addMBB(FBB); + ++Count; + } + return Count; +} + +/// GetInstSize - Return the number of bytes of code the specified +/// instruction may be. This returns the maximum number of bytes. +/// +unsigned MSP430InstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { + const MCInstrDesc &Desc = MI->getDesc(); + + switch (Desc.TSFlags & MSP430II::SizeMask) { + default: + switch (Desc.getOpcode()) { + default: llvm_unreachable("Unknown instruction size!"); + case TargetOpcode::PROLOG_LABEL: + case TargetOpcode::EH_LABEL: + case TargetOpcode::IMPLICIT_DEF: + case TargetOpcode::KILL: + case TargetOpcode::DBG_VALUE: + return 0; + case TargetOpcode::INLINEASM: { + const MachineFunction *MF = MI->getParent()->getParent(); + const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); + return TII.getInlineAsmLength(MI->getOperand(0).getSymbolName(), + *MF->getTarget().getMCAsmInfo()); + } + } + case MSP430II::SizeSpecial: + switch (MI->getOpcode()) { + default: llvm_unreachable("Unknown instruction size!"); + case MSP430::SAR8r1c: + case MSP430::SAR16r1c: + return 4; + } + case MSP430II::Size2Bytes: + return 2; + case MSP430II::Size4Bytes: + return 4; + case MSP430II::Size6Bytes: + return 6; + } +}