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" 16*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 17349cc55cSDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 18349cc55cSDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h" 19349cc55cSDimitry Andric #include "llvm/MC/MCContext.h" 20349cc55cSDimitry Andric 21349cc55cSDimitry Andric #define GET_REGINFO_TARGET_DESC 22349cc55cSDimitry Andric #include "CSKYGenRegisterInfo.inc" 23349cc55cSDimitry Andric 24349cc55cSDimitry Andric using namespace llvm; 25349cc55cSDimitry Andric 26349cc55cSDimitry Andric CSKYRegisterInfo::CSKYRegisterInfo() 27349cc55cSDimitry Andric : CSKYGenRegisterInfo(CSKY::R15, 0, 0, 0) {} 28349cc55cSDimitry Andric 29349cc55cSDimitry Andric const uint32_t * 30349cc55cSDimitry Andric CSKYRegisterInfo::getCallPreservedMask(const MachineFunction &MF, 31349cc55cSDimitry Andric CallingConv::ID Id) const { 32349cc55cSDimitry Andric const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>(); 33*81ad6265SDimitry Andric if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat()) 34*81ad6265SDimitry Andric return CSR_GPR_FPR64_RegMask; 35*81ad6265SDimitry Andric if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat()) 36*81ad6265SDimitry Andric return CSR_GPR_FPR32_RegMask; 37349cc55cSDimitry Andric return CSR_I32_RegMask; 38349cc55cSDimitry Andric } 39349cc55cSDimitry Andric 40349cc55cSDimitry Andric Register CSKYRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 41349cc55cSDimitry Andric const TargetFrameLowering *TFI = getFrameLowering(MF); 42349cc55cSDimitry Andric return TFI->hasFP(MF) ? CSKY::R8 : CSKY::R14; 43349cc55cSDimitry Andric } 44349cc55cSDimitry Andric 45349cc55cSDimitry Andric BitVector CSKYRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 46349cc55cSDimitry Andric const CSKYFrameLowering *TFI = getFrameLowering(MF); 47349cc55cSDimitry Andric const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>(); 48349cc55cSDimitry Andric BitVector Reserved(getNumRegs()); 49349cc55cSDimitry Andric 50349cc55cSDimitry Andric // Reserve the base register if we need to allocate 51349cc55cSDimitry Andric // variable-sized objects at runtime. 52349cc55cSDimitry Andric if (TFI->hasBP(MF)) 53349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R7); // bp 54349cc55cSDimitry Andric 55349cc55cSDimitry Andric if (TFI->hasFP(MF)) 56349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R8); // fp 57349cc55cSDimitry Andric 58349cc55cSDimitry Andric if (!STI.hasE2()) { 59349cc55cSDimitry Andric for (unsigned i = 0; i < 6; i++) 60349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R8 + i); // R8 - R13 61349cc55cSDimitry Andric } 62349cc55cSDimitry Andric 63349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R14); // sp 64349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R15); // lr 65349cc55cSDimitry Andric 66349cc55cSDimitry Andric if (!STI.hasHighRegisters()) { 67349cc55cSDimitry Andric for (unsigned i = 0; i < 10; i++) 68349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R16 + i); // R16 - R25 69349cc55cSDimitry Andric } 70349cc55cSDimitry Andric 71349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R26); 72349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R27); 73349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R28); // gp 74349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R29); 75349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R30); 76349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R31); // tp 77349cc55cSDimitry Andric 78349cc55cSDimitry Andric assert(checkAllSuperRegsMarked(Reserved)); 79349cc55cSDimitry Andric return Reserved; 80349cc55cSDimitry Andric } 81349cc55cSDimitry Andric 82349cc55cSDimitry Andric const uint32_t *CSKYRegisterInfo::getNoPreservedMask() const { 83349cc55cSDimitry Andric return CSR_NoRegs_RegMask; 84349cc55cSDimitry Andric } 85349cc55cSDimitry Andric 86349cc55cSDimitry Andric const MCPhysReg * 87349cc55cSDimitry Andric CSKYRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 88349cc55cSDimitry Andric const CSKYSubtarget &STI = MF->getSubtarget<CSKYSubtarget>(); 89349cc55cSDimitry Andric if (MF->getFunction().hasFnAttribute("interrupt")) { 90*81ad6265SDimitry Andric if (STI.hasFPUv3DoubleFloat()) 91*81ad6265SDimitry Andric return CSR_GPR_FPR64v3_ISR_SaveList; 92*81ad6265SDimitry Andric if (STI.hasFPUv3SingleFloat()) 93*81ad6265SDimitry Andric return CSR_GPR_FPR32v3_ISR_SaveList; 94*81ad6265SDimitry Andric if (STI.hasFPUv2DoubleFloat()) 95*81ad6265SDimitry Andric return CSR_GPR_FPR64_ISR_SaveList; 96*81ad6265SDimitry Andric if (STI.hasFPUv2SingleFloat()) 97*81ad6265SDimitry Andric return CSR_GPR_FPR32_ISR_SaveList; 98349cc55cSDimitry Andric return CSR_GPR_ISR_SaveList; 99349cc55cSDimitry Andric } 100349cc55cSDimitry Andric 101*81ad6265SDimitry Andric if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat()) 102*81ad6265SDimitry Andric return CSR_GPR_FPR64_SaveList; 103*81ad6265SDimitry Andric if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat()) 104*81ad6265SDimitry Andric return CSR_GPR_FPR32_SaveList; 105349cc55cSDimitry Andric return CSR_I32_SaveList; 106349cc55cSDimitry Andric } 107349cc55cSDimitry Andric 1080eae32dcSDimitry Andric static bool IsLegalOffset(const CSKYInstrInfo *TII, MachineInstr *MI, 1090eae32dcSDimitry Andric int &Offset) { 1100eae32dcSDimitry Andric const MCInstrDesc &Desc = MI->getDesc(); 1110eae32dcSDimitry Andric unsigned AddrMode = (Desc.TSFlags & CSKYII::AddrModeMask); 1120eae32dcSDimitry Andric unsigned i = 0; 1130eae32dcSDimitry Andric for (; !MI->getOperand(i).isFI(); ++i) { 1140eae32dcSDimitry Andric assert(i + 1 < MI->getNumOperands() && 1150eae32dcSDimitry Andric "Instr doesn't have FrameIndex operand!"); 1160eae32dcSDimitry Andric } 1170eae32dcSDimitry Andric 1180eae32dcSDimitry Andric if (MI->getOpcode() == CSKY::ADDI32) { 1190eae32dcSDimitry Andric if (!isUInt<12>(std::abs(Offset) - 1)) 1200eae32dcSDimitry Andric return false; 1210eae32dcSDimitry Andric if (Offset < 0) { 1220eae32dcSDimitry Andric MI->setDesc(TII->get(CSKY::SUBI32)); 1230eae32dcSDimitry Andric Offset = -Offset; 1240eae32dcSDimitry Andric } 1250eae32dcSDimitry Andric 1260eae32dcSDimitry Andric return true; 1270eae32dcSDimitry Andric } 1280eae32dcSDimitry Andric 1290eae32dcSDimitry Andric if (MI->getOpcode() == CSKY::ADDI16XZ) 1300eae32dcSDimitry Andric return false; 1310eae32dcSDimitry Andric 1320eae32dcSDimitry Andric if (Offset < 0) 1330eae32dcSDimitry Andric return false; 1340eae32dcSDimitry Andric 1350eae32dcSDimitry Andric unsigned NumBits = 0; 1360eae32dcSDimitry Andric unsigned Scale = 1; 1370eae32dcSDimitry Andric switch (AddrMode) { 1380eae32dcSDimitry Andric case CSKYII::AddrMode32B: 1390eae32dcSDimitry Andric Scale = 1; 1400eae32dcSDimitry Andric NumBits = 12; 1410eae32dcSDimitry Andric break; 1420eae32dcSDimitry Andric case CSKYII::AddrMode32H: 1430eae32dcSDimitry Andric Scale = 2; 1440eae32dcSDimitry Andric NumBits = 12; 1450eae32dcSDimitry Andric break; 1460eae32dcSDimitry Andric case CSKYII::AddrMode32WD: 1470eae32dcSDimitry Andric Scale = 4; 1480eae32dcSDimitry Andric NumBits = 12; 1490eae32dcSDimitry Andric break; 1500eae32dcSDimitry Andric case CSKYII::AddrMode16B: 1510eae32dcSDimitry Andric Scale = 1; 1520eae32dcSDimitry Andric NumBits = 5; 1530eae32dcSDimitry Andric break; 1540eae32dcSDimitry Andric case CSKYII::AddrMode16H: 1550eae32dcSDimitry Andric Scale = 2; 1560eae32dcSDimitry Andric NumBits = 5; 1570eae32dcSDimitry Andric break; 1580eae32dcSDimitry Andric case CSKYII::AddrMode16W: 1590eae32dcSDimitry Andric Scale = 4; 1600eae32dcSDimitry Andric NumBits = 5; 1610eae32dcSDimitry Andric break; 1620eae32dcSDimitry Andric case CSKYII::AddrMode32SDF: 1630eae32dcSDimitry Andric Scale = 4; 1640eae32dcSDimitry Andric NumBits = 8; 1650eae32dcSDimitry Andric break; 1660eae32dcSDimitry Andric default: 1670eae32dcSDimitry Andric llvm_unreachable("Unsupported addressing mode!"); 1680eae32dcSDimitry Andric } 1690eae32dcSDimitry Andric 1700eae32dcSDimitry Andric // Cannot encode offset. 1710eae32dcSDimitry Andric if ((Offset & (Scale - 1)) != 0) 1720eae32dcSDimitry Andric return false; 1730eae32dcSDimitry Andric 1740eae32dcSDimitry Andric unsigned Mask = (1 << NumBits) - 1; 1750eae32dcSDimitry Andric if ((unsigned)Offset <= Mask * Scale) 1760eae32dcSDimitry Andric return true; 1770eae32dcSDimitry Andric 1780eae32dcSDimitry Andric // Offset out of range. 1790eae32dcSDimitry Andric return false; 1800eae32dcSDimitry Andric } 1810eae32dcSDimitry Andric 182349cc55cSDimitry Andric void CSKYRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 183349cc55cSDimitry Andric int SPAdj, unsigned FIOperandNum, 184349cc55cSDimitry Andric RegScavenger *RS) const { 185349cc55cSDimitry Andric assert(SPAdj == 0 && "Unexpected non-zero SPAdj value"); 1860eae32dcSDimitry Andric 1870eae32dcSDimitry Andric MachineInstr *MI = &*II; 1880eae32dcSDimitry Andric MachineBasicBlock &MBB = *MI->getParent(); 1890eae32dcSDimitry Andric MachineFunction &MF = *MI->getParent()->getParent(); 1900eae32dcSDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 1910eae32dcSDimitry Andric const CSKYInstrInfo *TII = MF.getSubtarget<CSKYSubtarget>().getInstrInfo(); 1920eae32dcSDimitry Andric DebugLoc DL = MI->getDebugLoc(); 1930eae32dcSDimitry Andric const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>(); 1940eae32dcSDimitry Andric 1950eae32dcSDimitry Andric switch (MI->getOpcode()) { 1960eae32dcSDimitry Andric default: 1970eae32dcSDimitry Andric break; 1980eae32dcSDimitry Andric case CSKY::RESTORE_CARRY: { 1990eae32dcSDimitry Andric Register NewReg = STI.hasE2() 2000eae32dcSDimitry Andric ? MRI.createVirtualRegister(&CSKY::GPRRegClass) 2010eae32dcSDimitry Andric : MRI.createVirtualRegister(&CSKY::mGPRRegClass); 2020eae32dcSDimitry Andric 2030eae32dcSDimitry Andric auto *Temp = BuildMI(MBB, II, DL, TII->get(CSKY::LD32W), NewReg) 2040eae32dcSDimitry Andric .add(MI->getOperand(1)) 2050eae32dcSDimitry Andric .add(MI->getOperand(2)) 2060eae32dcSDimitry Andric .getInstr(); 2070eae32dcSDimitry Andric 2080eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(STI.hasE2() ? CSKY::BTSTI32 : CSKY::BTSTI16), 2090eae32dcSDimitry Andric MI->getOperand(0).getReg()) 2100eae32dcSDimitry Andric .addReg(NewReg, getKillRegState(true)) 2110eae32dcSDimitry Andric .addImm(0); 2120eae32dcSDimitry Andric 2130eae32dcSDimitry Andric MI = Temp; 2140eae32dcSDimitry Andric 2150eae32dcSDimitry Andric MBB.erase(II); 2160eae32dcSDimitry Andric break; 2170eae32dcSDimitry Andric } 2180eae32dcSDimitry Andric case CSKY::SPILL_CARRY: { 2190eae32dcSDimitry Andric Register NewReg; 2200eae32dcSDimitry Andric if (STI.hasE2()) { 2210eae32dcSDimitry Andric NewReg = MRI.createVirtualRegister(&CSKY::GPRRegClass); 2220eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(CSKY::MVC32), NewReg) 2230eae32dcSDimitry Andric .add(MI->getOperand(0)); 2240eae32dcSDimitry Andric } else { 2250eae32dcSDimitry Andric NewReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass); 2260eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(CSKY::MOVI16), NewReg).addImm(0); 2270eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(CSKY::ADDC16)) 2280eae32dcSDimitry Andric .addReg(NewReg, RegState::Define) 2290eae32dcSDimitry Andric .addReg(MI->getOperand(0).getReg(), RegState::Define) 2300eae32dcSDimitry Andric .addReg(NewReg, getKillRegState(true)) 2310eae32dcSDimitry Andric .addReg(NewReg, getKillRegState(true)) 2320eae32dcSDimitry Andric .addReg(MI->getOperand(0).getReg()); 2330eae32dcSDimitry Andric 2340eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(CSKY::BTSTI16), MI->getOperand(0).getReg()) 2350eae32dcSDimitry Andric .addReg(NewReg) 2360eae32dcSDimitry Andric .addImm(0); 2370eae32dcSDimitry Andric } 2380eae32dcSDimitry Andric 2390eae32dcSDimitry Andric MI = BuildMI(MBB, II, DL, TII->get(CSKY::ST32W)) 2400eae32dcSDimitry Andric .addReg(NewReg, getKillRegState(true)) 2410eae32dcSDimitry Andric .add(MI->getOperand(1)) 2420eae32dcSDimitry Andric .add(MI->getOperand(2)) 2430eae32dcSDimitry Andric .getInstr(); 2440eae32dcSDimitry Andric 2450eae32dcSDimitry Andric MBB.erase(II); 2460eae32dcSDimitry Andric 2470eae32dcSDimitry Andric break; 2480eae32dcSDimitry Andric } 2490eae32dcSDimitry Andric } 2500eae32dcSDimitry Andric 2510eae32dcSDimitry Andric int FrameIndex = MI->getOperand(FIOperandNum).getIndex(); 2520eae32dcSDimitry Andric Register FrameReg; 2530eae32dcSDimitry Andric int Offset = getFrameLowering(MF) 2540eae32dcSDimitry Andric ->getFrameIndexReference(MF, FrameIndex, FrameReg) 2550eae32dcSDimitry Andric .getFixed() + 2560eae32dcSDimitry Andric MI->getOperand(FIOperandNum + 1).getImm(); 2570eae32dcSDimitry Andric 2580eae32dcSDimitry Andric if (!isInt<32>(Offset)) 2590eae32dcSDimitry Andric report_fatal_error( 2600eae32dcSDimitry Andric "Frame offsets outside of the signed 32-bit range not supported"); 2610eae32dcSDimitry Andric 2620eae32dcSDimitry Andric bool FrameRegIsKill = false; 2630eae32dcSDimitry Andric MachineBasicBlock::iterator NewII(MI); 2640eae32dcSDimitry Andric if (!IsLegalOffset(TII, MI, Offset)) { 2650eae32dcSDimitry Andric assert(isInt<32>(Offset) && "Int32 expected"); 2660eae32dcSDimitry Andric // The offset won't fit in an immediate, so use a scratch register instead 2670eae32dcSDimitry Andric // Modify Offset and FrameReg appropriately 2680eae32dcSDimitry Andric Register ScratchReg = TII->movImm(MBB, NewII, DL, Offset); 2690eae32dcSDimitry Andric BuildMI(MBB, NewII, DL, 2700eae32dcSDimitry Andric TII->get(STI.hasE2() ? CSKY::ADDU32 : CSKY::ADDU16XZ), ScratchReg) 2710eae32dcSDimitry Andric .addReg(ScratchReg, RegState::Kill) 2720eae32dcSDimitry Andric .addReg(FrameReg); 2730eae32dcSDimitry Andric 2740eae32dcSDimitry Andric Offset = 0; 2750eae32dcSDimitry Andric FrameReg = ScratchReg; 2760eae32dcSDimitry Andric FrameRegIsKill = true; 2770eae32dcSDimitry Andric } 2780eae32dcSDimitry Andric 2790eae32dcSDimitry Andric if (Offset == 0 && 2800eae32dcSDimitry Andric (MI->getOpcode() == CSKY::ADDI32 || MI->getOpcode() == CSKY::ADDI16XZ)) { 2810eae32dcSDimitry Andric MI->setDesc(TII->get(TargetOpcode::COPY)); 2820eae32dcSDimitry Andric MI->getOperand(FIOperandNum) 2830eae32dcSDimitry Andric .ChangeToRegister(FrameReg, false, false, FrameRegIsKill); 284*81ad6265SDimitry Andric MI->removeOperand(FIOperandNum + 1); 2850eae32dcSDimitry Andric } else { 2860eae32dcSDimitry Andric MI->getOperand(FIOperandNum) 2870eae32dcSDimitry Andric .ChangeToRegister(FrameReg, false, false, FrameRegIsKill); 2880eae32dcSDimitry Andric MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 2890eae32dcSDimitry Andric } 290349cc55cSDimitry Andric } 291