xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/M68k/M68kRegisterInfo.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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.
anchor()43fe6060f1SDimitry Andric void M68kRegisterInfo::anchor() {}
44fe6060f1SDimitry Andric 
M68kRegisterInfo(const M68kSubtarget & ST)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 *
getCalleeSavedRegs(const MachineFunction * MF) const60fe6060f1SDimitry Andric M68kRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
61fe6060f1SDimitry Andric   return CSR_STD_SaveList;
62fe6060f1SDimitry Andric }
63fe6060f1SDimitry Andric 
64fe6060f1SDimitry Andric const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID) const65fe6060f1SDimitry 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 *
getRegsForTailCall(const MachineFunction & MF) const71fe6060f1SDimitry Andric M68kRegisterInfo::getRegsForTailCall(const MachineFunction &MF) const {
72fe6060f1SDimitry Andric   return &M68k::XR32_TCRegClass;
73fe6060f1SDimitry Andric }
74fe6060f1SDimitry Andric 
75fe6060f1SDimitry Andric unsigned
getMatchingMegaReg(unsigned Reg,const TargetRegisterClass * RC) const76fe6060f1SDimitry Andric M68kRegisterInfo::getMatchingMegaReg(unsigned Reg,
77fe6060f1SDimitry Andric                                      const TargetRegisterClass *RC) const {
78*06c3fb27SDimitry Andric   for (MCPhysReg Super : superregs(Reg))
79*06c3fb27SDimitry Andric     if (RC->contains(Super))
80*06c3fb27SDimitry Andric       return Super;
81fe6060f1SDimitry Andric   return 0;
82fe6060f1SDimitry Andric }
83fe6060f1SDimitry Andric 
84fe6060f1SDimitry Andric const TargetRegisterClass *
getMaximalPhysRegClass(unsigned reg,MVT VT) const85fe6060f1SDimitry 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 
getRegisterOrder(unsigned Reg,const TargetRegisterClass & TRC) const106fe6060f1SDimitry 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 
getSpillRegisterOrder(unsigned Reg) const116fe6060f1SDimitry 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 
getReservedRegs(const MachineFunction & MF) const122fe6060f1SDimitry 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     }
132*06c3fb27SDimitry Andric     for (MCPhysReg I : subregs_inclusive(Reg)) {
133*06c3fb27SDimitry 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 
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const165bdd1243dSDimitry 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);
211bdd1243dSDimitry Andric   return false;
212fe6060f1SDimitry Andric }
213fe6060f1SDimitry Andric 
requiresRegisterScavenging(const MachineFunction & MF) const214fe6060f1SDimitry Andric bool M68kRegisterInfo::requiresRegisterScavenging(
215fe6060f1SDimitry Andric     const MachineFunction &MF) const {
216*06c3fb27SDimitry Andric   return false;
217fe6060f1SDimitry Andric }
218fe6060f1SDimitry Andric 
trackLivenessAfterRegAlloc(const MachineFunction & MF) const219fe6060f1SDimitry Andric bool M68kRegisterInfo::trackLivenessAfterRegAlloc(
220fe6060f1SDimitry Andric     const MachineFunction &MF) const {
221fe6060f1SDimitry Andric   return true;
222fe6060f1SDimitry Andric }
223fe6060f1SDimitry Andric 
CantUseSP(const MachineFrameInfo & MFI)224fe6060f1SDimitry Andric static bool CantUseSP(const MachineFrameInfo &MFI) {
225fe6060f1SDimitry Andric   return MFI.hasVarSizedObjects() || MFI.hasOpaqueSPAdjustment();
226fe6060f1SDimitry Andric }
227fe6060f1SDimitry Andric 
hasBasePointer(const MachineFunction & MF) const228fe6060f1SDimitry 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 
canRealignStack(const MachineFunction & MF) const243fe6060f1SDimitry 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 
getFrameRegister(const MachineFunction & MF) const262fe6060f1SDimitry 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 
intRegClass(unsigned size) const267fe6060f1SDimitry Andric const TargetRegisterClass *M68kRegisterInfo::intRegClass(unsigned size) const {
268fe6060f1SDimitry Andric   return &M68k::DR32RegClass;
269fe6060f1SDimitry Andric }
270