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