1349cc55cSDimitry Andric //===-- CSKYRegisterInfo.h - CSKY Register Information Impl ---*- C++ -*---===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric // 9349cc55cSDimitry Andric // This file contains the CSKY implementation of the TargetRegisterInfo class. 10349cc55cSDimitry Andric // 11349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 12349cc55cSDimitry Andric 13349cc55cSDimitry Andric #include "CSKYRegisterInfo.h" 14349cc55cSDimitry Andric #include "CSKY.h" 15349cc55cSDimitry Andric #include "CSKYSubtarget.h" 16349cc55cSDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 17349cc55cSDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h" 18349cc55cSDimitry Andric #include "llvm/MC/MCContext.h" 19349cc55cSDimitry Andric 20349cc55cSDimitry Andric #define GET_REGINFO_TARGET_DESC 21349cc55cSDimitry Andric #include "CSKYGenRegisterInfo.inc" 22349cc55cSDimitry Andric 23349cc55cSDimitry Andric using namespace llvm; 24349cc55cSDimitry Andric 25349cc55cSDimitry Andric CSKYRegisterInfo::CSKYRegisterInfo() 26349cc55cSDimitry Andric : CSKYGenRegisterInfo(CSKY::R15, 0, 0, 0) {} 27349cc55cSDimitry Andric 28349cc55cSDimitry Andric const uint32_t * 29349cc55cSDimitry Andric CSKYRegisterInfo::getCallPreservedMask(const MachineFunction &MF, 30349cc55cSDimitry Andric CallingConv::ID Id) const { 31349cc55cSDimitry Andric const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>(); 32349cc55cSDimitry Andric return CSR_I32_RegMask; 33349cc55cSDimitry Andric } 34349cc55cSDimitry Andric 35349cc55cSDimitry Andric Register CSKYRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 36349cc55cSDimitry Andric const TargetFrameLowering *TFI = getFrameLowering(MF); 37349cc55cSDimitry Andric return TFI->hasFP(MF) ? CSKY::R8 : CSKY::R14; 38349cc55cSDimitry Andric } 39349cc55cSDimitry Andric 40349cc55cSDimitry Andric BitVector CSKYRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 41349cc55cSDimitry Andric const CSKYFrameLowering *TFI = getFrameLowering(MF); 42349cc55cSDimitry Andric const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>(); 43349cc55cSDimitry Andric BitVector Reserved(getNumRegs()); 44349cc55cSDimitry Andric 45349cc55cSDimitry Andric // Reserve the base register if we need to allocate 46349cc55cSDimitry Andric // variable-sized objects at runtime. 47349cc55cSDimitry Andric if (TFI->hasBP(MF)) 48349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R7); // bp 49349cc55cSDimitry Andric 50349cc55cSDimitry Andric if (TFI->hasFP(MF)) 51349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R8); // fp 52349cc55cSDimitry Andric 53349cc55cSDimitry Andric if (!STI.hasE2()) { 54349cc55cSDimitry Andric for (unsigned i = 0; i < 6; i++) 55349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R8 + i); // R8 - R13 56349cc55cSDimitry Andric } 57349cc55cSDimitry Andric 58349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R14); // sp 59349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R15); // lr 60349cc55cSDimitry Andric 61349cc55cSDimitry Andric if (!STI.hasHighRegisters()) { 62349cc55cSDimitry Andric for (unsigned i = 0; i < 10; i++) 63349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R16 + i); // R16 - R25 64349cc55cSDimitry Andric } 65349cc55cSDimitry Andric 66349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R26); 67349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R27); 68349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R28); // gp 69349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R29); 70349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R30); 71349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R31); // tp 72349cc55cSDimitry Andric 73349cc55cSDimitry Andric assert(checkAllSuperRegsMarked(Reserved)); 74349cc55cSDimitry Andric return Reserved; 75349cc55cSDimitry Andric } 76349cc55cSDimitry Andric 77349cc55cSDimitry Andric const uint32_t *CSKYRegisterInfo::getNoPreservedMask() const { 78349cc55cSDimitry Andric return CSR_NoRegs_RegMask; 79349cc55cSDimitry Andric } 80349cc55cSDimitry Andric 81349cc55cSDimitry Andric const MCPhysReg * 82349cc55cSDimitry Andric CSKYRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 83349cc55cSDimitry Andric const CSKYSubtarget &STI = MF->getSubtarget<CSKYSubtarget>(); 84349cc55cSDimitry Andric if (MF->getFunction().hasFnAttribute("interrupt")) { 85349cc55cSDimitry Andric return CSR_GPR_ISR_SaveList; 86349cc55cSDimitry Andric } 87349cc55cSDimitry Andric 88349cc55cSDimitry Andric return CSR_I32_SaveList; 89349cc55cSDimitry Andric } 90349cc55cSDimitry Andric 91*0eae32dcSDimitry Andric static bool IsLegalOffset(const CSKYInstrInfo *TII, MachineInstr *MI, 92*0eae32dcSDimitry Andric int &Offset) { 93*0eae32dcSDimitry Andric const MCInstrDesc &Desc = MI->getDesc(); 94*0eae32dcSDimitry Andric unsigned AddrMode = (Desc.TSFlags & CSKYII::AddrModeMask); 95*0eae32dcSDimitry Andric unsigned i = 0; 96*0eae32dcSDimitry Andric for (; !MI->getOperand(i).isFI(); ++i) { 97*0eae32dcSDimitry Andric assert(i + 1 < MI->getNumOperands() && 98*0eae32dcSDimitry Andric "Instr doesn't have FrameIndex operand!"); 99*0eae32dcSDimitry Andric } 100*0eae32dcSDimitry Andric 101*0eae32dcSDimitry Andric if (MI->getOpcode() == CSKY::ADDI32) { 102*0eae32dcSDimitry Andric if (!isUInt<12>(std::abs(Offset) - 1)) 103*0eae32dcSDimitry Andric return false; 104*0eae32dcSDimitry Andric if (Offset < 0) { 105*0eae32dcSDimitry Andric MI->setDesc(TII->get(CSKY::SUBI32)); 106*0eae32dcSDimitry Andric Offset = -Offset; 107*0eae32dcSDimitry Andric } 108*0eae32dcSDimitry Andric 109*0eae32dcSDimitry Andric return true; 110*0eae32dcSDimitry Andric } 111*0eae32dcSDimitry Andric 112*0eae32dcSDimitry Andric if (MI->getOpcode() == CSKY::ADDI16XZ) 113*0eae32dcSDimitry Andric return false; 114*0eae32dcSDimitry Andric 115*0eae32dcSDimitry Andric if (Offset < 0) 116*0eae32dcSDimitry Andric return false; 117*0eae32dcSDimitry Andric 118*0eae32dcSDimitry Andric unsigned NumBits = 0; 119*0eae32dcSDimitry Andric unsigned Scale = 1; 120*0eae32dcSDimitry Andric switch (AddrMode) { 121*0eae32dcSDimitry Andric case CSKYII::AddrMode32B: 122*0eae32dcSDimitry Andric Scale = 1; 123*0eae32dcSDimitry Andric NumBits = 12; 124*0eae32dcSDimitry Andric break; 125*0eae32dcSDimitry Andric case CSKYII::AddrMode32H: 126*0eae32dcSDimitry Andric Scale = 2; 127*0eae32dcSDimitry Andric NumBits = 12; 128*0eae32dcSDimitry Andric break; 129*0eae32dcSDimitry Andric case CSKYII::AddrMode32WD: 130*0eae32dcSDimitry Andric Scale = 4; 131*0eae32dcSDimitry Andric NumBits = 12; 132*0eae32dcSDimitry Andric break; 133*0eae32dcSDimitry Andric case CSKYII::AddrMode16B: 134*0eae32dcSDimitry Andric Scale = 1; 135*0eae32dcSDimitry Andric NumBits = 5; 136*0eae32dcSDimitry Andric break; 137*0eae32dcSDimitry Andric case CSKYII::AddrMode16H: 138*0eae32dcSDimitry Andric Scale = 2; 139*0eae32dcSDimitry Andric NumBits = 5; 140*0eae32dcSDimitry Andric break; 141*0eae32dcSDimitry Andric case CSKYII::AddrMode16W: 142*0eae32dcSDimitry Andric Scale = 4; 143*0eae32dcSDimitry Andric NumBits = 5; 144*0eae32dcSDimitry Andric break; 145*0eae32dcSDimitry Andric case CSKYII::AddrMode32SDF: 146*0eae32dcSDimitry Andric Scale = 4; 147*0eae32dcSDimitry Andric NumBits = 8; 148*0eae32dcSDimitry Andric break; 149*0eae32dcSDimitry Andric default: 150*0eae32dcSDimitry Andric llvm_unreachable("Unsupported addressing mode!"); 151*0eae32dcSDimitry Andric } 152*0eae32dcSDimitry Andric 153*0eae32dcSDimitry Andric // Cannot encode offset. 154*0eae32dcSDimitry Andric if ((Offset & (Scale - 1)) != 0) 155*0eae32dcSDimitry Andric return false; 156*0eae32dcSDimitry Andric 157*0eae32dcSDimitry Andric unsigned Mask = (1 << NumBits) - 1; 158*0eae32dcSDimitry Andric if ((unsigned)Offset <= Mask * Scale) 159*0eae32dcSDimitry Andric return true; 160*0eae32dcSDimitry Andric 161*0eae32dcSDimitry Andric // Offset out of range. 162*0eae32dcSDimitry Andric return false; 163*0eae32dcSDimitry Andric } 164*0eae32dcSDimitry Andric 165349cc55cSDimitry Andric void CSKYRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 166349cc55cSDimitry Andric int SPAdj, unsigned FIOperandNum, 167349cc55cSDimitry Andric RegScavenger *RS) const { 168349cc55cSDimitry Andric assert(SPAdj == 0 && "Unexpected non-zero SPAdj value"); 169*0eae32dcSDimitry Andric 170*0eae32dcSDimitry Andric MachineInstr *MI = &*II; 171*0eae32dcSDimitry Andric MachineBasicBlock &MBB = *MI->getParent(); 172*0eae32dcSDimitry Andric MachineFunction &MF = *MI->getParent()->getParent(); 173*0eae32dcSDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 174*0eae32dcSDimitry Andric const CSKYInstrInfo *TII = MF.getSubtarget<CSKYSubtarget>().getInstrInfo(); 175*0eae32dcSDimitry Andric DebugLoc DL = MI->getDebugLoc(); 176*0eae32dcSDimitry Andric const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>(); 177*0eae32dcSDimitry Andric 178*0eae32dcSDimitry Andric switch (MI->getOpcode()) { 179*0eae32dcSDimitry Andric default: 180*0eae32dcSDimitry Andric break; 181*0eae32dcSDimitry Andric case CSKY::RESTORE_CARRY: { 182*0eae32dcSDimitry Andric Register NewReg = STI.hasE2() 183*0eae32dcSDimitry Andric ? MRI.createVirtualRegister(&CSKY::GPRRegClass) 184*0eae32dcSDimitry Andric : MRI.createVirtualRegister(&CSKY::mGPRRegClass); 185*0eae32dcSDimitry Andric 186*0eae32dcSDimitry Andric auto *Temp = BuildMI(MBB, II, DL, TII->get(CSKY::LD32W), NewReg) 187*0eae32dcSDimitry Andric .add(MI->getOperand(1)) 188*0eae32dcSDimitry Andric .add(MI->getOperand(2)) 189*0eae32dcSDimitry Andric .getInstr(); 190*0eae32dcSDimitry Andric 191*0eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(STI.hasE2() ? CSKY::BTSTI32 : CSKY::BTSTI16), 192*0eae32dcSDimitry Andric MI->getOperand(0).getReg()) 193*0eae32dcSDimitry Andric .addReg(NewReg, getKillRegState(true)) 194*0eae32dcSDimitry Andric .addImm(0); 195*0eae32dcSDimitry Andric 196*0eae32dcSDimitry Andric MI = Temp; 197*0eae32dcSDimitry Andric 198*0eae32dcSDimitry Andric MBB.erase(II); 199*0eae32dcSDimitry Andric break; 200*0eae32dcSDimitry Andric } 201*0eae32dcSDimitry Andric case CSKY::SPILL_CARRY: { 202*0eae32dcSDimitry Andric Register NewReg; 203*0eae32dcSDimitry Andric if (STI.hasE2()) { 204*0eae32dcSDimitry Andric NewReg = MRI.createVirtualRegister(&CSKY::GPRRegClass); 205*0eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(CSKY::MVC32), NewReg) 206*0eae32dcSDimitry Andric .add(MI->getOperand(0)); 207*0eae32dcSDimitry Andric } else { 208*0eae32dcSDimitry Andric NewReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass); 209*0eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(CSKY::MOVI16), NewReg).addImm(0); 210*0eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(CSKY::ADDC16)) 211*0eae32dcSDimitry Andric .addReg(NewReg, RegState::Define) 212*0eae32dcSDimitry Andric .addReg(MI->getOperand(0).getReg(), RegState::Define) 213*0eae32dcSDimitry Andric .addReg(NewReg, getKillRegState(true)) 214*0eae32dcSDimitry Andric .addReg(NewReg, getKillRegState(true)) 215*0eae32dcSDimitry Andric .addReg(MI->getOperand(0).getReg()); 216*0eae32dcSDimitry Andric 217*0eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(CSKY::BTSTI16), MI->getOperand(0).getReg()) 218*0eae32dcSDimitry Andric .addReg(NewReg) 219*0eae32dcSDimitry Andric .addImm(0); 220*0eae32dcSDimitry Andric } 221*0eae32dcSDimitry Andric 222*0eae32dcSDimitry Andric MI = BuildMI(MBB, II, DL, TII->get(CSKY::ST32W)) 223*0eae32dcSDimitry Andric .addReg(NewReg, getKillRegState(true)) 224*0eae32dcSDimitry Andric .add(MI->getOperand(1)) 225*0eae32dcSDimitry Andric .add(MI->getOperand(2)) 226*0eae32dcSDimitry Andric .getInstr(); 227*0eae32dcSDimitry Andric 228*0eae32dcSDimitry Andric MBB.erase(II); 229*0eae32dcSDimitry Andric 230*0eae32dcSDimitry Andric break; 231*0eae32dcSDimitry Andric } 232*0eae32dcSDimitry Andric } 233*0eae32dcSDimitry Andric 234*0eae32dcSDimitry Andric int FrameIndex = MI->getOperand(FIOperandNum).getIndex(); 235*0eae32dcSDimitry Andric Register FrameReg; 236*0eae32dcSDimitry Andric int Offset = getFrameLowering(MF) 237*0eae32dcSDimitry Andric ->getFrameIndexReference(MF, FrameIndex, FrameReg) 238*0eae32dcSDimitry Andric .getFixed() + 239*0eae32dcSDimitry Andric MI->getOperand(FIOperandNum + 1).getImm(); 240*0eae32dcSDimitry Andric 241*0eae32dcSDimitry Andric if (!isInt<32>(Offset)) 242*0eae32dcSDimitry Andric report_fatal_error( 243*0eae32dcSDimitry Andric "Frame offsets outside of the signed 32-bit range not supported"); 244*0eae32dcSDimitry Andric 245*0eae32dcSDimitry Andric bool FrameRegIsKill = false; 246*0eae32dcSDimitry Andric MachineBasicBlock::iterator NewII(MI); 247*0eae32dcSDimitry Andric if (!IsLegalOffset(TII, MI, Offset)) { 248*0eae32dcSDimitry Andric assert(isInt<32>(Offset) && "Int32 expected"); 249*0eae32dcSDimitry Andric // The offset won't fit in an immediate, so use a scratch register instead 250*0eae32dcSDimitry Andric // Modify Offset and FrameReg appropriately 251*0eae32dcSDimitry Andric assert(Offset >= 0); 252*0eae32dcSDimitry Andric Register ScratchReg = TII->movImm(MBB, NewII, DL, Offset); 253*0eae32dcSDimitry Andric BuildMI(MBB, NewII, DL, 254*0eae32dcSDimitry Andric TII->get(STI.hasE2() ? CSKY::ADDU32 : CSKY::ADDU16XZ), ScratchReg) 255*0eae32dcSDimitry Andric .addReg(ScratchReg, RegState::Kill) 256*0eae32dcSDimitry Andric .addReg(FrameReg); 257*0eae32dcSDimitry Andric 258*0eae32dcSDimitry Andric Offset = 0; 259*0eae32dcSDimitry Andric FrameReg = ScratchReg; 260*0eae32dcSDimitry Andric FrameRegIsKill = true; 261*0eae32dcSDimitry Andric } 262*0eae32dcSDimitry Andric 263*0eae32dcSDimitry Andric if (Offset == 0 && 264*0eae32dcSDimitry Andric (MI->getOpcode() == CSKY::ADDI32 || MI->getOpcode() == CSKY::ADDI16XZ)) { 265*0eae32dcSDimitry Andric MI->setDesc(TII->get(TargetOpcode::COPY)); 266*0eae32dcSDimitry Andric MI->getOperand(FIOperandNum) 267*0eae32dcSDimitry Andric .ChangeToRegister(FrameReg, false, false, FrameRegIsKill); 268*0eae32dcSDimitry Andric MI->RemoveOperand(FIOperandNum + 1); 269*0eae32dcSDimitry Andric } else { 270*0eae32dcSDimitry Andric MI->getOperand(FIOperandNum) 271*0eae32dcSDimitry Andric .ChangeToRegister(FrameReg, false, false, FrameRegIsKill); 272*0eae32dcSDimitry Andric MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 273*0eae32dcSDimitry Andric } 274349cc55cSDimitry Andric } 275