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