10b57cec5SDimitry Andric //===-- MSP430InstrInfo.cpp - MSP430 Instruction Information --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains the MSP430 implementation of the TargetInstrInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "MSP430InstrInfo.h"
140b57cec5SDimitry Andric #include "MSP430.h"
150b57cec5SDimitry Andric #include "MSP430MachineFunctionInfo.h"
160b57cec5SDimitry Andric #include "MSP430TargetMachine.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
200b57cec5SDimitry Andric #include "llvm/IR/Function.h"
21349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
220b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
270b57cec5SDimitry Andric #include "MSP430GenInstrInfo.inc"
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric // Pin the vtable to this file.
anchor()300b57cec5SDimitry Andric void MSP430InstrInfo::anchor() {}
310b57cec5SDimitry Andric
MSP430InstrInfo(MSP430Subtarget & STI)320b57cec5SDimitry Andric MSP430InstrInfo::MSP430InstrInfo(MSP430Subtarget &STI)
330b57cec5SDimitry Andric : MSP430GenInstrInfo(MSP430::ADJCALLSTACKDOWN, MSP430::ADJCALLSTACKUP),
340b57cec5SDimitry Andric RI() {}
350b57cec5SDimitry Andric
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,Register SrcReg,bool isKill,int FrameIdx,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg) const36*bdd1243dSDimitry Andric void MSP430InstrInfo::storeRegToStackSlot(
37*bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,
38*bdd1243dSDimitry Andric bool isKill, int FrameIdx, const TargetRegisterClass *RC,
39*bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, Register VReg) const {
400b57cec5SDimitry Andric DebugLoc DL;
410b57cec5SDimitry Andric if (MI != MBB.end()) DL = MI->getDebugLoc();
420b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent();
430b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo();
440b57cec5SDimitry Andric
450b57cec5SDimitry Andric MachineMemOperand *MMO = MF.getMachineMemOperand(
460b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(MF, FrameIdx),
470b57cec5SDimitry Andric MachineMemOperand::MOStore, MFI.getObjectSize(FrameIdx),
485ffd83dbSDimitry Andric MFI.getObjectAlign(FrameIdx));
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric if (RC == &MSP430::GR16RegClass)
510b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(MSP430::MOV16mr))
520b57cec5SDimitry Andric .addFrameIndex(FrameIdx).addImm(0)
530b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
540b57cec5SDimitry Andric else if (RC == &MSP430::GR8RegClass)
550b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(MSP430::MOV8mr))
560b57cec5SDimitry Andric .addFrameIndex(FrameIdx).addImm(0)
570b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
580b57cec5SDimitry Andric else
590b57cec5SDimitry Andric llvm_unreachable("Cannot store this register to stack slot!");
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,Register DestReg,int FrameIdx,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg) const620b57cec5SDimitry Andric void MSP430InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
630b57cec5SDimitry Andric MachineBasicBlock::iterator MI,
645ffd83dbSDimitry Andric Register DestReg, int FrameIdx,
650b57cec5SDimitry Andric const TargetRegisterClass *RC,
66*bdd1243dSDimitry Andric const TargetRegisterInfo *TRI,
67*bdd1243dSDimitry Andric Register VReg) const {
680b57cec5SDimitry Andric DebugLoc DL;
690b57cec5SDimitry Andric if (MI != MBB.end()) DL = MI->getDebugLoc();
700b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent();
710b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo();
720b57cec5SDimitry Andric
730b57cec5SDimitry Andric MachineMemOperand *MMO = MF.getMachineMemOperand(
740b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(MF, FrameIdx),
750b57cec5SDimitry Andric MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIdx),
765ffd83dbSDimitry Andric MFI.getObjectAlign(FrameIdx));
770b57cec5SDimitry Andric
780b57cec5SDimitry Andric if (RC == &MSP430::GR16RegClass)
790b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(MSP430::MOV16rm))
800b57cec5SDimitry Andric .addReg(DestReg, getDefRegState(true)).addFrameIndex(FrameIdx)
810b57cec5SDimitry Andric .addImm(0).addMemOperand(MMO);
820b57cec5SDimitry Andric else if (RC == &MSP430::GR8RegClass)
830b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(MSP430::MOV8rm))
840b57cec5SDimitry Andric .addReg(DestReg, getDefRegState(true)).addFrameIndex(FrameIdx)
850b57cec5SDimitry Andric .addImm(0).addMemOperand(MMO);
860b57cec5SDimitry Andric else
870b57cec5SDimitry Andric llvm_unreachable("Cannot store this register to stack slot!");
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,const DebugLoc & DL,MCRegister DestReg,MCRegister SrcReg,bool KillSrc) const900b57cec5SDimitry Andric void MSP430InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
910b57cec5SDimitry Andric MachineBasicBlock::iterator I,
92480093f4SDimitry Andric const DebugLoc &DL, MCRegister DestReg,
93480093f4SDimitry Andric MCRegister SrcReg, bool KillSrc) const {
940b57cec5SDimitry Andric unsigned Opc;
950b57cec5SDimitry Andric if (MSP430::GR16RegClass.contains(DestReg, SrcReg))
960b57cec5SDimitry Andric Opc = MSP430::MOV16rr;
970b57cec5SDimitry Andric else if (MSP430::GR8RegClass.contains(DestReg, SrcReg))
980b57cec5SDimitry Andric Opc = MSP430::MOV8rr;
990b57cec5SDimitry Andric else
1000b57cec5SDimitry Andric llvm_unreachable("Impossible reg-to-reg copy");
1010b57cec5SDimitry Andric
1020b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Opc), DestReg)
1030b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc));
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric
removeBranch(MachineBasicBlock & MBB,int * BytesRemoved) const1060b57cec5SDimitry Andric unsigned MSP430InstrInfo::removeBranch(MachineBasicBlock &MBB,
1070b57cec5SDimitry Andric int *BytesRemoved) const {
1080b57cec5SDimitry Andric assert(!BytesRemoved && "code size not handled");
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric MachineBasicBlock::iterator I = MBB.end();
1110b57cec5SDimitry Andric unsigned Count = 0;
1120b57cec5SDimitry Andric
1130b57cec5SDimitry Andric while (I != MBB.begin()) {
1140b57cec5SDimitry Andric --I;
1150b57cec5SDimitry Andric if (I->isDebugInstr())
1160b57cec5SDimitry Andric continue;
1170b57cec5SDimitry Andric if (I->getOpcode() != MSP430::JMP &&
1180b57cec5SDimitry Andric I->getOpcode() != MSP430::JCC &&
119349cc55cSDimitry Andric I->getOpcode() != MSP430::Bi &&
1200b57cec5SDimitry Andric I->getOpcode() != MSP430::Br &&
1210b57cec5SDimitry Andric I->getOpcode() != MSP430::Bm)
1220b57cec5SDimitry Andric break;
1230b57cec5SDimitry Andric // Remove the branch.
1240b57cec5SDimitry Andric I->eraseFromParent();
1250b57cec5SDimitry Andric I = MBB.end();
1260b57cec5SDimitry Andric ++Count;
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric
1290b57cec5SDimitry Andric return Count;
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric
1320b57cec5SDimitry Andric bool MSP430InstrInfo::
reverseBranchCondition(SmallVectorImpl<MachineOperand> & Cond) const1330b57cec5SDimitry Andric reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
1340b57cec5SDimitry Andric assert(Cond.size() == 1 && "Invalid Xbranch condition!");
1350b57cec5SDimitry Andric
1360b57cec5SDimitry Andric MSP430CC::CondCodes CC = static_cast<MSP430CC::CondCodes>(Cond[0].getImm());
1370b57cec5SDimitry Andric
1380b57cec5SDimitry Andric switch (CC) {
1390b57cec5SDimitry Andric default: llvm_unreachable("Invalid branch condition!");
1400b57cec5SDimitry Andric case MSP430CC::COND_E:
1410b57cec5SDimitry Andric CC = MSP430CC::COND_NE;
1420b57cec5SDimitry Andric break;
1430b57cec5SDimitry Andric case MSP430CC::COND_NE:
1440b57cec5SDimitry Andric CC = MSP430CC::COND_E;
1450b57cec5SDimitry Andric break;
1460b57cec5SDimitry Andric case MSP430CC::COND_L:
1470b57cec5SDimitry Andric CC = MSP430CC::COND_GE;
1480b57cec5SDimitry Andric break;
1490b57cec5SDimitry Andric case MSP430CC::COND_GE:
1500b57cec5SDimitry Andric CC = MSP430CC::COND_L;
1510b57cec5SDimitry Andric break;
1520b57cec5SDimitry Andric case MSP430CC::COND_HS:
1530b57cec5SDimitry Andric CC = MSP430CC::COND_LO;
1540b57cec5SDimitry Andric break;
1550b57cec5SDimitry Andric case MSP430CC::COND_LO:
1560b57cec5SDimitry Andric CC = MSP430CC::COND_HS;
1570b57cec5SDimitry Andric break;
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andric Cond[0].setImm(CC);
1610b57cec5SDimitry Andric return false;
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const1640b57cec5SDimitry Andric bool MSP430InstrInfo::analyzeBranch(MachineBasicBlock &MBB,
1650b57cec5SDimitry Andric MachineBasicBlock *&TBB,
1660b57cec5SDimitry Andric MachineBasicBlock *&FBB,
1670b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond,
1680b57cec5SDimitry Andric bool AllowModify) const {
1690b57cec5SDimitry Andric // Start from the bottom of the block and work up, examining the
1700b57cec5SDimitry Andric // terminator instructions.
1710b57cec5SDimitry Andric MachineBasicBlock::iterator I = MBB.end();
1720b57cec5SDimitry Andric while (I != MBB.begin()) {
1730b57cec5SDimitry Andric --I;
1740b57cec5SDimitry Andric if (I->isDebugInstr())
1750b57cec5SDimitry Andric continue;
1760b57cec5SDimitry Andric
1770b57cec5SDimitry Andric // Working from the bottom, when we see a non-terminator
1780b57cec5SDimitry Andric // instruction, we're done.
1790b57cec5SDimitry Andric if (!isUnpredicatedTerminator(*I))
1800b57cec5SDimitry Andric break;
1810b57cec5SDimitry Andric
1820b57cec5SDimitry Andric // A terminator that isn't a branch can't easily be handled
1830b57cec5SDimitry Andric // by this analysis.
1840b57cec5SDimitry Andric if (!I->isBranch())
1850b57cec5SDimitry Andric return true;
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andric // Cannot handle indirect branches.
1880b57cec5SDimitry Andric if (I->getOpcode() == MSP430::Br ||
1890b57cec5SDimitry Andric I->getOpcode() == MSP430::Bm)
1900b57cec5SDimitry Andric return true;
1910b57cec5SDimitry Andric
1920b57cec5SDimitry Andric // Handle unconditional branches.
193349cc55cSDimitry Andric if (I->getOpcode() == MSP430::JMP || I->getOpcode() == MSP430::Bi) {
1940b57cec5SDimitry Andric if (!AllowModify) {
1950b57cec5SDimitry Andric TBB = I->getOperand(0).getMBB();
1960b57cec5SDimitry Andric continue;
1970b57cec5SDimitry Andric }
1980b57cec5SDimitry Andric
1990b57cec5SDimitry Andric // If the block has any instructions after a JMP, delete them.
20081ad6265SDimitry Andric MBB.erase(std::next(I), MBB.end());
2010b57cec5SDimitry Andric Cond.clear();
2020b57cec5SDimitry Andric FBB = nullptr;
2030b57cec5SDimitry Andric
2040b57cec5SDimitry Andric // Delete the JMP if it's equivalent to a fall-through.
2050b57cec5SDimitry Andric if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
2060b57cec5SDimitry Andric TBB = nullptr;
2070b57cec5SDimitry Andric I->eraseFromParent();
2080b57cec5SDimitry Andric I = MBB.end();
2090b57cec5SDimitry Andric continue;
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric
2120b57cec5SDimitry Andric // TBB is used to indicate the unconditinal destination.
2130b57cec5SDimitry Andric TBB = I->getOperand(0).getMBB();
2140b57cec5SDimitry Andric continue;
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric
2170b57cec5SDimitry Andric // Handle conditional branches.
2180b57cec5SDimitry Andric assert(I->getOpcode() == MSP430::JCC && "Invalid conditional branch");
2190b57cec5SDimitry Andric MSP430CC::CondCodes BranchCode =
2200b57cec5SDimitry Andric static_cast<MSP430CC::CondCodes>(I->getOperand(1).getImm());
2210b57cec5SDimitry Andric if (BranchCode == MSP430CC::COND_INVALID)
2220b57cec5SDimitry Andric return true; // Can't handle weird stuff.
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric // Working from the bottom, handle the first conditional branch.
2250b57cec5SDimitry Andric if (Cond.empty()) {
2260b57cec5SDimitry Andric FBB = TBB;
2270b57cec5SDimitry Andric TBB = I->getOperand(0).getMBB();
2280b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(BranchCode));
2290b57cec5SDimitry Andric continue;
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric // Handle subsequent conditional branches. Only handle the case where all
2330b57cec5SDimitry Andric // conditional branches branch to the same destination.
2340b57cec5SDimitry Andric assert(Cond.size() == 1);
2350b57cec5SDimitry Andric assert(TBB);
2360b57cec5SDimitry Andric
2370b57cec5SDimitry Andric // Only handle the case where all conditional branches branch to
2380b57cec5SDimitry Andric // the same destination.
2390b57cec5SDimitry Andric if (TBB != I->getOperand(0).getMBB())
2400b57cec5SDimitry Andric return true;
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric MSP430CC::CondCodes OldBranchCode = (MSP430CC::CondCodes)Cond[0].getImm();
2430b57cec5SDimitry Andric // If the conditions are the same, we can leave them alone.
2440b57cec5SDimitry Andric if (OldBranchCode == BranchCode)
2450b57cec5SDimitry Andric continue;
2460b57cec5SDimitry Andric
2470b57cec5SDimitry Andric return true;
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric
2500b57cec5SDimitry Andric return false;
2510b57cec5SDimitry Andric }
2520b57cec5SDimitry Andric
insertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL,int * BytesAdded) const2530b57cec5SDimitry Andric unsigned MSP430InstrInfo::insertBranch(MachineBasicBlock &MBB,
2540b57cec5SDimitry Andric MachineBasicBlock *TBB,
2550b57cec5SDimitry Andric MachineBasicBlock *FBB,
2560b57cec5SDimitry Andric ArrayRef<MachineOperand> Cond,
2570b57cec5SDimitry Andric const DebugLoc &DL,
2580b57cec5SDimitry Andric int *BytesAdded) const {
2590b57cec5SDimitry Andric // Shouldn't be a fall through.
2600b57cec5SDimitry Andric assert(TBB && "insertBranch must not be told to insert a fallthrough");
2610b57cec5SDimitry Andric assert((Cond.size() == 1 || Cond.size() == 0) &&
2620b57cec5SDimitry Andric "MSP430 branch conditions have one component!");
2630b57cec5SDimitry Andric assert(!BytesAdded && "code size not handled");
2640b57cec5SDimitry Andric
2650b57cec5SDimitry Andric if (Cond.empty()) {
2660b57cec5SDimitry Andric // Unconditional branch?
2670b57cec5SDimitry Andric assert(!FBB && "Unconditional branch with multiple successors!");
2680b57cec5SDimitry Andric BuildMI(&MBB, DL, get(MSP430::JMP)).addMBB(TBB);
2690b57cec5SDimitry Andric return 1;
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric
2720b57cec5SDimitry Andric // Conditional branch.
2730b57cec5SDimitry Andric unsigned Count = 0;
2740b57cec5SDimitry Andric BuildMI(&MBB, DL, get(MSP430::JCC)).addMBB(TBB).addImm(Cond[0].getImm());
2750b57cec5SDimitry Andric ++Count;
2760b57cec5SDimitry Andric
2770b57cec5SDimitry Andric if (FBB) {
2780b57cec5SDimitry Andric // Two-way Conditional branch. Insert the second branch.
2790b57cec5SDimitry Andric BuildMI(&MBB, DL, get(MSP430::JMP)).addMBB(FBB);
2800b57cec5SDimitry Andric ++Count;
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric return Count;
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric
2850b57cec5SDimitry Andric /// GetInstSize - Return the number of bytes of code the specified
2860b57cec5SDimitry Andric /// instruction may be. This returns the maximum number of bytes.
2870b57cec5SDimitry Andric ///
getInstSizeInBytes(const MachineInstr & MI) const2880b57cec5SDimitry Andric unsigned MSP430InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
2890b57cec5SDimitry Andric const MCInstrDesc &Desc = MI.getDesc();
2900b57cec5SDimitry Andric
2910b57cec5SDimitry Andric switch (Desc.getOpcode()) {
2920b57cec5SDimitry Andric case TargetOpcode::CFI_INSTRUCTION:
2930b57cec5SDimitry Andric case TargetOpcode::EH_LABEL:
2940b57cec5SDimitry Andric case TargetOpcode::IMPLICIT_DEF:
2950b57cec5SDimitry Andric case TargetOpcode::KILL:
2960b57cec5SDimitry Andric case TargetOpcode::DBG_VALUE:
2970b57cec5SDimitry Andric return 0;
2980b57cec5SDimitry Andric case TargetOpcode::INLINEASM:
2990b57cec5SDimitry Andric case TargetOpcode::INLINEASM_BR: {
3000b57cec5SDimitry Andric const MachineFunction *MF = MI.getParent()->getParent();
3010b57cec5SDimitry Andric const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
3020b57cec5SDimitry Andric return TII.getInlineAsmLength(MI.getOperand(0).getSymbolName(),
3030b57cec5SDimitry Andric *MF->getTarget().getMCAsmInfo());
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric
3070b57cec5SDimitry Andric return Desc.getSize();
3080b57cec5SDimitry Andric }
309