//===-- MSP430InstrInfo.cpp - MSP430 Instruction 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 TargetInstrInfo class. // //===----------------------------------------------------------------------===// #include "MSP430InstrInfo.h" #include "MSP430.h" #include "MSP430MachineFunctionInfo.h" #include "MSP430TargetMachine.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 #include "MSP430GenInstrInfo.inc" using namespace llvm; MSP430InstrInfo::MSP430InstrInfo(MSP430TargetMachine &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<MachineOperand> &Cond) const { assert(Cond.size() == 1 && "Invalid Xbranch condition!"); MSP430CC::CondCodes CC = static_cast<MSP430CC::CondCodes>(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<MachineOperand> &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<MSP430CC::CondCodes>(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<MachineOperand> &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; } }