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