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