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