1*0fca6ea1SDimitry Andric //===- XtensaRegisterInfo.cpp - Xtensa Register Information ---------------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric // This file contains the Xtensa implementation of the TargetRegisterInfo class. 10*0fca6ea1SDimitry Andric // 11*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 12*0fca6ea1SDimitry Andric 13*0fca6ea1SDimitry Andric #include "XtensaRegisterInfo.h" 14*0fca6ea1SDimitry Andric #include "XtensaInstrInfo.h" 15*0fca6ea1SDimitry Andric #include "XtensaSubtarget.h" 16*0fca6ea1SDimitry Andric #include "XtensaUtils.h" 17*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 18*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 19*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 20*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 21*0fca6ea1SDimitry Andric #include "llvm/Support/Debug.h" 22*0fca6ea1SDimitry Andric #include "llvm/Support/ErrorHandling.h" 23*0fca6ea1SDimitry Andric #include "llvm/Support/raw_ostream.h" 24*0fca6ea1SDimitry Andric 25*0fca6ea1SDimitry Andric #define DEBUG_TYPE "xtensa-reg-info" 26*0fca6ea1SDimitry Andric 27*0fca6ea1SDimitry Andric #define GET_REGINFO_TARGET_DESC 28*0fca6ea1SDimitry Andric #include "XtensaGenRegisterInfo.inc" 29*0fca6ea1SDimitry Andric 30*0fca6ea1SDimitry Andric using namespace llvm; 31*0fca6ea1SDimitry Andric 32*0fca6ea1SDimitry Andric XtensaRegisterInfo::XtensaRegisterInfo(const XtensaSubtarget &STI) 33*0fca6ea1SDimitry Andric : XtensaGenRegisterInfo(Xtensa::A0), Subtarget(STI) {} 34*0fca6ea1SDimitry Andric 35*0fca6ea1SDimitry Andric const uint16_t * 36*0fca6ea1SDimitry Andric XtensaRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 37*0fca6ea1SDimitry Andric return CSR_Xtensa_SaveList; 38*0fca6ea1SDimitry Andric } 39*0fca6ea1SDimitry Andric 40*0fca6ea1SDimitry Andric const uint32_t * 41*0fca6ea1SDimitry Andric XtensaRegisterInfo::getCallPreservedMask(const MachineFunction &MF, 42*0fca6ea1SDimitry Andric CallingConv::ID) const { 43*0fca6ea1SDimitry Andric return CSR_Xtensa_RegMask; 44*0fca6ea1SDimitry Andric } 45*0fca6ea1SDimitry Andric 46*0fca6ea1SDimitry Andric BitVector XtensaRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 47*0fca6ea1SDimitry Andric BitVector Reserved(getNumRegs()); 48*0fca6ea1SDimitry Andric const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); 49*0fca6ea1SDimitry Andric 50*0fca6ea1SDimitry Andric Reserved.set(Xtensa::A0); 51*0fca6ea1SDimitry Andric if (TFI->hasFP(MF)) { 52*0fca6ea1SDimitry Andric // Reserve frame pointer. 53*0fca6ea1SDimitry Andric Reserved.set(getFrameRegister(MF)); 54*0fca6ea1SDimitry Andric } 55*0fca6ea1SDimitry Andric 56*0fca6ea1SDimitry Andric // Reserve stack pointer. 57*0fca6ea1SDimitry Andric Reserved.set(Xtensa::SP); 58*0fca6ea1SDimitry Andric return Reserved; 59*0fca6ea1SDimitry Andric } 60*0fca6ea1SDimitry Andric 61*0fca6ea1SDimitry Andric bool XtensaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 62*0fca6ea1SDimitry Andric int SPAdj, unsigned FIOperandNum, 63*0fca6ea1SDimitry Andric RegScavenger *RS) const { 64*0fca6ea1SDimitry Andric MachineInstr &MI = *II; 65*0fca6ea1SDimitry Andric MachineFunction &MF = *MI.getParent()->getParent(); 66*0fca6ea1SDimitry Andric int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 67*0fca6ea1SDimitry Andric uint64_t StackSize = MF.getFrameInfo().getStackSize(); 68*0fca6ea1SDimitry Andric int64_t SPOffset = MF.getFrameInfo().getObjectOffset(FrameIndex); 69*0fca6ea1SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 70*0fca6ea1SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 71*0fca6ea1SDimitry Andric int MinCSFI = 0; 72*0fca6ea1SDimitry Andric int MaxCSFI = -1; 73*0fca6ea1SDimitry Andric 74*0fca6ea1SDimitry Andric if (CSI.size()) { 75*0fca6ea1SDimitry Andric MinCSFI = CSI[0].getFrameIdx(); 76*0fca6ea1SDimitry Andric MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); 77*0fca6ea1SDimitry Andric } 78*0fca6ea1SDimitry Andric // The following stack frame objects are always referenced relative to $sp: 79*0fca6ea1SDimitry Andric // 1. Outgoing arguments. 80*0fca6ea1SDimitry Andric // 2. Pointer to dynamically allocated stack space. 81*0fca6ea1SDimitry Andric // 3. Locations for callee-saved registers. 82*0fca6ea1SDimitry Andric // 4. Locations for eh data registers. 83*0fca6ea1SDimitry Andric // Everything else is referenced relative to whatever register 84*0fca6ea1SDimitry Andric // getFrameRegister() returns. 85*0fca6ea1SDimitry Andric unsigned FrameReg; 86*0fca6ea1SDimitry Andric if ((FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI)) 87*0fca6ea1SDimitry Andric FrameReg = Xtensa::SP; 88*0fca6ea1SDimitry Andric else 89*0fca6ea1SDimitry Andric FrameReg = getFrameRegister(MF); 90*0fca6ea1SDimitry Andric 91*0fca6ea1SDimitry Andric // Calculate final offset. 92*0fca6ea1SDimitry Andric // - There is no need to change the offset if the frame object is one of the 93*0fca6ea1SDimitry Andric // following: an outgoing argument, pointer to a dynamically allocated 94*0fca6ea1SDimitry Andric // stack space or a $gp restore location, 95*0fca6ea1SDimitry Andric // - If the frame object is any of the following, its offset must be adjusted 96*0fca6ea1SDimitry Andric // by adding the size of the stack: 97*0fca6ea1SDimitry Andric // incoming argument, callee-saved register location or local variable. 98*0fca6ea1SDimitry Andric bool IsKill = false; 99*0fca6ea1SDimitry Andric int64_t Offset = 100*0fca6ea1SDimitry Andric SPOffset + (int64_t)StackSize + MI.getOperand(FIOperandNum + 1).getImm(); 101*0fca6ea1SDimitry Andric 102*0fca6ea1SDimitry Andric bool Valid = isValidAddrOffset(MI, Offset); 103*0fca6ea1SDimitry Andric 104*0fca6ea1SDimitry Andric // If MI is not a debug value, make sure Offset fits in the 16-bit immediate 105*0fca6ea1SDimitry Andric // field. 106*0fca6ea1SDimitry Andric if (!MI.isDebugValue() && !Valid) { 107*0fca6ea1SDimitry Andric MachineBasicBlock &MBB = *MI.getParent(); 108*0fca6ea1SDimitry Andric DebugLoc DL = II->getDebugLoc(); 109*0fca6ea1SDimitry Andric unsigned ADD = Xtensa::ADD; 110*0fca6ea1SDimitry Andric unsigned Reg; 111*0fca6ea1SDimitry Andric const XtensaInstrInfo &TII = *static_cast<const XtensaInstrInfo *>( 112*0fca6ea1SDimitry Andric MBB.getParent()->getSubtarget().getInstrInfo()); 113*0fca6ea1SDimitry Andric 114*0fca6ea1SDimitry Andric TII.loadImmediate(MBB, II, &Reg, Offset); 115*0fca6ea1SDimitry Andric BuildMI(MBB, II, DL, TII.get(ADD), Reg) 116*0fca6ea1SDimitry Andric .addReg(FrameReg) 117*0fca6ea1SDimitry Andric .addReg(Reg, RegState::Kill); 118*0fca6ea1SDimitry Andric 119*0fca6ea1SDimitry Andric FrameReg = Reg; 120*0fca6ea1SDimitry Andric Offset = 0; 121*0fca6ea1SDimitry Andric IsKill = true; 122*0fca6ea1SDimitry Andric } 123*0fca6ea1SDimitry Andric 124*0fca6ea1SDimitry Andric MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false, false, IsKill); 125*0fca6ea1SDimitry Andric MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 126*0fca6ea1SDimitry Andric 127*0fca6ea1SDimitry Andric return false; 128*0fca6ea1SDimitry Andric } 129*0fca6ea1SDimitry Andric 130*0fca6ea1SDimitry Andric Register XtensaRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 131*0fca6ea1SDimitry Andric const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); 132*0fca6ea1SDimitry Andric return TFI->hasFP(MF) ? Xtensa::A15 : Xtensa::SP; 133*0fca6ea1SDimitry Andric } 134