Implment base support of the TLS functionality using Xtensa THREADPTR Option. Implement basic functionality of the DFPAccel Option(registers support).
139 lines
5.0 KiB
C++
139 lines
5.0 KiB
C++
//===- XtensaRegisterInfo.cpp - Xtensa Register Information ---------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains the Xtensa implementation of the TargetRegisterInfo class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "XtensaRegisterInfo.h"
|
|
#include "MCTargetDesc/XtensaMCTargetDesc.h"
|
|
#include "XtensaInstrInfo.h"
|
|
#include "XtensaSubtarget.h"
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#define DEBUG_TYPE "xtensa-reg-info"
|
|
|
|
#define GET_REGINFO_TARGET_DESC
|
|
#include "XtensaGenRegisterInfo.inc"
|
|
|
|
using namespace llvm;
|
|
|
|
XtensaRegisterInfo::XtensaRegisterInfo(const XtensaSubtarget &STI)
|
|
: XtensaGenRegisterInfo(Xtensa::A0), Subtarget(STI) {}
|
|
|
|
const uint16_t *
|
|
XtensaRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
|
return Subtarget.isWindowedABI() ? CSRW8_Xtensa_SaveList
|
|
: CSR_Xtensa_SaveList;
|
|
}
|
|
|
|
const uint32_t *
|
|
XtensaRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
|
|
CallingConv::ID) const {
|
|
return Subtarget.isWindowedABI() ? CSRW8_Xtensa_RegMask : CSR_Xtensa_RegMask;
|
|
}
|
|
|
|
BitVector XtensaRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
|
BitVector Reserved(getNumRegs());
|
|
const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
|
|
|
|
Reserved.set(Xtensa::A0);
|
|
if (TFI->hasFP(MF)) {
|
|
// Reserve frame pointer.
|
|
Reserved.set(getFrameRegister(MF));
|
|
}
|
|
if (Subtarget.hasTHREADPTR()) {
|
|
// Reserve frame pointer.
|
|
Reserved.set(Xtensa::THREADPTR);
|
|
}
|
|
// Reserve stack pointer.
|
|
Reserved.set(Xtensa::SP);
|
|
return Reserved;
|
|
}
|
|
|
|
bool XtensaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|
int SPAdj, unsigned FIOperandNum,
|
|
RegScavenger *RS) const {
|
|
MachineInstr &MI = *II;
|
|
MachineFunction &MF = *MI.getParent()->getParent();
|
|
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
|
|
uint64_t StackSize = MF.getFrameInfo().getStackSize();
|
|
int64_t SPOffset = MF.getFrameInfo().getObjectOffset(FrameIndex);
|
|
MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
|
|
int MinCSFI = 0;
|
|
int MaxCSFI = -1;
|
|
|
|
if (CSI.size()) {
|
|
MinCSFI = CSI[0].getFrameIdx();
|
|
MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
|
|
}
|
|
// The following stack frame objects are always referenced relative to $sp:
|
|
// 1. Outgoing arguments.
|
|
// 2. Pointer to dynamically allocated stack space.
|
|
// 3. Locations for callee-saved registers.
|
|
// 4. Locations for eh data registers.
|
|
// Everything else is referenced relative to whatever register
|
|
// getFrameRegister() returns.
|
|
MCRegister FrameReg;
|
|
if ((FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI))
|
|
FrameReg = Xtensa::SP;
|
|
else
|
|
FrameReg = getFrameRegister(MF);
|
|
|
|
// Calculate final offset.
|
|
// - There is no need to change the offset if the frame object is one of the
|
|
// following: an outgoing argument, pointer to a dynamically allocated
|
|
// stack space or a $gp restore location,
|
|
// - If the frame object is any of the following, its offset must be adjusted
|
|
// by adding the size of the stack:
|
|
// incoming argument, callee-saved register location or local variable.
|
|
bool IsKill = false;
|
|
int64_t Offset =
|
|
SPOffset + (int64_t)StackSize + MI.getOperand(FIOperandNum + 1).getImm();
|
|
|
|
bool Valid = Xtensa::isValidAddrOffsetForOpcode(MI.getOpcode(), Offset);
|
|
|
|
// If MI is not a debug value, make sure Offset fits in the 16-bit immediate
|
|
// field.
|
|
if (!MI.isDebugValue() && !Valid) {
|
|
MachineBasicBlock &MBB = *MI.getParent();
|
|
DebugLoc DL = II->getDebugLoc();
|
|
unsigned ADD = Xtensa::ADD;
|
|
MCRegister Reg;
|
|
const XtensaInstrInfo &TII = *static_cast<const XtensaInstrInfo *>(
|
|
MBB.getParent()->getSubtarget().getInstrInfo());
|
|
|
|
TII.loadImmediate(MBB, II, &Reg, Offset);
|
|
BuildMI(MBB, II, DL, TII.get(ADD), Reg)
|
|
.addReg(FrameReg)
|
|
.addReg(Reg, RegState::Kill);
|
|
|
|
FrameReg = Reg;
|
|
Offset = 0;
|
|
IsKill = true;
|
|
}
|
|
|
|
MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false, false, IsKill);
|
|
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
|
|
|
|
return false;
|
|
}
|
|
|
|
Register XtensaRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
|
const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
|
|
return TFI->hasFP(MF) ? (Subtarget.isWindowedABI() ? Xtensa::A7 : Xtensa::A15)
|
|
: Xtensa::SP;
|
|
}
|