1*fe6060f1SDimitry Andric //===-- M68kRegisterInfo.cpp - CPU0 Register 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 CPU0 implementation of the TargetRegisterInfo class. 11*fe6060f1SDimitry Andric /// 12*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 13*fe6060f1SDimitry Andric 14*fe6060f1SDimitry Andric #include "M68kRegisterInfo.h" 15*fe6060f1SDimitry Andric 16*fe6060f1SDimitry Andric #include "M68k.h" 17*fe6060f1SDimitry Andric #include "M68kMachineFunction.h" 18*fe6060f1SDimitry Andric #include "M68kSubtarget.h" 19*fe6060f1SDimitry Andric 20*fe6060f1SDimitry Andric #include "MCTargetDesc/M68kMCTargetDesc.h" 21*fe6060f1SDimitry Andric 22*fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 23*fe6060f1SDimitry Andric #include "llvm/IR/Function.h" 24*fe6060f1SDimitry Andric #include "llvm/IR/Type.h" 25*fe6060f1SDimitry Andric #include "llvm/Support/CommandLine.h" 26*fe6060f1SDimitry Andric #include "llvm/Support/Debug.h" 27*fe6060f1SDimitry Andric #include "llvm/Support/ErrorHandling.h" 28*fe6060f1SDimitry Andric #include "llvm/Support/raw_ostream.h" 29*fe6060f1SDimitry Andric 30*fe6060f1SDimitry Andric #define GET_REGINFO_TARGET_DESC 31*fe6060f1SDimitry Andric #include "M68kGenRegisterInfo.inc" 32*fe6060f1SDimitry Andric 33*fe6060f1SDimitry Andric #define DEBUG_TYPE "m68k-reg-info" 34*fe6060f1SDimitry Andric 35*fe6060f1SDimitry Andric using namespace llvm; 36*fe6060f1SDimitry Andric 37*fe6060f1SDimitry Andric static cl::opt<bool> EnableBasePointer( 38*fe6060f1SDimitry Andric "m68k-use-base-pointer", cl::Hidden, cl::init(true), 39*fe6060f1SDimitry Andric cl::desc("Enable use of a base pointer for complex stack frames")); 40*fe6060f1SDimitry Andric 41*fe6060f1SDimitry Andric // Pin the vtable to this file. 42*fe6060f1SDimitry Andric void M68kRegisterInfo::anchor() {} 43*fe6060f1SDimitry Andric 44*fe6060f1SDimitry Andric M68kRegisterInfo::M68kRegisterInfo(const M68kSubtarget &ST) 45*fe6060f1SDimitry Andric // FIXME x26 not sure it this the correct value, it expects RA, but M68k 46*fe6060f1SDimitry Andric // passes IP anyway, how this works? 47*fe6060f1SDimitry Andric : M68kGenRegisterInfo(M68k::A0, 0, 0, M68k::PC), Subtarget(ST) { 48*fe6060f1SDimitry Andric StackPtr = M68k::SP; 49*fe6060f1SDimitry Andric FramePtr = M68k::A6; 50*fe6060f1SDimitry Andric GlobalBasePtr = M68k::A5; 51*fe6060f1SDimitry Andric BasePtr = M68k::A4; 52*fe6060f1SDimitry Andric } 53*fe6060f1SDimitry Andric 54*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 55*fe6060f1SDimitry Andric // Callee Saved Registers methods 56*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 57*fe6060f1SDimitry Andric 58*fe6060f1SDimitry Andric const MCPhysReg * 59*fe6060f1SDimitry Andric M68kRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 60*fe6060f1SDimitry Andric return CSR_STD_SaveList; 61*fe6060f1SDimitry Andric } 62*fe6060f1SDimitry Andric 63*fe6060f1SDimitry Andric const uint32_t * 64*fe6060f1SDimitry Andric M68kRegisterInfo::getCallPreservedMask(const MachineFunction &MF, 65*fe6060f1SDimitry Andric CallingConv::ID) const { 66*fe6060f1SDimitry Andric return CSR_STD_RegMask; 67*fe6060f1SDimitry Andric } 68*fe6060f1SDimitry Andric 69*fe6060f1SDimitry Andric const TargetRegisterClass * 70*fe6060f1SDimitry Andric M68kRegisterInfo::getRegsForTailCall(const MachineFunction &MF) const { 71*fe6060f1SDimitry Andric return &M68k::XR32_TCRegClass; 72*fe6060f1SDimitry Andric } 73*fe6060f1SDimitry Andric 74*fe6060f1SDimitry Andric unsigned 75*fe6060f1SDimitry Andric M68kRegisterInfo::getMatchingMegaReg(unsigned Reg, 76*fe6060f1SDimitry Andric const TargetRegisterClass *RC) const { 77*fe6060f1SDimitry Andric for (MCSuperRegIterator Super(Reg, this); Super.isValid(); ++Super) 78*fe6060f1SDimitry Andric if (RC->contains(*Super)) 79*fe6060f1SDimitry Andric return *Super; 80*fe6060f1SDimitry Andric return 0; 81*fe6060f1SDimitry Andric } 82*fe6060f1SDimitry Andric 83*fe6060f1SDimitry Andric const TargetRegisterClass * 84*fe6060f1SDimitry Andric M68kRegisterInfo::getMaximalPhysRegClass(unsigned reg, MVT VT) const { 85*fe6060f1SDimitry Andric assert(Register::isPhysicalRegister(reg) && 86*fe6060f1SDimitry Andric "reg must be a physical register"); 87*fe6060f1SDimitry Andric 88*fe6060f1SDimitry Andric // Pick the most sub register class of the right type that contains 89*fe6060f1SDimitry Andric // this physreg. 90*fe6060f1SDimitry Andric const TargetRegisterClass *BestRC = nullptr; 91*fe6060f1SDimitry Andric for (regclass_iterator I = regclass_begin(), E = regclass_end(); I != E; 92*fe6060f1SDimitry Andric ++I) { 93*fe6060f1SDimitry Andric const TargetRegisterClass *RC = *I; 94*fe6060f1SDimitry Andric if ((VT == MVT::Other || isTypeLegalForClass(*RC, VT)) && 95*fe6060f1SDimitry Andric RC->contains(reg) && 96*fe6060f1SDimitry Andric (!BestRC || 97*fe6060f1SDimitry Andric (BestRC->hasSubClass(RC) && RC->getNumRegs() > BestRC->getNumRegs()))) 98*fe6060f1SDimitry Andric BestRC = RC; 99*fe6060f1SDimitry Andric } 100*fe6060f1SDimitry Andric 101*fe6060f1SDimitry Andric assert(BestRC && "Couldn't find the register class"); 102*fe6060f1SDimitry Andric return BestRC; 103*fe6060f1SDimitry Andric } 104*fe6060f1SDimitry Andric 105*fe6060f1SDimitry Andric int M68kRegisterInfo::getRegisterOrder(unsigned Reg, 106*fe6060f1SDimitry Andric const TargetRegisterClass &TRC) const { 107*fe6060f1SDimitry Andric for (unsigned i = 0; i < TRC.getNumRegs(); ++i) { 108*fe6060f1SDimitry Andric if (regsOverlap(Reg, TRC.getRegister(i))) { 109*fe6060f1SDimitry Andric return i; 110*fe6060f1SDimitry Andric } 111*fe6060f1SDimitry Andric } 112*fe6060f1SDimitry Andric return -1; 113*fe6060f1SDimitry Andric } 114*fe6060f1SDimitry Andric 115*fe6060f1SDimitry Andric int M68kRegisterInfo::getSpillRegisterOrder(unsigned Reg) const { 116*fe6060f1SDimitry Andric int Result = getRegisterOrder(Reg, *getRegClass(M68k::SPILLRegClassID)); 117*fe6060f1SDimitry Andric assert(Result >= 0 && "Can not determine spill order"); 118*fe6060f1SDimitry Andric return Result; 119*fe6060f1SDimitry Andric } 120*fe6060f1SDimitry Andric 121*fe6060f1SDimitry Andric BitVector M68kRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 122*fe6060f1SDimitry Andric const M68kFrameLowering *TFI = getFrameLowering(MF); 123*fe6060f1SDimitry Andric 124*fe6060f1SDimitry Andric BitVector Reserved(getNumRegs()); 125*fe6060f1SDimitry Andric 126*fe6060f1SDimitry Andric // Set a register's and its sub-registers and aliases as reserved. 127*fe6060f1SDimitry Andric auto setBitVector = [&Reserved, this](unsigned Reg) { 128*fe6060f1SDimitry Andric for (MCRegAliasIterator I(Reg, this, /* self */ true); I.isValid(); ++I) { 129*fe6060f1SDimitry Andric Reserved.set(*I); 130*fe6060f1SDimitry Andric } 131*fe6060f1SDimitry Andric for (MCSubRegIterator I(Reg, this, /* self */ true); I.isValid(); ++I) { 132*fe6060f1SDimitry Andric Reserved.set(*I); 133*fe6060f1SDimitry Andric } 134*fe6060f1SDimitry Andric }; 135*fe6060f1SDimitry Andric 136*fe6060f1SDimitry Andric // Registers reserved by users 137*fe6060f1SDimitry Andric for (size_t Reg = 0, Total = getNumRegs(); Reg != Total; ++Reg) { 138*fe6060f1SDimitry Andric if (MF.getSubtarget<M68kSubtarget>().isRegisterReservedByUser(Reg)) 139*fe6060f1SDimitry Andric setBitVector(Reg); 140*fe6060f1SDimitry Andric } 141*fe6060f1SDimitry Andric 142*fe6060f1SDimitry Andric setBitVector(M68k::PC); 143*fe6060f1SDimitry Andric setBitVector(M68k::SP); 144*fe6060f1SDimitry Andric 145*fe6060f1SDimitry Andric if (TFI->hasFP(MF)) { 146*fe6060f1SDimitry Andric setBitVector(FramePtr); 147*fe6060f1SDimitry Andric } 148*fe6060f1SDimitry Andric 149*fe6060f1SDimitry Andric // Set the base-pointer register and its aliases as reserved if needed. 150*fe6060f1SDimitry Andric if (hasBasePointer(MF)) { 151*fe6060f1SDimitry Andric CallingConv::ID CC = MF.getFunction().getCallingConv(); 152*fe6060f1SDimitry Andric const uint32_t *RegMask = getCallPreservedMask(MF, CC); 153*fe6060f1SDimitry Andric if (MachineOperand::clobbersPhysReg(RegMask, getBaseRegister())) 154*fe6060f1SDimitry Andric report_fatal_error("Stack realignment in presence of dynamic allocas is " 155*fe6060f1SDimitry Andric "not supported with" 156*fe6060f1SDimitry Andric "this calling convention."); 157*fe6060f1SDimitry Andric 158*fe6060f1SDimitry Andric setBitVector(getBaseRegister()); 159*fe6060f1SDimitry Andric } 160*fe6060f1SDimitry Andric 161*fe6060f1SDimitry Andric return Reserved; 162*fe6060f1SDimitry Andric } 163*fe6060f1SDimitry Andric 164*fe6060f1SDimitry Andric void M68kRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 165*fe6060f1SDimitry Andric int SPAdj, unsigned FIOperandNum, 166*fe6060f1SDimitry Andric RegScavenger *RS) const { 167*fe6060f1SDimitry Andric MachineInstr &MI = *II; 168*fe6060f1SDimitry Andric MachineFunction &MF = *MI.getParent()->getParent(); 169*fe6060f1SDimitry Andric const M68kFrameLowering *TFI = getFrameLowering(MF); 170*fe6060f1SDimitry Andric 171*fe6060f1SDimitry Andric // We have either (i,An,Rn) or (i,An) EA form 172*fe6060f1SDimitry Andric // NOTE Base contains the FI and we need to backtrace a bit to get Disp 173*fe6060f1SDimitry Andric MachineOperand &Disp = MI.getOperand(FIOperandNum - 1); 174*fe6060f1SDimitry Andric MachineOperand &Base = MI.getOperand(FIOperandNum); 175*fe6060f1SDimitry Andric 176*fe6060f1SDimitry Andric int Imm = (int)(Disp.getImm()); 177*fe6060f1SDimitry Andric int FIndex = (int)(Base.getIndex()); 178*fe6060f1SDimitry Andric 179*fe6060f1SDimitry Andric // FIXME tail call: implement jmp from mem 180*fe6060f1SDimitry Andric bool AfterFPPop = false; 181*fe6060f1SDimitry Andric 182*fe6060f1SDimitry Andric unsigned BasePtr; 183*fe6060f1SDimitry Andric if (hasBasePointer(MF)) 184*fe6060f1SDimitry Andric BasePtr = (FIndex < 0 ? FramePtr : getBaseRegister()); 185*fe6060f1SDimitry Andric else if (hasStackRealignment(MF)) 186*fe6060f1SDimitry Andric BasePtr = (FIndex < 0 ? FramePtr : StackPtr); 187*fe6060f1SDimitry Andric else if (AfterFPPop) 188*fe6060f1SDimitry Andric BasePtr = StackPtr; 189*fe6060f1SDimitry Andric else 190*fe6060f1SDimitry Andric BasePtr = (TFI->hasFP(MF) ? FramePtr : StackPtr); 191*fe6060f1SDimitry Andric 192*fe6060f1SDimitry Andric Base.ChangeToRegister(BasePtr, false); 193*fe6060f1SDimitry Andric 194*fe6060f1SDimitry Andric // Now add the frame object offset to the offset from FP. 195*fe6060f1SDimitry Andric int64_t FIOffset; 196*fe6060f1SDimitry Andric Register IgnoredFrameReg; 197*fe6060f1SDimitry Andric if (AfterFPPop) { 198*fe6060f1SDimitry Andric // Tail call jmp happens after FP is popped. 199*fe6060f1SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 200*fe6060f1SDimitry Andric FIOffset = MFI.getObjectOffset(FIndex) - TFI->getOffsetOfLocalArea(); 201*fe6060f1SDimitry Andric } else { 202*fe6060f1SDimitry Andric FIOffset = 203*fe6060f1SDimitry Andric TFI->getFrameIndexReference(MF, FIndex, IgnoredFrameReg).getFixed(); 204*fe6060f1SDimitry Andric } 205*fe6060f1SDimitry Andric 206*fe6060f1SDimitry Andric if (BasePtr == StackPtr) 207*fe6060f1SDimitry Andric FIOffset += SPAdj; 208*fe6060f1SDimitry Andric 209*fe6060f1SDimitry Andric Disp.ChangeToImmediate(FIOffset + Imm); 210*fe6060f1SDimitry Andric } 211*fe6060f1SDimitry Andric 212*fe6060f1SDimitry Andric bool M68kRegisterInfo::requiresRegisterScavenging( 213*fe6060f1SDimitry Andric const MachineFunction &MF) const { 214*fe6060f1SDimitry Andric return true; 215*fe6060f1SDimitry Andric } 216*fe6060f1SDimitry Andric 217*fe6060f1SDimitry Andric bool M68kRegisterInfo::trackLivenessAfterRegAlloc( 218*fe6060f1SDimitry Andric const MachineFunction &MF) const { 219*fe6060f1SDimitry Andric return true; 220*fe6060f1SDimitry Andric } 221*fe6060f1SDimitry Andric 222*fe6060f1SDimitry Andric static bool CantUseSP(const MachineFrameInfo &MFI) { 223*fe6060f1SDimitry Andric return MFI.hasVarSizedObjects() || MFI.hasOpaqueSPAdjustment(); 224*fe6060f1SDimitry Andric } 225*fe6060f1SDimitry Andric 226*fe6060f1SDimitry Andric bool M68kRegisterInfo::hasBasePointer(const MachineFunction &MF) const { 227*fe6060f1SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 228*fe6060f1SDimitry Andric 229*fe6060f1SDimitry Andric if (!EnableBasePointer) 230*fe6060f1SDimitry Andric return false; 231*fe6060f1SDimitry Andric 232*fe6060f1SDimitry Andric // When we need stack realignment, we can't address the stack from the frame 233*fe6060f1SDimitry Andric // pointer. When we have dynamic allocas or stack-adjusting inline asm, we 234*fe6060f1SDimitry Andric // can't address variables from the stack pointer. MS inline asm can 235*fe6060f1SDimitry Andric // reference locals while also adjusting the stack pointer. When we can't 236*fe6060f1SDimitry Andric // use both the SP and the FP, we need a separate base pointer register. 237*fe6060f1SDimitry Andric bool CantUseFP = hasStackRealignment(MF); 238*fe6060f1SDimitry Andric return CantUseFP && CantUseSP(MFI); 239*fe6060f1SDimitry Andric } 240*fe6060f1SDimitry Andric 241*fe6060f1SDimitry Andric bool M68kRegisterInfo::canRealignStack(const MachineFunction &MF) const { 242*fe6060f1SDimitry Andric if (!TargetRegisterInfo::canRealignStack(MF)) 243*fe6060f1SDimitry Andric return false; 244*fe6060f1SDimitry Andric 245*fe6060f1SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 246*fe6060f1SDimitry Andric const MachineRegisterInfo *MRI = &MF.getRegInfo(); 247*fe6060f1SDimitry Andric 248*fe6060f1SDimitry Andric // Stack realignment requires a frame pointer. If we already started 249*fe6060f1SDimitry Andric // register allocation with frame pointer elimination, it is too late now. 250*fe6060f1SDimitry Andric if (!MRI->canReserveReg(FramePtr)) 251*fe6060f1SDimitry Andric return false; 252*fe6060f1SDimitry Andric 253*fe6060f1SDimitry Andric // If a base pointer is necessary. Check that it isn't too late to reserve it. 254*fe6060f1SDimitry Andric if (CantUseSP(MFI)) 255*fe6060f1SDimitry Andric return MRI->canReserveReg(BasePtr); 256*fe6060f1SDimitry Andric 257*fe6060f1SDimitry Andric return true; 258*fe6060f1SDimitry Andric } 259*fe6060f1SDimitry Andric 260*fe6060f1SDimitry Andric Register M68kRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 261*fe6060f1SDimitry Andric const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); 262*fe6060f1SDimitry Andric return TFI->hasFP(MF) ? FramePtr : StackPtr; 263*fe6060f1SDimitry Andric } 264*fe6060f1SDimitry Andric 265*fe6060f1SDimitry Andric const TargetRegisterClass *M68kRegisterInfo::intRegClass(unsigned size) const { 266*fe6060f1SDimitry Andric return &M68k::DR32RegClass; 267*fe6060f1SDimitry Andric } 268