text: //===-- 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/Function.h"
  #include "llvm/CodeGen/MachineFrameInfo.h"
  #include "llvm/CodeGen/MachineInstrBuilder.h"
  #include "llvm/CodeGen/MachineRegisterInfo.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, *this) {}
  
  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;
    }
  }
  