2021-03-07 16:32:18 -08:00
|
|
|
//===-- M68kRegisterInfo.cpp - CPU0 Register Information -----*- C++ -*--===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
///
|
|
|
|
/// \file
|
|
|
|
/// This file contains the CPU0 implementation of the TargetRegisterInfo class.
|
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "m68k-reg-info"
|
|
|
|
|
|
|
|
#include "M68kRegisterInfo.h"
|
|
|
|
|
|
|
|
#include "M68k.h"
|
|
|
|
#include "M68kMachineFunction.h"
|
|
|
|
#include "M68kSubtarget.h"
|
|
|
|
|
|
|
|
#include "MCTargetDesc/M68kMCTargetDesc.h"
|
|
|
|
|
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
|
|
#include "llvm/IR/Function.h"
|
|
|
|
#include "llvm/IR/Type.h"
|
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
|
|
|
|
#define GET_REGINFO_TARGET_DESC
|
|
|
|
#include "M68kGenRegisterInfo.inc"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
static cl::opt<bool> EnableBasePointer(
|
|
|
|
"m68k-use-base-pointer", cl::Hidden, cl::init(true),
|
|
|
|
cl::desc("Enable use of a base pointer for complex stack frames"));
|
|
|
|
|
|
|
|
// Pin the vtable to this file.
|
|
|
|
void M68kRegisterInfo::anchor() {}
|
|
|
|
|
|
|
|
M68kRegisterInfo::M68kRegisterInfo(const M68kSubtarget &ST)
|
|
|
|
// FIXME x26 not sure it this the correct value, it expects RA, but M68k
|
|
|
|
// passes IP anyway, how this works?
|
|
|
|
: M68kGenRegisterInfo(M68k::A0, 0, 0, M68k::PC), Subtarget(ST) {
|
|
|
|
StackPtr = M68k::SP;
|
|
|
|
FramePtr = M68k::A6;
|
|
|
|
GlobalBasePtr = M68k::A5;
|
|
|
|
BasePtr = M68k::A4;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Callee Saved Registers methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
const MCPhysReg *
|
|
|
|
M68kRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
|
|
|
return CSR_STD_SaveList;
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint32_t *
|
|
|
|
M68kRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
|
|
|
|
CallingConv::ID) const {
|
|
|
|
return CSR_STD_RegMask;
|
|
|
|
}
|
|
|
|
|
|
|
|
const TargetRegisterClass *
|
|
|
|
M68kRegisterInfo::getRegsForTailCall(const MachineFunction &MF) const {
|
|
|
|
return &M68k::XR32_TCRegClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
|
|
|
M68kRegisterInfo::getMatchingMegaReg(unsigned Reg,
|
|
|
|
const TargetRegisterClass *RC) const {
|
|
|
|
for (MCSuperRegIterator Super(Reg, this); Super.isValid(); ++Super)
|
|
|
|
if (RC->contains(*Super))
|
|
|
|
return *Super;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const TargetRegisterClass *
|
|
|
|
M68kRegisterInfo::getMaximalPhysRegClass(unsigned reg, MVT VT) const {
|
|
|
|
assert(Register::isPhysicalRegister(reg) &&
|
|
|
|
"reg must be a physical register");
|
|
|
|
|
|
|
|
// Pick the most sub register class of the right type that contains
|
|
|
|
// this physreg.
|
|
|
|
const TargetRegisterClass *BestRC = nullptr;
|
|
|
|
for (regclass_iterator I = regclass_begin(), E = regclass_end(); I != E;
|
|
|
|
++I) {
|
|
|
|
const TargetRegisterClass *RC = *I;
|
|
|
|
if ((VT == MVT::Other || isTypeLegalForClass(*RC, VT)) &&
|
|
|
|
RC->contains(reg) &&
|
|
|
|
(!BestRC ||
|
|
|
|
(BestRC->hasSubClass(RC) && RC->getNumRegs() > BestRC->getNumRegs())))
|
|
|
|
BestRC = RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(BestRC && "Couldn't find the register class");
|
|
|
|
return BestRC;
|
|
|
|
}
|
|
|
|
|
|
|
|
int M68kRegisterInfo::getRegisterOrder(unsigned Reg,
|
|
|
|
const TargetRegisterClass &TRC) const {
|
|
|
|
for (unsigned i = 0; i < TRC.getNumRegs(); ++i) {
|
|
|
|
if (regsOverlap(Reg, TRC.getRegister(i))) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int M68kRegisterInfo::getSpillRegisterOrder(unsigned Reg) const {
|
|
|
|
int Result = getRegisterOrder(Reg, *getRegClass(M68k::SPILLRegClassID));
|
|
|
|
assert(Result >= 0 && "Can not determine spill order");
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
BitVector M68kRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
|
|
|
const M68kFrameLowering *TFI = getFrameLowering(MF);
|
|
|
|
|
|
|
|
BitVector Reserved(getNumRegs());
|
|
|
|
|
|
|
|
// Set a register's and its sub-registers and aliases as reserved.
|
|
|
|
auto setBitVector = [&Reserved, this](unsigned Reg) {
|
|
|
|
for (MCRegAliasIterator I(Reg, this, /* self */ true); I.isValid(); ++I) {
|
|
|
|
Reserved.set(*I);
|
|
|
|
}
|
|
|
|
for (MCSubRegIterator I(Reg, this, /* self */ true); I.isValid(); ++I) {
|
|
|
|
Reserved.set(*I);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
setBitVector(M68k::PC);
|
|
|
|
setBitVector(M68k::SP);
|
|
|
|
|
|
|
|
if (TFI->hasFP(MF)) {
|
|
|
|
setBitVector(FramePtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the base-pointer register and its aliases as reserved if needed.
|
|
|
|
if (hasBasePointer(MF)) {
|
|
|
|
CallingConv::ID CC = MF.getFunction().getCallingConv();
|
|
|
|
const uint32_t *RegMask = getCallPreservedMask(MF, CC);
|
|
|
|
if (MachineOperand::clobbersPhysReg(RegMask, getBaseRegister()))
|
|
|
|
report_fatal_error("Stack realignment in presence of dynamic allocas is "
|
|
|
|
"not supported with"
|
|
|
|
"this calling convention.");
|
|
|
|
|
|
|
|
setBitVector(getBaseRegister());
|
|
|
|
}
|
|
|
|
|
|
|
|
return Reserved;
|
|
|
|
}
|
|
|
|
|
|
|
|
void M68kRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|
|
|
int SPAdj, unsigned FIOperandNum,
|
|
|
|
RegScavenger *RS) const {
|
|
|
|
MachineInstr &MI = *II;
|
|
|
|
MachineFunction &MF = *MI.getParent()->getParent();
|
|
|
|
const M68kFrameLowering *TFI = getFrameLowering(MF);
|
|
|
|
|
|
|
|
// We have either (i,An,Rn) or (i,An) EA form
|
|
|
|
// NOTE Base contains the FI and we need to backtrace a bit to get Disp
|
|
|
|
MachineOperand &Disp = MI.getOperand(FIOperandNum - 1);
|
|
|
|
MachineOperand &Base = MI.getOperand(FIOperandNum);
|
|
|
|
|
|
|
|
int Imm = (int)(Disp.getImm());
|
|
|
|
int FIndex = (int)(Base.getIndex());
|
|
|
|
|
|
|
|
// FIXME tail call: implement jmp from mem
|
|
|
|
bool AfterFPPop = false;
|
|
|
|
|
|
|
|
unsigned BasePtr;
|
|
|
|
if (hasBasePointer(MF))
|
|
|
|
BasePtr = (FIndex < 0 ? FramePtr : getBaseRegister());
|
2021-03-15 13:01:34 +00:00
|
|
|
else if (hasStackRealignment(MF))
|
2021-03-07 16:32:18 -08:00
|
|
|
BasePtr = (FIndex < 0 ? FramePtr : StackPtr);
|
|
|
|
else if (AfterFPPop)
|
|
|
|
BasePtr = StackPtr;
|
|
|
|
else
|
|
|
|
BasePtr = (TFI->hasFP(MF) ? FramePtr : StackPtr);
|
|
|
|
|
|
|
|
Base.ChangeToRegister(BasePtr, false);
|
|
|
|
|
|
|
|
// Now add the frame object offset to the offset from FP.
|
|
|
|
int64_t FIOffset;
|
|
|
|
Register IgnoredFrameReg;
|
|
|
|
if (AfterFPPop) {
|
|
|
|
// Tail call jmp happens after FP is popped.
|
|
|
|
const MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
|
|
FIOffset = MFI.getObjectOffset(FIndex) - TFI->getOffsetOfLocalArea();
|
|
|
|
} else {
|
|
|
|
FIOffset =
|
|
|
|
TFI->getFrameIndexReference(MF, FIndex, IgnoredFrameReg).getFixed();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (BasePtr == StackPtr)
|
|
|
|
FIOffset += SPAdj;
|
|
|
|
|
|
|
|
Disp.ChangeToImmediate(FIOffset + Imm);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool M68kRegisterInfo::requiresRegisterScavenging(
|
|
|
|
const MachineFunction &MF) const {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool M68kRegisterInfo::trackLivenessAfterRegAlloc(
|
|
|
|
const MachineFunction &MF) const {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool CantUseSP(const MachineFrameInfo &MFI) {
|
|
|
|
return MFI.hasVarSizedObjects() || MFI.hasOpaqueSPAdjustment();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool M68kRegisterInfo::hasBasePointer(const MachineFunction &MF) const {
|
|
|
|
const MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
|
|
|
|
|
|
if (!EnableBasePointer)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// When we need stack realignment, we can't address the stack from the frame
|
|
|
|
// pointer. When we have dynamic allocas or stack-adjusting inline asm, we
|
|
|
|
// can't address variables from the stack pointer. MS inline asm can
|
|
|
|
// reference locals while also adjusting the stack pointer. When we can't
|
|
|
|
// use both the SP and the FP, we need a separate base pointer register.
|
2021-03-15 13:01:34 +00:00
|
|
|
bool CantUseFP = hasStackRealignment(MF);
|
2021-03-07 16:32:18 -08:00
|
|
|
return CantUseFP && CantUseSP(MFI);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool M68kRegisterInfo::canRealignStack(const MachineFunction &MF) const {
|
|
|
|
if (!TargetRegisterInfo::canRealignStack(MF))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
|
|
const MachineRegisterInfo *MRI = &MF.getRegInfo();
|
|
|
|
|
|
|
|
// Stack realignment requires a frame pointer. If we already started
|
|
|
|
// register allocation with frame pointer elimination, it is too late now.
|
|
|
|
if (!MRI->canReserveReg(FramePtr))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// If a base pointer is necessary. Check that it isn't too late to reserve it.
|
|
|
|
if (CantUseSP(MFI))
|
|
|
|
return MRI->canReserveReg(BasePtr);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Register M68kRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
|
|
|
const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
|
|
|
|
return TFI->hasFP(MF) ? FramePtr : StackPtr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const TargetRegisterClass *M68kRegisterInfo::intRegClass(unsigned size) const {
|
|
|
|
return &M68k::DR32RegClass;
|
|
|
|
}
|