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"); 364*5f757f3fSDimitry Andric (void)RCSrc; 365fe6060f1SDimitry Andric 366fe6060f1SDimitry Andric // We need to find the super source register that matches the size of Dst 367fe6060f1SDimitry Andric unsigned SSrc = RI.getMatchingMegaReg(Src, RCDst); 368fe6060f1SDimitry Andric assert(SSrc && "No viable MEGA register available"); 369fe6060f1SDimitry Andric 370fe6060f1SDimitry Andric DebugLoc DL = MIB->getDebugLoc(); 371fe6060f1SDimitry Andric 372fe6060f1SDimitry Andric // If it happens to that super source register is the destination register 373fe6060f1SDimitry Andric // we do nothing 374fe6060f1SDimitry Andric if (Dst == SSrc) { 375fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Remove " << *MIB.getInstr() << '\n'); 376fe6060f1SDimitry Andric MIB->eraseFromParent(); 377fe6060f1SDimitry Andric } else { // otherwise we need to MOV 378fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to MOV\n"); 379fe6060f1SDimitry Andric MIB->setDesc(get(Move)); 380fe6060f1SDimitry Andric MIB->getOperand(1).setReg(SSrc); 381fe6060f1SDimitry Andric } 382fe6060f1SDimitry Andric 383fe6060f1SDimitry Andric return true; 384fe6060f1SDimitry Andric } 385fe6060f1SDimitry Andric 386fe6060f1SDimitry Andric /// Expand SExt MOVE pseudos into a MOV and a EXT if the operands are two 387fe6060f1SDimitry Andric /// different registers or just EXT if it is the same register 388fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandMOVSZX_RR(MachineInstrBuilder &MIB, bool IsSigned, 389fe6060f1SDimitry Andric MVT MVTDst, MVT MVTSrc) const { 390fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to "); 391fe6060f1SDimitry Andric 392fe6060f1SDimitry Andric unsigned Move; 393fe6060f1SDimitry Andric 394fe6060f1SDimitry Andric if (MVTDst == MVT::i16) 395fe6060f1SDimitry Andric Move = M68k::MOV16rr; 396fe6060f1SDimitry Andric else // i32 397fe6060f1SDimitry Andric Move = M68k::MOV32rr; 398fe6060f1SDimitry Andric 39904eeddc0SDimitry Andric Register Dst = MIB->getOperand(0).getReg(); 40004eeddc0SDimitry Andric Register Src = MIB->getOperand(1).getReg(); 401fe6060f1SDimitry Andric 402fe6060f1SDimitry Andric assert(Dst != Src && "You cannot use the same Regs with MOVSX_RR"); 403fe6060f1SDimitry Andric 404fe6060f1SDimitry Andric const auto &TRI = getRegisterInfo(); 405fe6060f1SDimitry Andric 406fe6060f1SDimitry Andric const auto *RCDst = TRI.getMaximalPhysRegClass(Dst, MVTDst); 407fe6060f1SDimitry Andric const auto *RCSrc = TRI.getMaximalPhysRegClass(Src, MVTSrc); 408fe6060f1SDimitry Andric 409fe6060f1SDimitry Andric assert(RCDst && RCSrc && "Wrong use of MOVSX_RR"); 410fe6060f1SDimitry Andric assert(RCDst != RCSrc && "You cannot use the same Reg Classes with MOVSX_RR"); 411*5f757f3fSDimitry Andric (void)RCSrc; 412fe6060f1SDimitry Andric 413fe6060f1SDimitry Andric // We need to find the super source register that matches the size of Dst 414fe6060f1SDimitry Andric unsigned SSrc = RI.getMatchingMegaReg(Src, RCDst); 415fe6060f1SDimitry Andric assert(SSrc && "No viable MEGA register available"); 416fe6060f1SDimitry Andric 417fe6060f1SDimitry Andric MachineBasicBlock &MBB = *MIB->getParent(); 418fe6060f1SDimitry Andric DebugLoc DL = MIB->getDebugLoc(); 419fe6060f1SDimitry Andric 420fe6060f1SDimitry Andric if (Dst != SSrc) { 421fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Move and " << '\n'); 422fe6060f1SDimitry Andric BuildMI(MBB, MIB.getInstr(), DL, get(Move), Dst).addReg(SSrc); 423fe6060f1SDimitry Andric } 424fe6060f1SDimitry Andric 425fe6060f1SDimitry Andric if (IsSigned) { 426fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Sign Extend" << '\n'); 427fe6060f1SDimitry Andric AddSExt(MBB, MIB.getInstr(), DL, Dst, MVTSrc, MVTDst); 428fe6060f1SDimitry Andric } else { 429fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Zero Extend" << '\n'); 430fe6060f1SDimitry Andric AddZExt(MBB, MIB.getInstr(), DL, Dst, MVTSrc, MVTDst); 431fe6060f1SDimitry Andric } 432fe6060f1SDimitry Andric 433fe6060f1SDimitry Andric MIB->eraseFromParent(); 434fe6060f1SDimitry Andric 435fe6060f1SDimitry Andric return true; 436fe6060f1SDimitry Andric } 437fe6060f1SDimitry Andric 438fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandMOVSZX_RM(MachineInstrBuilder &MIB, bool IsSigned, 439fe6060f1SDimitry Andric const MCInstrDesc &Desc, MVT MVTDst, 440fe6060f1SDimitry Andric MVT MVTSrc) const { 441fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to LOAD and "); 442fe6060f1SDimitry Andric 44304eeddc0SDimitry Andric Register Dst = MIB->getOperand(0).getReg(); 444fe6060f1SDimitry Andric 445fe6060f1SDimitry Andric // We need the subreg of Dst to make instruction verifier happy because the 446fe6060f1SDimitry Andric // real machine instruction consumes and produces values of the same size and 447fe6060f1SDimitry Andric // the registers the will be used here fall into different classes and this 448fe6060f1SDimitry Andric // makes IV cry. We could use a bigger operation, but this will put some 449fe6060f1SDimitry Andric // pressure on cache and memory, so no. 450fe6060f1SDimitry Andric unsigned SubDst = 451fe6060f1SDimitry Andric RI.getSubReg(Dst, MVTSrc == MVT::i8 ? M68k::MxSubRegIndex8Lo 452fe6060f1SDimitry Andric : M68k::MxSubRegIndex16Lo); 453fe6060f1SDimitry Andric assert(SubDst && "No viable SUB register available"); 454fe6060f1SDimitry Andric 455fe6060f1SDimitry Andric // Make this a plain move 456fe6060f1SDimitry Andric MIB->setDesc(Desc); 457fe6060f1SDimitry Andric MIB->getOperand(0).setReg(SubDst); 458fe6060f1SDimitry Andric 459fe6060f1SDimitry Andric MachineBasicBlock::iterator I = MIB.getInstr(); 460fe6060f1SDimitry Andric I++; 461fe6060f1SDimitry Andric MachineBasicBlock &MBB = *MIB->getParent(); 462fe6060f1SDimitry Andric DebugLoc DL = MIB->getDebugLoc(); 463fe6060f1SDimitry Andric 464fe6060f1SDimitry Andric if (IsSigned) { 465fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Sign Extend" << '\n'); 466fe6060f1SDimitry Andric AddSExt(MBB, I, DL, Dst, MVTSrc, MVTDst); 467fe6060f1SDimitry Andric } else { 468fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Zero Extend" << '\n'); 469fe6060f1SDimitry Andric AddZExt(MBB, I, DL, Dst, MVTSrc, MVTDst); 470fe6060f1SDimitry Andric } 471fe6060f1SDimitry Andric 472fe6060f1SDimitry Andric return true; 473fe6060f1SDimitry Andric } 474fe6060f1SDimitry Andric 475fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandPUSH_POP(MachineInstrBuilder &MIB, 476fe6060f1SDimitry Andric const MCInstrDesc &Desc, bool IsPush) const { 477fe6060f1SDimitry Andric MachineBasicBlock::iterator I = MIB.getInstr(); 478fe6060f1SDimitry Andric I++; 479fe6060f1SDimitry Andric MachineBasicBlock &MBB = *MIB->getParent(); 480fe6060f1SDimitry Andric MachineOperand MO = MIB->getOperand(0); 481fe6060f1SDimitry Andric DebugLoc DL = MIB->getDebugLoc(); 482fe6060f1SDimitry Andric if (IsPush) 483fe6060f1SDimitry Andric BuildMI(MBB, I, DL, Desc).addReg(RI.getStackRegister()).add(MO); 484fe6060f1SDimitry Andric else 485fe6060f1SDimitry Andric BuildMI(MBB, I, DL, Desc, MO.getReg()).addReg(RI.getStackRegister()); 486fe6060f1SDimitry Andric 487fe6060f1SDimitry Andric MIB->eraseFromParent(); 488fe6060f1SDimitry Andric return true; 489fe6060f1SDimitry Andric } 490fe6060f1SDimitry Andric 491fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const { 492fe6060f1SDimitry Andric 493fe6060f1SDimitry Andric // Replace the pseudo instruction with the real one 494fe6060f1SDimitry Andric if (IsToCCR) 495fe6060f1SDimitry Andric MIB->setDesc(get(M68k::MOV16cd)); 496fe6060f1SDimitry Andric else 497fe6060f1SDimitry Andric // FIXME M68010 or later is required 498fe6060f1SDimitry Andric MIB->setDesc(get(M68k::MOV16dc)); 499fe6060f1SDimitry Andric 500fe6060f1SDimitry Andric // Promote used register to the next class 501fe6060f1SDimitry Andric auto &Opd = MIB->getOperand(1); 502fe6060f1SDimitry Andric Opd.setReg(getRegisterInfo().getMatchingSuperReg( 503fe6060f1SDimitry Andric Opd.getReg(), M68k::MxSubRegIndex8Lo, &M68k::DR16RegClass)); 504fe6060f1SDimitry Andric 505fe6060f1SDimitry Andric return true; 506fe6060f1SDimitry Andric } 507fe6060f1SDimitry Andric 508fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandMOVEM(MachineInstrBuilder &MIB, 509fe6060f1SDimitry Andric const MCInstrDesc &Desc, bool IsRM) const { 510fe6060f1SDimitry Andric int Reg = 0, Offset = 0, Base = 0; 511fe6060f1SDimitry Andric auto XR32 = RI.getRegClass(M68k::XR32RegClassID); 512fe6060f1SDimitry Andric auto DL = MIB->getDebugLoc(); 513fe6060f1SDimitry Andric auto MI = MIB.getInstr(); 514fe6060f1SDimitry Andric auto &MBB = *MIB->getParent(); 515fe6060f1SDimitry Andric 516fe6060f1SDimitry Andric if (IsRM) { 517fe6060f1SDimitry Andric Reg = MIB->getOperand(0).getReg(); 518fe6060f1SDimitry Andric Offset = MIB->getOperand(1).getImm(); 519fe6060f1SDimitry Andric Base = MIB->getOperand(2).getReg(); 520fe6060f1SDimitry Andric } else { 521fe6060f1SDimitry Andric Offset = MIB->getOperand(0).getImm(); 522fe6060f1SDimitry Andric Base = MIB->getOperand(1).getReg(); 523fe6060f1SDimitry Andric Reg = MIB->getOperand(2).getReg(); 524fe6060f1SDimitry Andric } 525fe6060f1SDimitry Andric 526fe6060f1SDimitry Andric // If the register is not in XR32 then it is smaller than 32 bit, we 527fe6060f1SDimitry Andric // implicitly promote it to 32 528fe6060f1SDimitry Andric if (!XR32->contains(Reg)) { 529fe6060f1SDimitry Andric Reg = RI.getMatchingMegaReg(Reg, XR32); 530fe6060f1SDimitry Andric assert(Reg && "Has not meaningful MEGA register"); 531fe6060f1SDimitry Andric } 532fe6060f1SDimitry Andric 533fe6060f1SDimitry Andric unsigned Mask = 1 << RI.getSpillRegisterOrder(Reg); 534fe6060f1SDimitry Andric if (IsRM) { 535fe6060f1SDimitry Andric BuildMI(MBB, MI, DL, Desc) 536fe6060f1SDimitry Andric .addImm(Mask) 537fe6060f1SDimitry Andric .addImm(Offset) 538fe6060f1SDimitry Andric .addReg(Base) 539fe6060f1SDimitry Andric .addReg(Reg, RegState::ImplicitDefine) 540fe6060f1SDimitry Andric .copyImplicitOps(*MIB); 541fe6060f1SDimitry Andric } else { 542fe6060f1SDimitry Andric BuildMI(MBB, MI, DL, Desc) 543fe6060f1SDimitry Andric .addImm(Offset) 544fe6060f1SDimitry Andric .addReg(Base) 545fe6060f1SDimitry Andric .addImm(Mask) 546fe6060f1SDimitry Andric .addReg(Reg, RegState::Implicit) 547fe6060f1SDimitry Andric .copyImplicitOps(*MIB); 548fe6060f1SDimitry Andric } 549fe6060f1SDimitry Andric 550fe6060f1SDimitry Andric MIB->eraseFromParent(); 551fe6060f1SDimitry Andric 552fe6060f1SDimitry Andric return true; 553fe6060f1SDimitry Andric } 554fe6060f1SDimitry Andric 555fe6060f1SDimitry Andric /// Expand a single-def pseudo instruction to a two-addr 556fe6060f1SDimitry Andric /// instruction with two undef reads of the register being defined. 557fe6060f1SDimitry Andric /// This is used for mapping: 558fe6060f1SDimitry Andric /// %d0 = SETCS_C32d 559fe6060f1SDimitry Andric /// to: 560fe6060f1SDimitry Andric /// %d0 = SUBX32dd %d0<undef>, %d0<undef> 561fe6060f1SDimitry Andric /// 562fe6060f1SDimitry Andric static bool Expand2AddrUndef(MachineInstrBuilder &MIB, 563fe6060f1SDimitry Andric const MCInstrDesc &Desc) { 564fe6060f1SDimitry Andric assert(Desc.getNumOperands() == 3 && "Expected two-addr instruction."); 56504eeddc0SDimitry Andric Register Reg = MIB->getOperand(0).getReg(); 566fe6060f1SDimitry Andric MIB->setDesc(Desc); 567fe6060f1SDimitry Andric 568fe6060f1SDimitry Andric // MachineInstr::addOperand() will insert explicit operands before any 569fe6060f1SDimitry Andric // implicit operands. 570fe6060f1SDimitry Andric MIB.addReg(Reg, RegState::Undef).addReg(Reg, RegState::Undef); 571fe6060f1SDimitry Andric // But we don't trust that. 572fe6060f1SDimitry Andric assert(MIB->getOperand(1).getReg() == Reg && 573fe6060f1SDimitry Andric MIB->getOperand(2).getReg() == Reg && "Misplaced operand"); 574fe6060f1SDimitry Andric return true; 575fe6060f1SDimitry Andric } 576fe6060f1SDimitry Andric 577fe6060f1SDimitry Andric bool M68kInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { 578fe6060f1SDimitry Andric MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI); 579fe6060f1SDimitry Andric switch (MI.getOpcode()) { 580fe6060f1SDimitry Andric case M68k::PUSH8d: 581fe6060f1SDimitry Andric return ExpandPUSH_POP(MIB, get(M68k::MOV8ed), true); 582fe6060f1SDimitry Andric case M68k::PUSH16d: 583fe6060f1SDimitry Andric return ExpandPUSH_POP(MIB, get(M68k::MOV16er), true); 584fe6060f1SDimitry Andric case M68k::PUSH32r: 585fe6060f1SDimitry Andric return ExpandPUSH_POP(MIB, get(M68k::MOV32er), true); 586fe6060f1SDimitry Andric 587fe6060f1SDimitry Andric case M68k::POP8d: 588fe6060f1SDimitry Andric return ExpandPUSH_POP(MIB, get(M68k::MOV8do), false); 589fe6060f1SDimitry Andric case M68k::POP16d: 590fe6060f1SDimitry Andric return ExpandPUSH_POP(MIB, get(M68k::MOV16ro), false); 591fe6060f1SDimitry Andric case M68k::POP32r: 592fe6060f1SDimitry Andric return ExpandPUSH_POP(MIB, get(M68k::MOV32ro), false); 593fe6060f1SDimitry Andric 594fe6060f1SDimitry Andric case M68k::SETCS_C8d: 595fe6060f1SDimitry Andric return Expand2AddrUndef(MIB, get(M68k::SUBX8dd)); 596fe6060f1SDimitry Andric case M68k::SETCS_C16d: 597fe6060f1SDimitry Andric return Expand2AddrUndef(MIB, get(M68k::SUBX16dd)); 598fe6060f1SDimitry Andric case M68k::SETCS_C32d: 599fe6060f1SDimitry Andric return Expand2AddrUndef(MIB, get(M68k::SUBX32dd)); 600fe6060f1SDimitry Andric } 601fe6060f1SDimitry Andric return false; 602fe6060f1SDimitry Andric } 603fe6060f1SDimitry Andric 604fe6060f1SDimitry Andric bool M68kInstrInfo::isPCRelRegisterOperandLegal( 605fe6060f1SDimitry Andric const MachineOperand &MO) const { 606fe6060f1SDimitry Andric assert(MO.isReg()); 607fe6060f1SDimitry Andric 60881ad6265SDimitry Andric // Check whether this MO belongs to an instruction with addressing mode 'k', 60981ad6265SDimitry Andric // Refer to TargetInstrInfo.h for more information about this function. 610fe6060f1SDimitry Andric 61181ad6265SDimitry Andric const MachineInstr *MI = MO.getParent(); 61281ad6265SDimitry Andric const unsigned NameIndices = M68kInstrNameIndices[MI->getOpcode()]; 61381ad6265SDimitry Andric StringRef InstrName(&M68kInstrNameData[NameIndices]); 61406c3fb27SDimitry Andric const unsigned OperandNo = MO.getOperandNo(); 61581ad6265SDimitry Andric 61681ad6265SDimitry Andric // If this machine operand is the 2nd operand, then check 61781ad6265SDimitry Andric // whether the instruction has destination addressing mode 'k'. 61881ad6265SDimitry Andric if (OperandNo == 1) 61981ad6265SDimitry Andric return Regex("[A-Z]+(8|16|32)k[a-z](_TC)?$").match(InstrName); 62081ad6265SDimitry Andric 62181ad6265SDimitry Andric // If this machine operand is the last one, then check 62281ad6265SDimitry Andric // whether the instruction has source addressing mode 'k'. 62381ad6265SDimitry Andric if (OperandNo == MI->getNumExplicitOperands() - 1) 62481ad6265SDimitry Andric return Regex("[A-Z]+(8|16|32)[a-z]k(_TC)?$").match(InstrName); 62581ad6265SDimitry Andric 626fe6060f1SDimitry Andric return false; 627fe6060f1SDimitry Andric } 628fe6060f1SDimitry Andric 629fe6060f1SDimitry Andric void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 630fe6060f1SDimitry Andric MachineBasicBlock::iterator MI, 631fe6060f1SDimitry Andric const DebugLoc &DL, MCRegister DstReg, 632fe6060f1SDimitry Andric MCRegister SrcReg, bool KillSrc) const { 633fe6060f1SDimitry Andric unsigned Opc = 0; 634fe6060f1SDimitry Andric 635fe6060f1SDimitry Andric // First deal with the normal symmetric copies. 636fe6060f1SDimitry Andric if (M68k::XR32RegClass.contains(DstReg, SrcReg)) 637fe6060f1SDimitry Andric Opc = M68k::MOV32rr; 638fe6060f1SDimitry Andric else if (M68k::XR16RegClass.contains(DstReg, SrcReg)) 639fe6060f1SDimitry Andric Opc = M68k::MOV16rr; 640fe6060f1SDimitry Andric else if (M68k::DR8RegClass.contains(DstReg, SrcReg)) 641fe6060f1SDimitry Andric Opc = M68k::MOV8dd; 642fe6060f1SDimitry Andric 643fe6060f1SDimitry Andric if (Opc) { 644fe6060f1SDimitry Andric BuildMI(MBB, MI, DL, get(Opc), DstReg) 645fe6060f1SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 646fe6060f1SDimitry Andric return; 647fe6060f1SDimitry Andric } 648fe6060f1SDimitry Andric 649fe6060f1SDimitry Andric // Now deal with asymmetrically sized copies. The cases that follow are upcast 650fe6060f1SDimitry Andric // moves. 651fe6060f1SDimitry Andric // 652fe6060f1SDimitry Andric // NOTE 653fe6060f1SDimitry Andric // These moves are not aware of type nature of these values and thus 654fe6060f1SDimitry Andric // won't do any SExt or ZExt and upper bits will basically contain garbage. 655fe6060f1SDimitry Andric MachineInstrBuilder MIB(*MBB.getParent(), MI); 656fe6060f1SDimitry Andric if (M68k::DR8RegClass.contains(SrcReg)) { 657fe6060f1SDimitry Andric if (M68k::XR16RegClass.contains(DstReg)) 658fe6060f1SDimitry Andric Opc = M68k::MOVXd16d8; 659fe6060f1SDimitry Andric else if (M68k::XR32RegClass.contains(DstReg)) 660fe6060f1SDimitry Andric Opc = M68k::MOVXd32d8; 661fe6060f1SDimitry Andric } else if (M68k::XR16RegClass.contains(SrcReg) && 662fe6060f1SDimitry Andric M68k::XR32RegClass.contains(DstReg)) 663fe6060f1SDimitry Andric Opc = M68k::MOVXd32d16; 664fe6060f1SDimitry Andric 665fe6060f1SDimitry Andric if (Opc) { 666fe6060f1SDimitry Andric BuildMI(MBB, MI, DL, get(Opc), DstReg) 667fe6060f1SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 668fe6060f1SDimitry Andric return; 669fe6060f1SDimitry Andric } 670fe6060f1SDimitry Andric 671fe6060f1SDimitry Andric bool FromCCR = SrcReg == M68k::CCR; 672fe6060f1SDimitry Andric bool FromSR = SrcReg == M68k::SR; 673fe6060f1SDimitry Andric bool ToCCR = DstReg == M68k::CCR; 674fe6060f1SDimitry Andric bool ToSR = DstReg == M68k::SR; 675fe6060f1SDimitry Andric 676fe6060f1SDimitry Andric if (FromCCR) { 677fe6060f1SDimitry Andric assert(M68k::DR8RegClass.contains(DstReg) && 678fe6060f1SDimitry Andric "Need DR8 register to copy CCR"); 679fe6060f1SDimitry Andric Opc = M68k::MOV8dc; 680fe6060f1SDimitry Andric } else if (ToCCR) { 681fe6060f1SDimitry Andric assert(M68k::DR8RegClass.contains(SrcReg) && 682fe6060f1SDimitry Andric "Need DR8 register to copy CCR"); 683fe6060f1SDimitry Andric Opc = M68k::MOV8cd; 684fe6060f1SDimitry Andric } else if (FromSR || ToSR) 685fe6060f1SDimitry Andric llvm_unreachable("Cannot emit SR copy instruction"); 686fe6060f1SDimitry Andric 687fe6060f1SDimitry Andric if (Opc) { 688fe6060f1SDimitry Andric BuildMI(MBB, MI, DL, get(Opc), DstReg) 689fe6060f1SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 690fe6060f1SDimitry Andric return; 691fe6060f1SDimitry Andric } 692fe6060f1SDimitry Andric 693fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to " 694fe6060f1SDimitry Andric << RI.getName(DstReg) << '\n'); 695fe6060f1SDimitry Andric llvm_unreachable("Cannot emit physreg copy instruction"); 696fe6060f1SDimitry Andric } 697fe6060f1SDimitry Andric 698fe6060f1SDimitry Andric namespace { 699fe6060f1SDimitry Andric unsigned getLoadStoreRegOpcode(unsigned Reg, const TargetRegisterClass *RC, 700fe6060f1SDimitry Andric const TargetRegisterInfo *TRI, 701fe6060f1SDimitry Andric const M68kSubtarget &STI, bool load) { 702fe6060f1SDimitry Andric switch (TRI->getRegSizeInBits(*RC)) { 703fe6060f1SDimitry Andric default: 704fe6060f1SDimitry Andric llvm_unreachable("Unknown spill size"); 705fe6060f1SDimitry Andric case 8: 706fe6060f1SDimitry Andric if (M68k::DR8RegClass.hasSubClassEq(RC)) 707bdd1243dSDimitry Andric return load ? M68k::MOV8dp : M68k::MOV8pd; 708fe6060f1SDimitry Andric if (M68k::CCRCRegClass.hasSubClassEq(RC)) 709fe6060f1SDimitry Andric return load ? M68k::MOV16cp : M68k::MOV16pc; 710fe6060f1SDimitry Andric 711fe6060f1SDimitry Andric llvm_unreachable("Unknown 1-byte regclass"); 712fe6060f1SDimitry Andric case 16: 713fe6060f1SDimitry Andric assert(M68k::XR16RegClass.hasSubClassEq(RC) && "Unknown 2-byte regclass"); 714fe6060f1SDimitry Andric return load ? M68k::MOVM16mp_P : M68k::MOVM16pm_P; 715fe6060f1SDimitry Andric case 32: 716fe6060f1SDimitry Andric assert(M68k::XR32RegClass.hasSubClassEq(RC) && "Unknown 4-byte regclass"); 717fe6060f1SDimitry Andric return load ? M68k::MOVM32mp_P : M68k::MOVM32pm_P; 718fe6060f1SDimitry Andric } 719fe6060f1SDimitry Andric } 720fe6060f1SDimitry Andric 721fe6060f1SDimitry Andric unsigned getStoreRegOpcode(unsigned SrcReg, const TargetRegisterClass *RC, 722fe6060f1SDimitry Andric const TargetRegisterInfo *TRI, 723fe6060f1SDimitry Andric const M68kSubtarget &STI) { 724fe6060f1SDimitry Andric return getLoadStoreRegOpcode(SrcReg, RC, TRI, STI, false); 725fe6060f1SDimitry Andric } 726fe6060f1SDimitry Andric 727fe6060f1SDimitry Andric unsigned getLoadRegOpcode(unsigned DstReg, const TargetRegisterClass *RC, 728fe6060f1SDimitry Andric const TargetRegisterInfo *TRI, 729fe6060f1SDimitry Andric const M68kSubtarget &STI) { 730fe6060f1SDimitry Andric return getLoadStoreRegOpcode(DstReg, RC, TRI, STI, true); 731fe6060f1SDimitry Andric } 732fe6060f1SDimitry Andric } // end anonymous namespace 733fe6060f1SDimitry Andric 734fe6060f1SDimitry Andric bool M68kInstrInfo::getStackSlotRange(const TargetRegisterClass *RC, 735fe6060f1SDimitry Andric unsigned SubIdx, unsigned &Size, 736fe6060f1SDimitry Andric unsigned &Offset, 737fe6060f1SDimitry Andric const MachineFunction &MF) const { 738fe6060f1SDimitry Andric // The slot size must be the maximum size so we can easily use MOVEM.L 739fe6060f1SDimitry Andric Size = 4; 740fe6060f1SDimitry Andric Offset = 0; 741fe6060f1SDimitry Andric return true; 742fe6060f1SDimitry Andric } 743fe6060f1SDimitry Andric 744bdd1243dSDimitry Andric void M68kInstrInfo::storeRegToStackSlot( 745bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, 746bdd1243dSDimitry Andric bool IsKill, int FrameIndex, const TargetRegisterClass *RC, 747bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, Register VReg) const { 748bdd1243dSDimitry Andric const MachineFrameInfo &MFI = MBB.getParent()->getFrameInfo(); 749bdd1243dSDimitry Andric assert(MFI.getObjectSize(FrameIndex) >= TRI->getSpillSize(*RC) && 750bdd1243dSDimitry Andric "Stack slot is too small to store"); 751*5f757f3fSDimitry Andric (void)MFI; 752bdd1243dSDimitry Andric 753fe6060f1SDimitry Andric unsigned Opc = getStoreRegOpcode(SrcReg, RC, TRI, Subtarget); 754fe6060f1SDimitry Andric DebugLoc DL = MBB.findDebugLoc(MI); 755fe6060f1SDimitry Andric // (0,FrameIndex) <- $reg 756fe6060f1SDimitry Andric M68k::addFrameReference(BuildMI(MBB, MI, DL, get(Opc)), FrameIndex) 757fe6060f1SDimitry Andric .addReg(SrcReg, getKillRegState(IsKill)); 758fe6060f1SDimitry Andric } 759fe6060f1SDimitry Andric 760fe6060f1SDimitry Andric void M68kInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 761fe6060f1SDimitry Andric MachineBasicBlock::iterator MI, 762fe6060f1SDimitry Andric Register DstReg, int FrameIndex, 763fe6060f1SDimitry Andric const TargetRegisterClass *RC, 764bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, 765bdd1243dSDimitry Andric Register VReg) const { 766bdd1243dSDimitry Andric const MachineFrameInfo &MFI = MBB.getParent()->getFrameInfo(); 767bdd1243dSDimitry Andric assert(MFI.getObjectSize(FrameIndex) >= TRI->getSpillSize(*RC) && 768bdd1243dSDimitry Andric "Stack slot is too small to load"); 769*5f757f3fSDimitry Andric (void)MFI; 770bdd1243dSDimitry Andric 771fe6060f1SDimitry Andric unsigned Opc = getLoadRegOpcode(DstReg, RC, TRI, Subtarget); 772fe6060f1SDimitry Andric DebugLoc DL = MBB.findDebugLoc(MI); 773fe6060f1SDimitry Andric M68k::addFrameReference(BuildMI(MBB, MI, DL, get(Opc), DstReg), FrameIndex); 774fe6060f1SDimitry Andric } 775fe6060f1SDimitry Andric 776*5f757f3fSDimitry Andric /// Return a virtual register initialized with the global base register 777fe6060f1SDimitry Andric /// value. Output instructions required to initialize the register in the 778fe6060f1SDimitry Andric /// function entry block, if necessary. 779fe6060f1SDimitry Andric /// 780fe6060f1SDimitry Andric /// TODO Move this function to M68kMachineFunctionInfo. 781fe6060f1SDimitry Andric unsigned M68kInstrInfo::getGlobalBaseReg(MachineFunction *MF) const { 782fe6060f1SDimitry Andric M68kMachineFunctionInfo *MxFI = MF->getInfo<M68kMachineFunctionInfo>(); 783fe6060f1SDimitry Andric unsigned GlobalBaseReg = MxFI->getGlobalBaseReg(); 784fe6060f1SDimitry Andric if (GlobalBaseReg != 0) 785fe6060f1SDimitry Andric return GlobalBaseReg; 786fe6060f1SDimitry Andric 787fe6060f1SDimitry Andric // Create the register. The code to initialize it is inserted later, 78806c3fb27SDimitry Andric // by the M68kGlobalBaseReg pass (below). 789fe6060f1SDimitry Andric // 790fe6060f1SDimitry Andric // NOTE 791fe6060f1SDimitry Andric // Normally M68k uses A5 register as global base pointer but this will 792fe6060f1SDimitry Andric // create unnecessary spill if we use less then 4 registers in code; since A5 793fe6060f1SDimitry Andric // is callee-save anyway we could try to allocate caller-save first and if 794fe6060f1SDimitry Andric // lucky get one, otherwise it does not really matter which callee-save to 795fe6060f1SDimitry Andric // use. 796fe6060f1SDimitry Andric MachineRegisterInfo &RegInfo = MF->getRegInfo(); 797fe6060f1SDimitry Andric GlobalBaseReg = RegInfo.createVirtualRegister(&M68k::AR32_NOSPRegClass); 798fe6060f1SDimitry Andric MxFI->setGlobalBaseReg(GlobalBaseReg); 799fe6060f1SDimitry Andric return GlobalBaseReg; 800fe6060f1SDimitry Andric } 801fe6060f1SDimitry Andric 802fe6060f1SDimitry Andric std::pair<unsigned, unsigned> 803fe6060f1SDimitry Andric M68kInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { 804fe6060f1SDimitry Andric return std::make_pair(TF, 0u); 805fe6060f1SDimitry Andric } 806fe6060f1SDimitry Andric 807fe6060f1SDimitry Andric ArrayRef<std::pair<unsigned, const char *>> 808fe6060f1SDimitry Andric M68kInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { 809fe6060f1SDimitry Andric using namespace M68kII; 810fe6060f1SDimitry Andric static const std::pair<unsigned, const char *> TargetFlags[] = { 811fe6060f1SDimitry Andric {MO_ABSOLUTE_ADDRESS, "m68k-absolute"}, 812fe6060f1SDimitry Andric {MO_PC_RELATIVE_ADDRESS, "m68k-pcrel"}, 813fe6060f1SDimitry Andric {MO_GOT, "m68k-got"}, 814fe6060f1SDimitry Andric {MO_GOTOFF, "m68k-gotoff"}, 815fe6060f1SDimitry Andric {MO_GOTPCREL, "m68k-gotpcrel"}, 81606c3fb27SDimitry Andric {MO_PLT, "m68k-plt"}, 81706c3fb27SDimitry Andric {MO_TLSGD, "m68k-tlsgd"}, 81806c3fb27SDimitry Andric {MO_TLSLD, "m68k-tlsld"}, 81906c3fb27SDimitry Andric {MO_TLSLDM, "m68k-tlsldm"}, 82006c3fb27SDimitry Andric {MO_TLSIE, "m68k-tlsie"}, 82106c3fb27SDimitry Andric {MO_TLSLE, "m68k-tlsle"}}; 822bdd1243dSDimitry Andric return ArrayRef(TargetFlags); 823fe6060f1SDimitry Andric } 824fe6060f1SDimitry Andric 82506c3fb27SDimitry Andric #undef DEBUG_TYPE 82606c3fb27SDimitry Andric #define DEBUG_TYPE "m68k-create-global-base-reg" 82706c3fb27SDimitry Andric 82806c3fb27SDimitry Andric #define PASS_NAME "M68k PIC Global Base Reg Initialization" 82906c3fb27SDimitry Andric 830fe6060f1SDimitry Andric namespace { 83106c3fb27SDimitry Andric /// This initializes the PIC global base register 83206c3fb27SDimitry Andric struct M68kGlobalBaseReg : public MachineFunctionPass { 833fe6060f1SDimitry Andric static char ID; 83406c3fb27SDimitry Andric M68kGlobalBaseReg() : MachineFunctionPass(ID) {} 835fe6060f1SDimitry Andric 836fe6060f1SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override { 837fe6060f1SDimitry Andric const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>(); 838fe6060f1SDimitry Andric M68kMachineFunctionInfo *MxFI = MF.getInfo<M68kMachineFunctionInfo>(); 839fe6060f1SDimitry Andric 840fe6060f1SDimitry Andric unsigned GlobalBaseReg = MxFI->getGlobalBaseReg(); 841fe6060f1SDimitry Andric 842fe6060f1SDimitry Andric // If we didn't need a GlobalBaseReg, don't insert code. 843fe6060f1SDimitry Andric if (GlobalBaseReg == 0) 844fe6060f1SDimitry Andric return false; 845fe6060f1SDimitry Andric 846fe6060f1SDimitry Andric // Insert the set of GlobalBaseReg into the first MBB of the function 847fe6060f1SDimitry Andric MachineBasicBlock &FirstMBB = MF.front(); 848fe6060f1SDimitry Andric MachineBasicBlock::iterator MBBI = FirstMBB.begin(); 849fe6060f1SDimitry Andric DebugLoc DL = FirstMBB.findDebugLoc(MBBI); 850fe6060f1SDimitry Andric const M68kInstrInfo *TII = STI.getInstrInfo(); 851fe6060f1SDimitry Andric 852fe6060f1SDimitry Andric // Generate lea (__GLOBAL_OFFSET_TABLE_,%PC), %A5 853fe6060f1SDimitry Andric BuildMI(FirstMBB, MBBI, DL, TII->get(M68k::LEA32q), GlobalBaseReg) 854fe6060f1SDimitry Andric .addExternalSymbol("_GLOBAL_OFFSET_TABLE_", M68kII::MO_GOTPCREL); 855fe6060f1SDimitry Andric 856fe6060f1SDimitry Andric return true; 857fe6060f1SDimitry Andric } 858fe6060f1SDimitry Andric 859fe6060f1SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 860fe6060f1SDimitry Andric AU.setPreservesCFG(); 861fe6060f1SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 862fe6060f1SDimitry Andric } 863fe6060f1SDimitry Andric }; 86406c3fb27SDimitry Andric char M68kGlobalBaseReg::ID = 0; 865fe6060f1SDimitry Andric } // namespace 866fe6060f1SDimitry Andric 86706c3fb27SDimitry Andric INITIALIZE_PASS(M68kGlobalBaseReg, DEBUG_TYPE, PASS_NAME, false, false) 86806c3fb27SDimitry Andric 86906c3fb27SDimitry Andric FunctionPass *llvm::createM68kGlobalBaseRegPass() { 87006c3fb27SDimitry Andric return new M68kGlobalBaseReg(); 87106c3fb27SDimitry Andric } 872