104eeddc0SDimitry Andric //===-- M68kInstrInfo.cpp - M68k Instruction Information --------*- C++ -*-===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric /// 9fe6060f1SDimitry Andric /// \file 10fe6060f1SDimitry Andric /// This file contains the M68k declaration of the TargetInstrInfo class. 11fe6060f1SDimitry Andric /// 12fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 13fe6060f1SDimitry Andric 14fe6060f1SDimitry Andric #include "M68kInstrInfo.h" 15fe6060f1SDimitry Andric 16fe6060f1SDimitry Andric #include "M68kInstrBuilder.h" 17fe6060f1SDimitry Andric #include "M68kMachineFunction.h" 18fe6060f1SDimitry Andric #include "M68kTargetMachine.h" 19fe6060f1SDimitry Andric #include "MCTargetDesc/M68kMCCodeEmitter.h" 20fe6060f1SDimitry Andric 21fe6060f1SDimitry Andric #include "llvm/ADT/STLExtras.h" 22fe6060f1SDimitry Andric #include "llvm/ADT/ScopeExit.h" 23fe6060f1SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h" 24fe6060f1SDimitry Andric #include "llvm/CodeGen/LiveVariables.h" 25fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 26fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 27349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 28fe6060f1SDimitry Andric #include "llvm/Support/ErrorHandling.h" 2981ad6265SDimitry Andric #include "llvm/Support/Regex.h" 30fe6060f1SDimitry Andric 31fe6060f1SDimitry Andric #include <functional> 32fe6060f1SDimitry Andric 33fe6060f1SDimitry Andric using namespace llvm; 34fe6060f1SDimitry Andric 35fe6060f1SDimitry Andric #define DEBUG_TYPE "M68k-instr-info" 36fe6060f1SDimitry Andric 37fe6060f1SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR 38fe6060f1SDimitry Andric #include "M68kGenInstrInfo.inc" 39fe6060f1SDimitry Andric 40fe6060f1SDimitry Andric // Pin the vtable to this file. 41fe6060f1SDimitry Andric void M68kInstrInfo::anchor() {} 42fe6060f1SDimitry Andric 43fe6060f1SDimitry Andric M68kInstrInfo::M68kInstrInfo(const M68kSubtarget &STI) 44fe6060f1SDimitry Andric : M68kGenInstrInfo(M68k::ADJCALLSTACKDOWN, M68k::ADJCALLSTACKUP, 0, 45fe6060f1SDimitry Andric M68k::RET), 46fe6060f1SDimitry Andric Subtarget(STI), RI(STI) {} 47fe6060f1SDimitry Andric 48fe6060f1SDimitry Andric static M68k::CondCode getCondFromBranchOpc(unsigned BrOpc) { 49fe6060f1SDimitry Andric switch (BrOpc) { 50fe6060f1SDimitry Andric default: 51fe6060f1SDimitry Andric return M68k::COND_INVALID; 52fe6060f1SDimitry Andric case M68k::Beq8: 53fe6060f1SDimitry Andric return M68k::COND_EQ; 54fe6060f1SDimitry Andric case M68k::Bne8: 55fe6060f1SDimitry Andric return M68k::COND_NE; 56fe6060f1SDimitry Andric case M68k::Blt8: 57fe6060f1SDimitry Andric return M68k::COND_LT; 58fe6060f1SDimitry Andric case M68k::Ble8: 59fe6060f1SDimitry Andric return M68k::COND_LE; 60fe6060f1SDimitry Andric case M68k::Bgt8: 61fe6060f1SDimitry Andric return M68k::COND_GT; 62fe6060f1SDimitry Andric case M68k::Bge8: 63fe6060f1SDimitry Andric return M68k::COND_GE; 64fe6060f1SDimitry Andric case M68k::Bcs8: 65fe6060f1SDimitry Andric return M68k::COND_CS; 66fe6060f1SDimitry Andric case M68k::Bls8: 67fe6060f1SDimitry Andric return M68k::COND_LS; 68fe6060f1SDimitry Andric case M68k::Bhi8: 69fe6060f1SDimitry Andric return M68k::COND_HI; 70fe6060f1SDimitry Andric case M68k::Bcc8: 71fe6060f1SDimitry Andric return M68k::COND_CC; 72fe6060f1SDimitry Andric case M68k::Bmi8: 73fe6060f1SDimitry Andric return M68k::COND_MI; 74fe6060f1SDimitry Andric case M68k::Bpl8: 75fe6060f1SDimitry Andric return M68k::COND_PL; 76fe6060f1SDimitry Andric case M68k::Bvs8: 77fe6060f1SDimitry Andric return M68k::COND_VS; 78fe6060f1SDimitry Andric case M68k::Bvc8: 79fe6060f1SDimitry Andric return M68k::COND_VC; 80fe6060f1SDimitry Andric } 81fe6060f1SDimitry Andric } 82fe6060f1SDimitry Andric 83fe6060f1SDimitry Andric bool M68kInstrInfo::AnalyzeBranchImpl(MachineBasicBlock &MBB, 84fe6060f1SDimitry Andric MachineBasicBlock *&TBB, 85fe6060f1SDimitry Andric MachineBasicBlock *&FBB, 86fe6060f1SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 87fe6060f1SDimitry Andric bool AllowModify) const { 88fe6060f1SDimitry Andric 89fe6060f1SDimitry Andric auto UncondBranch = 90fe6060f1SDimitry Andric std::pair<MachineBasicBlock::reverse_iterator, MachineBasicBlock *>{ 91fe6060f1SDimitry Andric MBB.rend(), nullptr}; 92fe6060f1SDimitry Andric 93fe6060f1SDimitry Andric // Erase any instructions if allowed at the end of the scope. 94fe6060f1SDimitry Andric std::vector<std::reference_wrapper<llvm::MachineInstr>> EraseList; 95fe6060f1SDimitry Andric auto FinalizeOnReturn = llvm::make_scope_exit([&EraseList] { 96fe6060f1SDimitry Andric std::for_each(EraseList.begin(), EraseList.end(), 97fe6060f1SDimitry Andric [](auto &ref) { ref.get().eraseFromParent(); }); 98fe6060f1SDimitry Andric }); 99fe6060f1SDimitry Andric 100fe6060f1SDimitry Andric // Start from the bottom of the block and work up, examining the 101fe6060f1SDimitry Andric // terminator instructions. 102fe6060f1SDimitry Andric for (auto iter = MBB.rbegin(); iter != MBB.rend(); iter = std::next(iter)) { 103fe6060f1SDimitry Andric 104fe6060f1SDimitry Andric unsigned Opcode = iter->getOpcode(); 105fe6060f1SDimitry Andric 106fe6060f1SDimitry Andric if (iter->isDebugInstr()) 107fe6060f1SDimitry Andric continue; 108fe6060f1SDimitry Andric 109fe6060f1SDimitry Andric // Working from the bottom, when we see a non-terminator instruction, we're 110fe6060f1SDimitry Andric // done. 111fe6060f1SDimitry Andric if (!isUnpredicatedTerminator(*iter)) 112fe6060f1SDimitry Andric break; 113fe6060f1SDimitry Andric 114fe6060f1SDimitry Andric // A terminator that isn't a branch can't easily be handled by this 115fe6060f1SDimitry Andric // analysis. 116fe6060f1SDimitry Andric if (!iter->isBranch()) 117fe6060f1SDimitry Andric return true; 118fe6060f1SDimitry Andric 119fe6060f1SDimitry Andric // Handle unconditional branches. 120fe6060f1SDimitry Andric if (Opcode == M68k::BRA8 || Opcode == M68k::BRA16) { 121fe6060f1SDimitry Andric if (!iter->getOperand(0).isMBB()) 122fe6060f1SDimitry Andric return true; 123fe6060f1SDimitry Andric UncondBranch = {iter, iter->getOperand(0).getMBB()}; 124fe6060f1SDimitry Andric 125fe6060f1SDimitry Andric // TBB is used to indicate the unconditional destination. 126fe6060f1SDimitry Andric TBB = UncondBranch.second; 127fe6060f1SDimitry Andric 128fe6060f1SDimitry Andric if (!AllowModify) 129fe6060f1SDimitry Andric continue; 130fe6060f1SDimitry Andric 131fe6060f1SDimitry Andric // If the block has any instructions after a JMP, erase them. 132fe6060f1SDimitry Andric EraseList.insert(EraseList.begin(), MBB.rbegin(), iter); 133fe6060f1SDimitry Andric 134fe6060f1SDimitry Andric Cond.clear(); 135fe6060f1SDimitry Andric FBB = nullptr; 136fe6060f1SDimitry Andric 137fe6060f1SDimitry Andric // Erase the JMP if it's equivalent to a fall-through. 138fe6060f1SDimitry Andric if (MBB.isLayoutSuccessor(UncondBranch.second)) { 139fe6060f1SDimitry Andric TBB = nullptr; 140fe6060f1SDimitry Andric EraseList.push_back(*iter); 141fe6060f1SDimitry Andric UncondBranch = {MBB.rend(), nullptr}; 142fe6060f1SDimitry Andric } 143fe6060f1SDimitry Andric 144fe6060f1SDimitry Andric continue; 145fe6060f1SDimitry Andric } 146fe6060f1SDimitry Andric 147fe6060f1SDimitry Andric // Handle conditional branches. 148fe6060f1SDimitry Andric auto BranchCode = M68k::GetCondFromBranchOpc(Opcode); 149fe6060f1SDimitry Andric 150fe6060f1SDimitry Andric // Can't handle indirect branch. 151fe6060f1SDimitry Andric if (BranchCode == M68k::COND_INVALID) 152fe6060f1SDimitry Andric return true; 153fe6060f1SDimitry Andric 154fe6060f1SDimitry Andric // In practice we should never have an undef CCR operand, if we do 155fe6060f1SDimitry Andric // abort here as we are not prepared to preserve the flag. 156fe6060f1SDimitry Andric // ??? Is this required? 157fe6060f1SDimitry Andric // if (iter->getOperand(1).isUndef()) 158fe6060f1SDimitry Andric // return true; 159fe6060f1SDimitry Andric 160fe6060f1SDimitry Andric // Working from the bottom, handle the first conditional branch. 161fe6060f1SDimitry Andric if (Cond.empty()) { 162fe6060f1SDimitry Andric if (!iter->getOperand(0).isMBB()) 163fe6060f1SDimitry Andric return true; 164fe6060f1SDimitry Andric MachineBasicBlock *CondBranchTarget = iter->getOperand(0).getMBB(); 165fe6060f1SDimitry Andric 166fe6060f1SDimitry Andric // If we see something like this: 167fe6060f1SDimitry Andric // 168fe6060f1SDimitry Andric // bcc l1 169fe6060f1SDimitry Andric // bra l2 170fe6060f1SDimitry Andric // ... 171fe6060f1SDimitry Andric // l1: 172fe6060f1SDimitry Andric // ... 173fe6060f1SDimitry Andric // l2: 174fe6060f1SDimitry Andric if (UncondBranch.first != MBB.rend()) { 175fe6060f1SDimitry Andric 176fe6060f1SDimitry Andric assert(std::next(UncondBranch.first) == iter && "Wrong block layout."); 177fe6060f1SDimitry Andric 178fe6060f1SDimitry Andric // And we are allowed to modify the block and the target block of the 179fe6060f1SDimitry Andric // conditional branch is the direct successor of this block: 180fe6060f1SDimitry Andric // 181fe6060f1SDimitry Andric // bcc l1 182fe6060f1SDimitry Andric // bra l2 183fe6060f1SDimitry Andric // l1: 184fe6060f1SDimitry Andric // ... 185fe6060f1SDimitry Andric // l2: 186fe6060f1SDimitry Andric // 187fe6060f1SDimitry Andric // we change it to this if allowed: 188fe6060f1SDimitry Andric // 189fe6060f1SDimitry Andric // bncc l2 190fe6060f1SDimitry Andric // l1: 191fe6060f1SDimitry Andric // ... 192fe6060f1SDimitry Andric // l2: 193fe6060f1SDimitry Andric // 194fe6060f1SDimitry Andric // Which is a bit more efficient. 195fe6060f1SDimitry Andric if (AllowModify && MBB.isLayoutSuccessor(CondBranchTarget)) { 196fe6060f1SDimitry Andric 197fe6060f1SDimitry Andric BranchCode = GetOppositeBranchCondition(BranchCode); 198fe6060f1SDimitry Andric unsigned BNCC = GetCondBranchFromCond(BranchCode); 199fe6060f1SDimitry Andric 200fe6060f1SDimitry Andric BuildMI(MBB, *UncondBranch.first, MBB.rfindDebugLoc(iter), get(BNCC)) 201fe6060f1SDimitry Andric .addMBB(UncondBranch.second); 202fe6060f1SDimitry Andric 203fe6060f1SDimitry Andric EraseList.push_back(*iter); 204fe6060f1SDimitry Andric EraseList.push_back(*UncondBranch.first); 205fe6060f1SDimitry Andric 206fe6060f1SDimitry Andric TBB = UncondBranch.second; 207fe6060f1SDimitry Andric FBB = nullptr; 208fe6060f1SDimitry Andric Cond.push_back(MachineOperand::CreateImm(BranchCode)); 209fe6060f1SDimitry Andric 210fe6060f1SDimitry Andric // Otherwise preserve TBB, FBB and Cond as requested 211fe6060f1SDimitry Andric } else { 212fe6060f1SDimitry Andric TBB = CondBranchTarget; 213fe6060f1SDimitry Andric FBB = UncondBranch.second; 214fe6060f1SDimitry Andric Cond.push_back(MachineOperand::CreateImm(BranchCode)); 215fe6060f1SDimitry Andric } 216fe6060f1SDimitry Andric 217fe6060f1SDimitry Andric UncondBranch = {MBB.rend(), nullptr}; 218fe6060f1SDimitry Andric continue; 219fe6060f1SDimitry Andric } 220fe6060f1SDimitry Andric 221fe6060f1SDimitry Andric TBB = CondBranchTarget; 222fe6060f1SDimitry Andric FBB = nullptr; 223fe6060f1SDimitry Andric Cond.push_back(MachineOperand::CreateImm(BranchCode)); 224fe6060f1SDimitry Andric 225fe6060f1SDimitry Andric continue; 226fe6060f1SDimitry Andric } 227fe6060f1SDimitry Andric 228fe6060f1SDimitry Andric // Handle subsequent conditional branches. Only handle the case where all 229fe6060f1SDimitry Andric // conditional branches branch to the same destination and their condition 230fe6060f1SDimitry Andric // opcodes fit one of the special multi-branch idioms. 231fe6060f1SDimitry Andric assert(Cond.size() == 1); 232fe6060f1SDimitry Andric assert(TBB); 233fe6060f1SDimitry Andric 234fe6060f1SDimitry Andric // If the conditions are the same, we can leave them alone. 235fe6060f1SDimitry Andric auto OldBranchCode = static_cast<M68k::CondCode>(Cond[0].getImm()); 236fe6060f1SDimitry Andric if (!iter->getOperand(0).isMBB()) 237fe6060f1SDimitry Andric return true; 238fe6060f1SDimitry Andric auto NewTBB = iter->getOperand(0).getMBB(); 239fe6060f1SDimitry Andric if (OldBranchCode == BranchCode && TBB == NewTBB) 240fe6060f1SDimitry Andric continue; 241fe6060f1SDimitry Andric 242fe6060f1SDimitry Andric // If they differ we cannot do much here. 243fe6060f1SDimitry Andric return true; 244fe6060f1SDimitry Andric } 245fe6060f1SDimitry Andric 246fe6060f1SDimitry Andric return false; 247fe6060f1SDimitry Andric } 248fe6060f1SDimitry Andric 249fe6060f1SDimitry Andric bool M68kInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 250fe6060f1SDimitry Andric MachineBasicBlock *&TBB, 251fe6060f1SDimitry Andric MachineBasicBlock *&FBB, 252fe6060f1SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 253fe6060f1SDimitry Andric bool AllowModify) const { 254fe6060f1SDimitry Andric return AnalyzeBranchImpl(MBB, TBB, FBB, Cond, AllowModify); 255fe6060f1SDimitry Andric } 256fe6060f1SDimitry Andric 257fe6060f1SDimitry Andric unsigned M68kInstrInfo::removeBranch(MachineBasicBlock &MBB, 258fe6060f1SDimitry Andric int *BytesRemoved) const { 259fe6060f1SDimitry Andric assert(!BytesRemoved && "code size not handled"); 260fe6060f1SDimitry Andric 261fe6060f1SDimitry Andric MachineBasicBlock::iterator I = MBB.end(); 262fe6060f1SDimitry Andric unsigned Count = 0; 263fe6060f1SDimitry Andric 264fe6060f1SDimitry Andric while (I != MBB.begin()) { 265fe6060f1SDimitry Andric --I; 266fe6060f1SDimitry Andric if (I->isDebugValue()) 267fe6060f1SDimitry Andric continue; 268fe6060f1SDimitry Andric if (I->getOpcode() != M68k::BRA8 && 269fe6060f1SDimitry Andric getCondFromBranchOpc(I->getOpcode()) == M68k::COND_INVALID) 270fe6060f1SDimitry Andric break; 271fe6060f1SDimitry Andric // Remove the branch. 272fe6060f1SDimitry Andric I->eraseFromParent(); 273fe6060f1SDimitry Andric I = MBB.end(); 274fe6060f1SDimitry Andric ++Count; 275fe6060f1SDimitry Andric } 276fe6060f1SDimitry Andric 277fe6060f1SDimitry Andric return Count; 278fe6060f1SDimitry Andric } 279fe6060f1SDimitry Andric 280fe6060f1SDimitry Andric unsigned M68kInstrInfo::insertBranch( 281fe6060f1SDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, 282fe6060f1SDimitry Andric ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const { 283fe6060f1SDimitry Andric // Shouldn't be a fall through. 284fe6060f1SDimitry Andric assert(TBB && "InsertBranch must not be told to insert a fallthrough"); 285fe6060f1SDimitry Andric assert((Cond.size() == 1 || Cond.size() == 0) && 286fe6060f1SDimitry Andric "M68k branch conditions have one component!"); 287fe6060f1SDimitry Andric assert(!BytesAdded && "code size not handled"); 288fe6060f1SDimitry Andric 289fe6060f1SDimitry Andric if (Cond.empty()) { 290fe6060f1SDimitry Andric // Unconditional branch? 291fe6060f1SDimitry Andric assert(!FBB && "Unconditional branch with multiple successors!"); 292fe6060f1SDimitry Andric BuildMI(&MBB, DL, get(M68k::BRA8)).addMBB(TBB); 293fe6060f1SDimitry Andric return 1; 294fe6060f1SDimitry Andric } 295fe6060f1SDimitry Andric 296fe6060f1SDimitry Andric // If FBB is null, it is implied to be a fall-through block. 297fe6060f1SDimitry Andric bool FallThru = FBB == nullptr; 298fe6060f1SDimitry Andric 299fe6060f1SDimitry Andric // Conditional branch. 300fe6060f1SDimitry Andric unsigned Count = 0; 301fe6060f1SDimitry Andric M68k::CondCode CC = (M68k::CondCode)Cond[0].getImm(); 302fe6060f1SDimitry Andric unsigned Opc = GetCondBranchFromCond(CC); 303fe6060f1SDimitry Andric BuildMI(&MBB, DL, get(Opc)).addMBB(TBB); 304fe6060f1SDimitry Andric ++Count; 305fe6060f1SDimitry Andric if (!FallThru) { 306fe6060f1SDimitry Andric // Two-way Conditional branch. Insert the second branch. 307fe6060f1SDimitry Andric BuildMI(&MBB, DL, get(M68k::BRA8)).addMBB(FBB); 308fe6060f1SDimitry Andric ++Count; 309fe6060f1SDimitry Andric } 310fe6060f1SDimitry Andric return Count; 311fe6060f1SDimitry Andric } 312fe6060f1SDimitry Andric 313fe6060f1SDimitry Andric void M68kInstrInfo::AddSExt(MachineBasicBlock &MBB, 314fe6060f1SDimitry Andric MachineBasicBlock::iterator I, DebugLoc DL, 315fe6060f1SDimitry Andric unsigned Reg, MVT From, MVT To) const { 316fe6060f1SDimitry Andric if (From == MVT::i8) { 317fe6060f1SDimitry Andric unsigned R = Reg; 318fe6060f1SDimitry Andric // EXT16 requires i16 register 319fe6060f1SDimitry Andric if (To == MVT::i32) { 320fe6060f1SDimitry Andric R = RI.getSubReg(Reg, M68k::MxSubRegIndex16Lo); 321fe6060f1SDimitry Andric assert(R && "No viable SUB register available"); 322fe6060f1SDimitry Andric } 323fe6060f1SDimitry Andric BuildMI(MBB, I, DL, get(M68k::EXT16), R).addReg(R); 324fe6060f1SDimitry Andric } 325fe6060f1SDimitry Andric 326fe6060f1SDimitry Andric if (To == MVT::i32) 327fe6060f1SDimitry Andric BuildMI(MBB, I, DL, get(M68k::EXT32), Reg).addReg(Reg); 328fe6060f1SDimitry Andric } 329fe6060f1SDimitry Andric 330fe6060f1SDimitry Andric void M68kInstrInfo::AddZExt(MachineBasicBlock &MBB, 331fe6060f1SDimitry Andric MachineBasicBlock::iterator I, DebugLoc DL, 332fe6060f1SDimitry Andric unsigned Reg, MVT From, MVT To) const { 333fe6060f1SDimitry Andric 334fe6060f1SDimitry Andric unsigned Mask, And; 335fe6060f1SDimitry Andric if (From == MVT::i8) 336fe6060f1SDimitry Andric Mask = 0xFF; 337fe6060f1SDimitry Andric else 338fe6060f1SDimitry Andric Mask = 0xFFFF; 339fe6060f1SDimitry Andric 340fe6060f1SDimitry Andric if (To == MVT::i16) 341fe6060f1SDimitry Andric And = M68k::AND16di; 342fe6060f1SDimitry Andric else // i32 343fe6060f1SDimitry Andric And = M68k::AND32di; 344fe6060f1SDimitry Andric 345fe6060f1SDimitry Andric // TODO use xor r,r to decrease size 346fe6060f1SDimitry Andric BuildMI(MBB, I, DL, get(And), Reg).addReg(Reg).addImm(Mask); 347fe6060f1SDimitry Andric } 348fe6060f1SDimitry Andric 349fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandMOVX_RR(MachineInstrBuilder &MIB, MVT MVTDst, 350fe6060f1SDimitry Andric MVT MVTSrc) const { 351fe6060f1SDimitry Andric unsigned Move = MVTDst == MVT::i16 ? M68k::MOV16rr : M68k::MOV32rr; 35204eeddc0SDimitry Andric Register Dst = MIB->getOperand(0).getReg(); 35304eeddc0SDimitry Andric Register Src = MIB->getOperand(1).getReg(); 354fe6060f1SDimitry Andric 355fe6060f1SDimitry Andric assert(Dst != Src && "You cannot use the same Regs with MOVX_RR"); 356fe6060f1SDimitry Andric 357fe6060f1SDimitry Andric const auto &TRI = getRegisterInfo(); 358fe6060f1SDimitry Andric 359fe6060f1SDimitry Andric const auto *RCDst = TRI.getMaximalPhysRegClass(Dst, MVTDst); 360fe6060f1SDimitry Andric const auto *RCSrc = TRI.getMaximalPhysRegClass(Src, MVTSrc); 361fe6060f1SDimitry Andric 362fe6060f1SDimitry Andric assert(RCDst && RCSrc && "Wrong use of MOVX_RR"); 363fe6060f1SDimitry Andric assert(RCDst != RCSrc && "You cannot use the same Reg Classes with MOVX_RR"); 364fe6060f1SDimitry Andric 365fe6060f1SDimitry Andric // We need to find the super source register that matches the size of Dst 366fe6060f1SDimitry Andric unsigned SSrc = RI.getMatchingMegaReg(Src, RCDst); 367fe6060f1SDimitry Andric assert(SSrc && "No viable MEGA register available"); 368fe6060f1SDimitry Andric 369fe6060f1SDimitry Andric DebugLoc DL = MIB->getDebugLoc(); 370fe6060f1SDimitry Andric 371fe6060f1SDimitry Andric // If it happens to that super source register is the destination register 372fe6060f1SDimitry Andric // we do nothing 373fe6060f1SDimitry Andric if (Dst == SSrc) { 374fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Remove " << *MIB.getInstr() << '\n'); 375fe6060f1SDimitry Andric MIB->eraseFromParent(); 376fe6060f1SDimitry Andric } else { // otherwise we need to MOV 377fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to MOV\n"); 378fe6060f1SDimitry Andric MIB->setDesc(get(Move)); 379fe6060f1SDimitry Andric MIB->getOperand(1).setReg(SSrc); 380fe6060f1SDimitry Andric } 381fe6060f1SDimitry Andric 382fe6060f1SDimitry Andric return true; 383fe6060f1SDimitry Andric } 384fe6060f1SDimitry Andric 385fe6060f1SDimitry Andric /// Expand SExt MOVE pseudos into a MOV and a EXT if the operands are two 386fe6060f1SDimitry Andric /// different registers or just EXT if it is the same register 387fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandMOVSZX_RR(MachineInstrBuilder &MIB, bool IsSigned, 388fe6060f1SDimitry Andric MVT MVTDst, MVT MVTSrc) const { 389fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to "); 390fe6060f1SDimitry Andric 391fe6060f1SDimitry Andric unsigned Move; 392fe6060f1SDimitry Andric 393fe6060f1SDimitry Andric if (MVTDst == MVT::i16) 394fe6060f1SDimitry Andric Move = M68k::MOV16rr; 395fe6060f1SDimitry Andric else // i32 396fe6060f1SDimitry Andric Move = M68k::MOV32rr; 397fe6060f1SDimitry Andric 39804eeddc0SDimitry Andric Register Dst = MIB->getOperand(0).getReg(); 39904eeddc0SDimitry Andric Register Src = MIB->getOperand(1).getReg(); 400fe6060f1SDimitry Andric 401fe6060f1SDimitry Andric assert(Dst != Src && "You cannot use the same Regs with MOVSX_RR"); 402fe6060f1SDimitry Andric 403fe6060f1SDimitry Andric const auto &TRI = getRegisterInfo(); 404fe6060f1SDimitry Andric 405fe6060f1SDimitry Andric const auto *RCDst = TRI.getMaximalPhysRegClass(Dst, MVTDst); 406fe6060f1SDimitry Andric const auto *RCSrc = TRI.getMaximalPhysRegClass(Src, MVTSrc); 407fe6060f1SDimitry Andric 408fe6060f1SDimitry Andric assert(RCDst && RCSrc && "Wrong use of MOVSX_RR"); 409fe6060f1SDimitry Andric assert(RCDst != RCSrc && "You cannot use the same Reg Classes with MOVSX_RR"); 410fe6060f1SDimitry Andric 411fe6060f1SDimitry Andric // We need to find the super source register that matches the size of Dst 412fe6060f1SDimitry Andric unsigned SSrc = RI.getMatchingMegaReg(Src, RCDst); 413fe6060f1SDimitry Andric assert(SSrc && "No viable MEGA register available"); 414fe6060f1SDimitry Andric 415fe6060f1SDimitry Andric MachineBasicBlock &MBB = *MIB->getParent(); 416fe6060f1SDimitry Andric DebugLoc DL = MIB->getDebugLoc(); 417fe6060f1SDimitry Andric 418fe6060f1SDimitry Andric if (Dst != SSrc) { 419fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Move and " << '\n'); 420fe6060f1SDimitry Andric BuildMI(MBB, MIB.getInstr(), DL, get(Move), Dst).addReg(SSrc); 421fe6060f1SDimitry Andric } 422fe6060f1SDimitry Andric 423fe6060f1SDimitry Andric if (IsSigned) { 424fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Sign Extend" << '\n'); 425fe6060f1SDimitry Andric AddSExt(MBB, MIB.getInstr(), DL, Dst, MVTSrc, MVTDst); 426fe6060f1SDimitry Andric } else { 427fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Zero Extend" << '\n'); 428fe6060f1SDimitry Andric AddZExt(MBB, MIB.getInstr(), DL, Dst, MVTSrc, MVTDst); 429fe6060f1SDimitry Andric } 430fe6060f1SDimitry Andric 431fe6060f1SDimitry Andric MIB->eraseFromParent(); 432fe6060f1SDimitry Andric 433fe6060f1SDimitry Andric return true; 434fe6060f1SDimitry Andric } 435fe6060f1SDimitry Andric 436fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandMOVSZX_RM(MachineInstrBuilder &MIB, bool IsSigned, 437fe6060f1SDimitry Andric const MCInstrDesc &Desc, MVT MVTDst, 438fe6060f1SDimitry Andric MVT MVTSrc) const { 439fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to LOAD and "); 440fe6060f1SDimitry Andric 44104eeddc0SDimitry Andric Register Dst = MIB->getOperand(0).getReg(); 442fe6060f1SDimitry Andric 443fe6060f1SDimitry Andric // We need the subreg of Dst to make instruction verifier happy because the 444fe6060f1SDimitry Andric // real machine instruction consumes and produces values of the same size and 445fe6060f1SDimitry Andric // the registers the will be used here fall into different classes and this 446fe6060f1SDimitry Andric // makes IV cry. We could use a bigger operation, but this will put some 447fe6060f1SDimitry Andric // pressure on cache and memory, so no. 448fe6060f1SDimitry Andric unsigned SubDst = 449fe6060f1SDimitry Andric RI.getSubReg(Dst, MVTSrc == MVT::i8 ? M68k::MxSubRegIndex8Lo 450fe6060f1SDimitry Andric : M68k::MxSubRegIndex16Lo); 451fe6060f1SDimitry Andric assert(SubDst && "No viable SUB register available"); 452fe6060f1SDimitry Andric 453fe6060f1SDimitry Andric // Make this a plain move 454fe6060f1SDimitry Andric MIB->setDesc(Desc); 455fe6060f1SDimitry Andric MIB->getOperand(0).setReg(SubDst); 456fe6060f1SDimitry Andric 457fe6060f1SDimitry Andric MachineBasicBlock::iterator I = MIB.getInstr(); 458fe6060f1SDimitry Andric I++; 459fe6060f1SDimitry Andric MachineBasicBlock &MBB = *MIB->getParent(); 460fe6060f1SDimitry Andric DebugLoc DL = MIB->getDebugLoc(); 461fe6060f1SDimitry Andric 462fe6060f1SDimitry Andric if (IsSigned) { 463fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Sign Extend" << '\n'); 464fe6060f1SDimitry Andric AddSExt(MBB, I, DL, Dst, MVTSrc, MVTDst); 465fe6060f1SDimitry Andric } else { 466fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Zero Extend" << '\n'); 467fe6060f1SDimitry Andric AddZExt(MBB, I, DL, Dst, MVTSrc, MVTDst); 468fe6060f1SDimitry Andric } 469fe6060f1SDimitry Andric 470fe6060f1SDimitry Andric return true; 471fe6060f1SDimitry Andric } 472fe6060f1SDimitry Andric 473fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandPUSH_POP(MachineInstrBuilder &MIB, 474fe6060f1SDimitry Andric const MCInstrDesc &Desc, bool IsPush) const { 475fe6060f1SDimitry Andric MachineBasicBlock::iterator I = MIB.getInstr(); 476fe6060f1SDimitry Andric I++; 477fe6060f1SDimitry Andric MachineBasicBlock &MBB = *MIB->getParent(); 478fe6060f1SDimitry Andric MachineOperand MO = MIB->getOperand(0); 479fe6060f1SDimitry Andric DebugLoc DL = MIB->getDebugLoc(); 480fe6060f1SDimitry Andric if (IsPush) 481fe6060f1SDimitry Andric BuildMI(MBB, I, DL, Desc).addReg(RI.getStackRegister()).add(MO); 482fe6060f1SDimitry Andric else 483fe6060f1SDimitry Andric BuildMI(MBB, I, DL, Desc, MO.getReg()).addReg(RI.getStackRegister()); 484fe6060f1SDimitry Andric 485fe6060f1SDimitry Andric MIB->eraseFromParent(); 486fe6060f1SDimitry Andric return true; 487fe6060f1SDimitry Andric } 488fe6060f1SDimitry Andric 489fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const { 490fe6060f1SDimitry Andric 491fe6060f1SDimitry Andric // Replace the pseudo instruction with the real one 492fe6060f1SDimitry Andric if (IsToCCR) 493fe6060f1SDimitry Andric MIB->setDesc(get(M68k::MOV16cd)); 494fe6060f1SDimitry Andric else 495fe6060f1SDimitry Andric // FIXME M68010 or later is required 496fe6060f1SDimitry Andric MIB->setDesc(get(M68k::MOV16dc)); 497fe6060f1SDimitry Andric 498fe6060f1SDimitry Andric // Promote used register to the next class 499fe6060f1SDimitry Andric auto &Opd = MIB->getOperand(1); 500fe6060f1SDimitry Andric Opd.setReg(getRegisterInfo().getMatchingSuperReg( 501fe6060f1SDimitry Andric Opd.getReg(), M68k::MxSubRegIndex8Lo, &M68k::DR16RegClass)); 502fe6060f1SDimitry Andric 503fe6060f1SDimitry Andric return true; 504fe6060f1SDimitry Andric } 505fe6060f1SDimitry Andric 506fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandMOVEM(MachineInstrBuilder &MIB, 507fe6060f1SDimitry Andric const MCInstrDesc &Desc, bool IsRM) const { 508fe6060f1SDimitry Andric int Reg = 0, Offset = 0, Base = 0; 509fe6060f1SDimitry Andric auto XR32 = RI.getRegClass(M68k::XR32RegClassID); 510fe6060f1SDimitry Andric auto DL = MIB->getDebugLoc(); 511fe6060f1SDimitry Andric auto MI = MIB.getInstr(); 512fe6060f1SDimitry Andric auto &MBB = *MIB->getParent(); 513fe6060f1SDimitry Andric 514fe6060f1SDimitry Andric if (IsRM) { 515fe6060f1SDimitry Andric Reg = MIB->getOperand(0).getReg(); 516fe6060f1SDimitry Andric Offset = MIB->getOperand(1).getImm(); 517fe6060f1SDimitry Andric Base = MIB->getOperand(2).getReg(); 518fe6060f1SDimitry Andric } else { 519fe6060f1SDimitry Andric Offset = MIB->getOperand(0).getImm(); 520fe6060f1SDimitry Andric Base = MIB->getOperand(1).getReg(); 521fe6060f1SDimitry Andric Reg = MIB->getOperand(2).getReg(); 522fe6060f1SDimitry Andric } 523fe6060f1SDimitry Andric 524fe6060f1SDimitry Andric // If the register is not in XR32 then it is smaller than 32 bit, we 525fe6060f1SDimitry Andric // implicitly promote it to 32 526fe6060f1SDimitry Andric if (!XR32->contains(Reg)) { 527fe6060f1SDimitry Andric Reg = RI.getMatchingMegaReg(Reg, XR32); 528fe6060f1SDimitry Andric assert(Reg && "Has not meaningful MEGA register"); 529fe6060f1SDimitry Andric } 530fe6060f1SDimitry Andric 531fe6060f1SDimitry Andric unsigned Mask = 1 << RI.getSpillRegisterOrder(Reg); 532fe6060f1SDimitry Andric if (IsRM) { 533fe6060f1SDimitry Andric BuildMI(MBB, MI, DL, Desc) 534fe6060f1SDimitry Andric .addImm(Mask) 535fe6060f1SDimitry Andric .addImm(Offset) 536fe6060f1SDimitry Andric .addReg(Base) 537fe6060f1SDimitry Andric .addReg(Reg, RegState::ImplicitDefine) 538fe6060f1SDimitry Andric .copyImplicitOps(*MIB); 539fe6060f1SDimitry Andric } else { 540fe6060f1SDimitry Andric BuildMI(MBB, MI, DL, Desc) 541fe6060f1SDimitry Andric .addImm(Offset) 542fe6060f1SDimitry Andric .addReg(Base) 543fe6060f1SDimitry Andric .addImm(Mask) 544fe6060f1SDimitry Andric .addReg(Reg, RegState::Implicit) 545fe6060f1SDimitry Andric .copyImplicitOps(*MIB); 546fe6060f1SDimitry Andric } 547fe6060f1SDimitry Andric 548fe6060f1SDimitry Andric MIB->eraseFromParent(); 549fe6060f1SDimitry Andric 550fe6060f1SDimitry Andric return true; 551fe6060f1SDimitry Andric } 552fe6060f1SDimitry Andric 553fe6060f1SDimitry Andric /// Expand a single-def pseudo instruction to a two-addr 554fe6060f1SDimitry Andric /// instruction with two undef reads of the register being defined. 555fe6060f1SDimitry Andric /// This is used for mapping: 556fe6060f1SDimitry Andric /// %d0 = SETCS_C32d 557fe6060f1SDimitry Andric /// to: 558fe6060f1SDimitry Andric /// %d0 = SUBX32dd %d0<undef>, %d0<undef> 559fe6060f1SDimitry Andric /// 560fe6060f1SDimitry Andric static bool Expand2AddrUndef(MachineInstrBuilder &MIB, 561fe6060f1SDimitry Andric const MCInstrDesc &Desc) { 562fe6060f1SDimitry Andric assert(Desc.getNumOperands() == 3 && "Expected two-addr instruction."); 56304eeddc0SDimitry Andric Register Reg = MIB->getOperand(0).getReg(); 564fe6060f1SDimitry Andric MIB->setDesc(Desc); 565fe6060f1SDimitry Andric 566fe6060f1SDimitry Andric // MachineInstr::addOperand() will insert explicit operands before any 567fe6060f1SDimitry Andric // implicit operands. 568fe6060f1SDimitry Andric MIB.addReg(Reg, RegState::Undef).addReg(Reg, RegState::Undef); 569fe6060f1SDimitry Andric // But we don't trust that. 570fe6060f1SDimitry Andric assert(MIB->getOperand(1).getReg() == Reg && 571fe6060f1SDimitry Andric MIB->getOperand(2).getReg() == Reg && "Misplaced operand"); 572fe6060f1SDimitry Andric return true; 573fe6060f1SDimitry Andric } 574fe6060f1SDimitry Andric 575fe6060f1SDimitry Andric bool M68kInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { 576fe6060f1SDimitry Andric MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI); 577fe6060f1SDimitry Andric switch (MI.getOpcode()) { 578fe6060f1SDimitry Andric case M68k::PUSH8d: 579fe6060f1SDimitry Andric return ExpandPUSH_POP(MIB, get(M68k::MOV8ed), true); 580fe6060f1SDimitry Andric case M68k::PUSH16d: 581fe6060f1SDimitry Andric return ExpandPUSH_POP(MIB, get(M68k::MOV16er), true); 582fe6060f1SDimitry Andric case M68k::PUSH32r: 583fe6060f1SDimitry Andric return ExpandPUSH_POP(MIB, get(M68k::MOV32er), true); 584fe6060f1SDimitry Andric 585fe6060f1SDimitry Andric case M68k::POP8d: 586fe6060f1SDimitry Andric return ExpandPUSH_POP(MIB, get(M68k::MOV8do), false); 587fe6060f1SDimitry Andric case M68k::POP16d: 588fe6060f1SDimitry Andric return ExpandPUSH_POP(MIB, get(M68k::MOV16ro), false); 589fe6060f1SDimitry Andric case M68k::POP32r: 590fe6060f1SDimitry Andric return ExpandPUSH_POP(MIB, get(M68k::MOV32ro), false); 591fe6060f1SDimitry Andric 592fe6060f1SDimitry Andric case M68k::SETCS_C8d: 593fe6060f1SDimitry Andric return Expand2AddrUndef(MIB, get(M68k::SUBX8dd)); 594fe6060f1SDimitry Andric case M68k::SETCS_C16d: 595fe6060f1SDimitry Andric return Expand2AddrUndef(MIB, get(M68k::SUBX16dd)); 596fe6060f1SDimitry Andric case M68k::SETCS_C32d: 597fe6060f1SDimitry Andric return Expand2AddrUndef(MIB, get(M68k::SUBX32dd)); 598fe6060f1SDimitry Andric } 599fe6060f1SDimitry Andric return false; 600fe6060f1SDimitry Andric } 601fe6060f1SDimitry Andric 602fe6060f1SDimitry Andric bool M68kInstrInfo::isPCRelRegisterOperandLegal( 603fe6060f1SDimitry Andric const MachineOperand &MO) const { 604fe6060f1SDimitry Andric assert(MO.isReg()); 605fe6060f1SDimitry Andric 60681ad6265SDimitry Andric // Check whether this MO belongs to an instruction with addressing mode 'k', 60781ad6265SDimitry Andric // Refer to TargetInstrInfo.h for more information about this function. 608fe6060f1SDimitry Andric 60981ad6265SDimitry Andric const MachineInstr *MI = MO.getParent(); 61081ad6265SDimitry Andric const unsigned NameIndices = M68kInstrNameIndices[MI->getOpcode()]; 61181ad6265SDimitry Andric StringRef InstrName(&M68kInstrNameData[NameIndices]); 61281ad6265SDimitry Andric const unsigned OperandNo = MI->getOperandNo(&MO); 61381ad6265SDimitry Andric 61481ad6265SDimitry Andric // If this machine operand is the 2nd operand, then check 61581ad6265SDimitry Andric // whether the instruction has destination addressing mode 'k'. 61681ad6265SDimitry Andric if (OperandNo == 1) 61781ad6265SDimitry Andric return Regex("[A-Z]+(8|16|32)k[a-z](_TC)?$").match(InstrName); 61881ad6265SDimitry Andric 61981ad6265SDimitry Andric // If this machine operand is the last one, then check 62081ad6265SDimitry Andric // whether the instruction has source addressing mode 'k'. 62181ad6265SDimitry Andric if (OperandNo == MI->getNumExplicitOperands() - 1) 62281ad6265SDimitry Andric return Regex("[A-Z]+(8|16|32)[a-z]k(_TC)?$").match(InstrName); 62381ad6265SDimitry Andric 624fe6060f1SDimitry Andric return false; 625fe6060f1SDimitry Andric } 626fe6060f1SDimitry Andric 627fe6060f1SDimitry Andric void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 628fe6060f1SDimitry Andric MachineBasicBlock::iterator MI, 629fe6060f1SDimitry Andric const DebugLoc &DL, MCRegister DstReg, 630fe6060f1SDimitry Andric MCRegister SrcReg, bool KillSrc) const { 631fe6060f1SDimitry Andric unsigned Opc = 0; 632fe6060f1SDimitry Andric 633fe6060f1SDimitry Andric // First deal with the normal symmetric copies. 634fe6060f1SDimitry Andric if (M68k::XR32RegClass.contains(DstReg, SrcReg)) 635fe6060f1SDimitry Andric Opc = M68k::MOV32rr; 636fe6060f1SDimitry Andric else if (M68k::XR16RegClass.contains(DstReg, SrcReg)) 637fe6060f1SDimitry Andric Opc = M68k::MOV16rr; 638fe6060f1SDimitry Andric else if (M68k::DR8RegClass.contains(DstReg, SrcReg)) 639fe6060f1SDimitry Andric Opc = M68k::MOV8dd; 640fe6060f1SDimitry Andric 641fe6060f1SDimitry Andric if (Opc) { 642fe6060f1SDimitry Andric BuildMI(MBB, MI, DL, get(Opc), DstReg) 643fe6060f1SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 644fe6060f1SDimitry Andric return; 645fe6060f1SDimitry Andric } 646fe6060f1SDimitry Andric 647fe6060f1SDimitry Andric // Now deal with asymmetrically sized copies. The cases that follow are upcast 648fe6060f1SDimitry Andric // moves. 649fe6060f1SDimitry Andric // 650fe6060f1SDimitry Andric // NOTE 651fe6060f1SDimitry Andric // These moves are not aware of type nature of these values and thus 652fe6060f1SDimitry Andric // won't do any SExt or ZExt and upper bits will basically contain garbage. 653fe6060f1SDimitry Andric MachineInstrBuilder MIB(*MBB.getParent(), MI); 654fe6060f1SDimitry Andric if (M68k::DR8RegClass.contains(SrcReg)) { 655fe6060f1SDimitry Andric if (M68k::XR16RegClass.contains(DstReg)) 656fe6060f1SDimitry Andric Opc = M68k::MOVXd16d8; 657fe6060f1SDimitry Andric else if (M68k::XR32RegClass.contains(DstReg)) 658fe6060f1SDimitry Andric Opc = M68k::MOVXd32d8; 659fe6060f1SDimitry Andric } else if (M68k::XR16RegClass.contains(SrcReg) && 660fe6060f1SDimitry Andric M68k::XR32RegClass.contains(DstReg)) 661fe6060f1SDimitry Andric Opc = M68k::MOVXd32d16; 662fe6060f1SDimitry Andric 663fe6060f1SDimitry Andric if (Opc) { 664fe6060f1SDimitry Andric BuildMI(MBB, MI, DL, get(Opc), DstReg) 665fe6060f1SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 666fe6060f1SDimitry Andric return; 667fe6060f1SDimitry Andric } 668fe6060f1SDimitry Andric 669fe6060f1SDimitry Andric bool FromCCR = SrcReg == M68k::CCR; 670fe6060f1SDimitry Andric bool FromSR = SrcReg == M68k::SR; 671fe6060f1SDimitry Andric bool ToCCR = DstReg == M68k::CCR; 672fe6060f1SDimitry Andric bool ToSR = DstReg == M68k::SR; 673fe6060f1SDimitry Andric 674fe6060f1SDimitry Andric if (FromCCR) { 675fe6060f1SDimitry Andric assert(M68k::DR8RegClass.contains(DstReg) && 676fe6060f1SDimitry Andric "Need DR8 register to copy CCR"); 677fe6060f1SDimitry Andric Opc = M68k::MOV8dc; 678fe6060f1SDimitry Andric } else if (ToCCR) { 679fe6060f1SDimitry Andric assert(M68k::DR8RegClass.contains(SrcReg) && 680fe6060f1SDimitry Andric "Need DR8 register to copy CCR"); 681fe6060f1SDimitry Andric Opc = M68k::MOV8cd; 682fe6060f1SDimitry Andric } else if (FromSR || ToSR) 683fe6060f1SDimitry Andric llvm_unreachable("Cannot emit SR copy instruction"); 684fe6060f1SDimitry Andric 685fe6060f1SDimitry Andric if (Opc) { 686fe6060f1SDimitry Andric BuildMI(MBB, MI, DL, get(Opc), DstReg) 687fe6060f1SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 688fe6060f1SDimitry Andric return; 689fe6060f1SDimitry Andric } 690fe6060f1SDimitry Andric 691fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to " 692fe6060f1SDimitry Andric << RI.getName(DstReg) << '\n'); 693fe6060f1SDimitry Andric llvm_unreachable("Cannot emit physreg copy instruction"); 694fe6060f1SDimitry Andric } 695fe6060f1SDimitry Andric 696fe6060f1SDimitry Andric namespace { 697fe6060f1SDimitry Andric unsigned getLoadStoreRegOpcode(unsigned Reg, const TargetRegisterClass *RC, 698fe6060f1SDimitry Andric const TargetRegisterInfo *TRI, 699fe6060f1SDimitry Andric const M68kSubtarget &STI, bool load) { 700fe6060f1SDimitry Andric switch (TRI->getRegSizeInBits(*RC)) { 701fe6060f1SDimitry Andric default: 702fe6060f1SDimitry Andric llvm_unreachable("Unknown spill size"); 703fe6060f1SDimitry Andric case 8: 704fe6060f1SDimitry Andric if (M68k::DR8RegClass.hasSubClassEq(RC)) 705*bdd1243dSDimitry Andric return load ? M68k::MOV8dp : M68k::MOV8pd; 706fe6060f1SDimitry Andric if (M68k::CCRCRegClass.hasSubClassEq(RC)) 707fe6060f1SDimitry Andric return load ? M68k::MOV16cp : M68k::MOV16pc; 708fe6060f1SDimitry Andric 709fe6060f1SDimitry Andric llvm_unreachable("Unknown 1-byte regclass"); 710fe6060f1SDimitry Andric case 16: 711fe6060f1SDimitry Andric assert(M68k::XR16RegClass.hasSubClassEq(RC) && "Unknown 2-byte regclass"); 712fe6060f1SDimitry Andric return load ? M68k::MOVM16mp_P : M68k::MOVM16pm_P; 713fe6060f1SDimitry Andric case 32: 714fe6060f1SDimitry Andric assert(M68k::XR32RegClass.hasSubClassEq(RC) && "Unknown 4-byte regclass"); 715fe6060f1SDimitry Andric return load ? M68k::MOVM32mp_P : M68k::MOVM32pm_P; 716fe6060f1SDimitry Andric } 717fe6060f1SDimitry Andric } 718fe6060f1SDimitry Andric 719fe6060f1SDimitry Andric unsigned getStoreRegOpcode(unsigned SrcReg, const TargetRegisterClass *RC, 720fe6060f1SDimitry Andric const TargetRegisterInfo *TRI, 721fe6060f1SDimitry Andric const M68kSubtarget &STI) { 722fe6060f1SDimitry Andric return getLoadStoreRegOpcode(SrcReg, RC, TRI, STI, false); 723fe6060f1SDimitry Andric } 724fe6060f1SDimitry Andric 725fe6060f1SDimitry Andric unsigned getLoadRegOpcode(unsigned DstReg, const TargetRegisterClass *RC, 726fe6060f1SDimitry Andric const TargetRegisterInfo *TRI, 727fe6060f1SDimitry Andric const M68kSubtarget &STI) { 728fe6060f1SDimitry Andric return getLoadStoreRegOpcode(DstReg, RC, TRI, STI, true); 729fe6060f1SDimitry Andric } 730fe6060f1SDimitry Andric } // end anonymous namespace 731fe6060f1SDimitry Andric 732fe6060f1SDimitry Andric bool M68kInstrInfo::getStackSlotRange(const TargetRegisterClass *RC, 733fe6060f1SDimitry Andric unsigned SubIdx, unsigned &Size, 734fe6060f1SDimitry Andric unsigned &Offset, 735fe6060f1SDimitry Andric const MachineFunction &MF) const { 736fe6060f1SDimitry Andric // The slot size must be the maximum size so we can easily use MOVEM.L 737fe6060f1SDimitry Andric Size = 4; 738fe6060f1SDimitry Andric Offset = 0; 739fe6060f1SDimitry Andric return true; 740fe6060f1SDimitry Andric } 741fe6060f1SDimitry Andric 742*bdd1243dSDimitry Andric void M68kInstrInfo::storeRegToStackSlot( 743*bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, 744*bdd1243dSDimitry Andric bool IsKill, int FrameIndex, const TargetRegisterClass *RC, 745*bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, Register VReg) const { 746*bdd1243dSDimitry Andric const MachineFrameInfo &MFI = MBB.getParent()->getFrameInfo(); 747*bdd1243dSDimitry Andric assert(MFI.getObjectSize(FrameIndex) >= TRI->getSpillSize(*RC) && 748*bdd1243dSDimitry Andric "Stack slot is too small to store"); 749*bdd1243dSDimitry Andric 750fe6060f1SDimitry Andric unsigned Opc = getStoreRegOpcode(SrcReg, RC, TRI, Subtarget); 751fe6060f1SDimitry Andric DebugLoc DL = MBB.findDebugLoc(MI); 752fe6060f1SDimitry Andric // (0,FrameIndex) <- $reg 753fe6060f1SDimitry Andric M68k::addFrameReference(BuildMI(MBB, MI, DL, get(Opc)), FrameIndex) 754fe6060f1SDimitry Andric .addReg(SrcReg, getKillRegState(IsKill)); 755fe6060f1SDimitry Andric } 756fe6060f1SDimitry Andric 757fe6060f1SDimitry Andric void M68kInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 758fe6060f1SDimitry Andric MachineBasicBlock::iterator MI, 759fe6060f1SDimitry Andric Register DstReg, int FrameIndex, 760fe6060f1SDimitry Andric const TargetRegisterClass *RC, 761*bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, 762*bdd1243dSDimitry Andric Register VReg) const { 763*bdd1243dSDimitry Andric const MachineFrameInfo &MFI = MBB.getParent()->getFrameInfo(); 764*bdd1243dSDimitry Andric assert(MFI.getObjectSize(FrameIndex) >= TRI->getSpillSize(*RC) && 765*bdd1243dSDimitry Andric "Stack slot is too small to load"); 766*bdd1243dSDimitry Andric 767fe6060f1SDimitry Andric unsigned Opc = getLoadRegOpcode(DstReg, RC, TRI, Subtarget); 768fe6060f1SDimitry Andric DebugLoc DL = MBB.findDebugLoc(MI); 769fe6060f1SDimitry Andric M68k::addFrameReference(BuildMI(MBB, MI, DL, get(Opc), DstReg), FrameIndex); 770fe6060f1SDimitry Andric } 771fe6060f1SDimitry Andric 772fe6060f1SDimitry Andric /// Return a virtual register initialized with the the global base register 773fe6060f1SDimitry Andric /// value. Output instructions required to initialize the register in the 774fe6060f1SDimitry Andric /// function entry block, if necessary. 775fe6060f1SDimitry Andric /// 776fe6060f1SDimitry Andric /// TODO Move this function to M68kMachineFunctionInfo. 777fe6060f1SDimitry Andric unsigned M68kInstrInfo::getGlobalBaseReg(MachineFunction *MF) const { 778fe6060f1SDimitry Andric M68kMachineFunctionInfo *MxFI = MF->getInfo<M68kMachineFunctionInfo>(); 779fe6060f1SDimitry Andric unsigned GlobalBaseReg = MxFI->getGlobalBaseReg(); 780fe6060f1SDimitry Andric if (GlobalBaseReg != 0) 781fe6060f1SDimitry Andric return GlobalBaseReg; 782fe6060f1SDimitry Andric 783fe6060f1SDimitry Andric // Create the register. The code to initialize it is inserted later, 784fe6060f1SDimitry Andric // by the CGBR pass (below). 785fe6060f1SDimitry Andric // 786fe6060f1SDimitry Andric // NOTE 787fe6060f1SDimitry Andric // Normally M68k uses A5 register as global base pointer but this will 788fe6060f1SDimitry Andric // create unnecessary spill if we use less then 4 registers in code; since A5 789fe6060f1SDimitry Andric // is callee-save anyway we could try to allocate caller-save first and if 790fe6060f1SDimitry Andric // lucky get one, otherwise it does not really matter which callee-save to 791fe6060f1SDimitry Andric // use. 792fe6060f1SDimitry Andric MachineRegisterInfo &RegInfo = MF->getRegInfo(); 793fe6060f1SDimitry Andric GlobalBaseReg = RegInfo.createVirtualRegister(&M68k::AR32_NOSPRegClass); 794fe6060f1SDimitry Andric MxFI->setGlobalBaseReg(GlobalBaseReg); 795fe6060f1SDimitry Andric return GlobalBaseReg; 796fe6060f1SDimitry Andric } 797fe6060f1SDimitry Andric 798fe6060f1SDimitry Andric std::pair<unsigned, unsigned> 799fe6060f1SDimitry Andric M68kInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { 800fe6060f1SDimitry Andric return std::make_pair(TF, 0u); 801fe6060f1SDimitry Andric } 802fe6060f1SDimitry Andric 803fe6060f1SDimitry Andric ArrayRef<std::pair<unsigned, const char *>> 804fe6060f1SDimitry Andric M68kInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { 805fe6060f1SDimitry Andric using namespace M68kII; 806fe6060f1SDimitry Andric static const std::pair<unsigned, const char *> TargetFlags[] = { 807fe6060f1SDimitry Andric {MO_ABSOLUTE_ADDRESS, "m68k-absolute"}, 808fe6060f1SDimitry Andric {MO_PC_RELATIVE_ADDRESS, "m68k-pcrel"}, 809fe6060f1SDimitry Andric {MO_GOT, "m68k-got"}, 810fe6060f1SDimitry Andric {MO_GOTOFF, "m68k-gotoff"}, 811fe6060f1SDimitry Andric {MO_GOTPCREL, "m68k-gotpcrel"}, 812fe6060f1SDimitry Andric {MO_PLT, "m68k-plt"}}; 813*bdd1243dSDimitry Andric return ArrayRef(TargetFlags); 814fe6060f1SDimitry Andric } 815fe6060f1SDimitry Andric 816fe6060f1SDimitry Andric namespace { 817fe6060f1SDimitry Andric /// Create Global Base Reg pass. This initializes the PIC global base register 818fe6060f1SDimitry Andric struct CGBR : public MachineFunctionPass { 819fe6060f1SDimitry Andric static char ID; 820fe6060f1SDimitry Andric CGBR() : MachineFunctionPass(ID) {} 821fe6060f1SDimitry Andric 822fe6060f1SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override { 823fe6060f1SDimitry Andric const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>(); 824fe6060f1SDimitry Andric M68kMachineFunctionInfo *MxFI = MF.getInfo<M68kMachineFunctionInfo>(); 825fe6060f1SDimitry Andric 826fe6060f1SDimitry Andric unsigned GlobalBaseReg = MxFI->getGlobalBaseReg(); 827fe6060f1SDimitry Andric 828fe6060f1SDimitry Andric // If we didn't need a GlobalBaseReg, don't insert code. 829fe6060f1SDimitry Andric if (GlobalBaseReg == 0) 830fe6060f1SDimitry Andric return false; 831fe6060f1SDimitry Andric 832fe6060f1SDimitry Andric // Insert the set of GlobalBaseReg into the first MBB of the function 833fe6060f1SDimitry Andric MachineBasicBlock &FirstMBB = MF.front(); 834fe6060f1SDimitry Andric MachineBasicBlock::iterator MBBI = FirstMBB.begin(); 835fe6060f1SDimitry Andric DebugLoc DL = FirstMBB.findDebugLoc(MBBI); 836fe6060f1SDimitry Andric const M68kInstrInfo *TII = STI.getInstrInfo(); 837fe6060f1SDimitry Andric 838fe6060f1SDimitry Andric // Generate lea (__GLOBAL_OFFSET_TABLE_,%PC), %A5 839fe6060f1SDimitry Andric BuildMI(FirstMBB, MBBI, DL, TII->get(M68k::LEA32q), GlobalBaseReg) 840fe6060f1SDimitry Andric .addExternalSymbol("_GLOBAL_OFFSET_TABLE_", M68kII::MO_GOTPCREL); 841fe6060f1SDimitry Andric 842fe6060f1SDimitry Andric return true; 843fe6060f1SDimitry Andric } 844fe6060f1SDimitry Andric 845fe6060f1SDimitry Andric StringRef getPassName() const override { 846fe6060f1SDimitry Andric return "M68k PIC Global Base Reg Initialization"; 847fe6060f1SDimitry Andric } 848fe6060f1SDimitry Andric 849fe6060f1SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 850fe6060f1SDimitry Andric AU.setPreservesCFG(); 851fe6060f1SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 852fe6060f1SDimitry Andric } 853fe6060f1SDimitry Andric }; 854fe6060f1SDimitry Andric } // namespace 855fe6060f1SDimitry Andric 856fe6060f1SDimitry Andric char CGBR::ID = 0; 857fe6060f1SDimitry Andric FunctionPass *llvm::createM68kGlobalBaseRegPass() { return new CGBR(); } 858