1 //===-- CSKYRegisterInfo.h - CSKY Register Information Impl ---*- C++ -*---===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains the CSKY implementation of the TargetRegisterInfo class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CSKYRegisterInfo.h" 14 #include "CSKY.h" 15 #include "CSKYSubtarget.h" 16 #include "llvm/CodeGen/MachineFunction.h" 17 #include "llvm/CodeGen/RegisterScavenging.h" 18 #include "llvm/MC/MCContext.h" 19 20 #define GET_REGINFO_TARGET_DESC 21 #include "CSKYGenRegisterInfo.inc" 22 23 using namespace llvm; 24 25 CSKYRegisterInfo::CSKYRegisterInfo() 26 : CSKYGenRegisterInfo(CSKY::R15, 0, 0, 0) {} 27 28 const uint32_t * 29 CSKYRegisterInfo::getCallPreservedMask(const MachineFunction &MF, 30 CallingConv::ID Id) const { 31 const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>(); 32 return CSR_I32_RegMask; 33 } 34 35 Register CSKYRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 36 const TargetFrameLowering *TFI = getFrameLowering(MF); 37 return TFI->hasFP(MF) ? CSKY::R8 : CSKY::R14; 38 } 39 40 BitVector CSKYRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 41 const CSKYFrameLowering *TFI = getFrameLowering(MF); 42 const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>(); 43 BitVector Reserved(getNumRegs()); 44 45 // Reserve the base register if we need to allocate 46 // variable-sized objects at runtime. 47 if (TFI->hasBP(MF)) 48 markSuperRegs(Reserved, CSKY::R7); // bp 49 50 if (TFI->hasFP(MF)) 51 markSuperRegs(Reserved, CSKY::R8); // fp 52 53 if (!STI.hasE2()) { 54 for (unsigned i = 0; i < 6; i++) 55 markSuperRegs(Reserved, CSKY::R8 + i); // R8 - R13 56 } 57 58 markSuperRegs(Reserved, CSKY::R14); // sp 59 markSuperRegs(Reserved, CSKY::R15); // lr 60 61 if (!STI.hasHighRegisters()) { 62 for (unsigned i = 0; i < 10; i++) 63 markSuperRegs(Reserved, CSKY::R16 + i); // R16 - R25 64 } 65 66 markSuperRegs(Reserved, CSKY::R26); 67 markSuperRegs(Reserved, CSKY::R27); 68 markSuperRegs(Reserved, CSKY::R28); // gp 69 markSuperRegs(Reserved, CSKY::R29); 70 markSuperRegs(Reserved, CSKY::R30); 71 markSuperRegs(Reserved, CSKY::R31); // tp 72 73 assert(checkAllSuperRegsMarked(Reserved)); 74 return Reserved; 75 } 76 77 const uint32_t *CSKYRegisterInfo::getNoPreservedMask() const { 78 return CSR_NoRegs_RegMask; 79 } 80 81 const MCPhysReg * 82 CSKYRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 83 const CSKYSubtarget &STI = MF->getSubtarget<CSKYSubtarget>(); 84 if (MF->getFunction().hasFnAttribute("interrupt")) { 85 return CSR_GPR_ISR_SaveList; 86 } 87 88 return CSR_I32_SaveList; 89 } 90 91 static bool IsLegalOffset(const CSKYInstrInfo *TII, MachineInstr *MI, 92 int &Offset) { 93 const MCInstrDesc &Desc = MI->getDesc(); 94 unsigned AddrMode = (Desc.TSFlags & CSKYII::AddrModeMask); 95 unsigned i = 0; 96 for (; !MI->getOperand(i).isFI(); ++i) { 97 assert(i + 1 < MI->getNumOperands() && 98 "Instr doesn't have FrameIndex operand!"); 99 } 100 101 if (MI->getOpcode() == CSKY::ADDI32) { 102 if (!isUInt<12>(std::abs(Offset) - 1)) 103 return false; 104 if (Offset < 0) { 105 MI->setDesc(TII->get(CSKY::SUBI32)); 106 Offset = -Offset; 107 } 108 109 return true; 110 } 111 112 if (MI->getOpcode() == CSKY::ADDI16XZ) 113 return false; 114 115 if (Offset < 0) 116 return false; 117 118 unsigned NumBits = 0; 119 unsigned Scale = 1; 120 switch (AddrMode) { 121 case CSKYII::AddrMode32B: 122 Scale = 1; 123 NumBits = 12; 124 break; 125 case CSKYII::AddrMode32H: 126 Scale = 2; 127 NumBits = 12; 128 break; 129 case CSKYII::AddrMode32WD: 130 Scale = 4; 131 NumBits = 12; 132 break; 133 case CSKYII::AddrMode16B: 134 Scale = 1; 135 NumBits = 5; 136 break; 137 case CSKYII::AddrMode16H: 138 Scale = 2; 139 NumBits = 5; 140 break; 141 case CSKYII::AddrMode16W: 142 Scale = 4; 143 NumBits = 5; 144 break; 145 case CSKYII::AddrMode32SDF: 146 Scale = 4; 147 NumBits = 8; 148 break; 149 default: 150 llvm_unreachable("Unsupported addressing mode!"); 151 } 152 153 // Cannot encode offset. 154 if ((Offset & (Scale - 1)) != 0) 155 return false; 156 157 unsigned Mask = (1 << NumBits) - 1; 158 if ((unsigned)Offset <= Mask * Scale) 159 return true; 160 161 // Offset out of range. 162 return false; 163 } 164 165 void CSKYRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 166 int SPAdj, unsigned FIOperandNum, 167 RegScavenger *RS) const { 168 assert(SPAdj == 0 && "Unexpected non-zero SPAdj value"); 169 170 MachineInstr *MI = &*II; 171 MachineBasicBlock &MBB = *MI->getParent(); 172 MachineFunction &MF = *MI->getParent()->getParent(); 173 MachineRegisterInfo &MRI = MF.getRegInfo(); 174 const CSKYInstrInfo *TII = MF.getSubtarget<CSKYSubtarget>().getInstrInfo(); 175 DebugLoc DL = MI->getDebugLoc(); 176 const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>(); 177 178 switch (MI->getOpcode()) { 179 default: 180 break; 181 case CSKY::RESTORE_CARRY: { 182 Register NewReg = STI.hasE2() 183 ? MRI.createVirtualRegister(&CSKY::GPRRegClass) 184 : MRI.createVirtualRegister(&CSKY::mGPRRegClass); 185 186 auto *Temp = BuildMI(MBB, II, DL, TII->get(CSKY::LD32W), NewReg) 187 .add(MI->getOperand(1)) 188 .add(MI->getOperand(2)) 189 .getInstr(); 190 191 BuildMI(MBB, II, DL, TII->get(STI.hasE2() ? CSKY::BTSTI32 : CSKY::BTSTI16), 192 MI->getOperand(0).getReg()) 193 .addReg(NewReg, getKillRegState(true)) 194 .addImm(0); 195 196 MI = Temp; 197 198 MBB.erase(II); 199 break; 200 } 201 case CSKY::SPILL_CARRY: { 202 Register NewReg; 203 if (STI.hasE2()) { 204 NewReg = MRI.createVirtualRegister(&CSKY::GPRRegClass); 205 BuildMI(MBB, II, DL, TII->get(CSKY::MVC32), NewReg) 206 .add(MI->getOperand(0)); 207 } else { 208 NewReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass); 209 BuildMI(MBB, II, DL, TII->get(CSKY::MOVI16), NewReg).addImm(0); 210 BuildMI(MBB, II, DL, TII->get(CSKY::ADDC16)) 211 .addReg(NewReg, RegState::Define) 212 .addReg(MI->getOperand(0).getReg(), RegState::Define) 213 .addReg(NewReg, getKillRegState(true)) 214 .addReg(NewReg, getKillRegState(true)) 215 .addReg(MI->getOperand(0).getReg()); 216 217 BuildMI(MBB, II, DL, TII->get(CSKY::BTSTI16), MI->getOperand(0).getReg()) 218 .addReg(NewReg) 219 .addImm(0); 220 } 221 222 MI = BuildMI(MBB, II, DL, TII->get(CSKY::ST32W)) 223 .addReg(NewReg, getKillRegState(true)) 224 .add(MI->getOperand(1)) 225 .add(MI->getOperand(2)) 226 .getInstr(); 227 228 MBB.erase(II); 229 230 break; 231 } 232 } 233 234 int FrameIndex = MI->getOperand(FIOperandNum).getIndex(); 235 Register FrameReg; 236 int Offset = getFrameLowering(MF) 237 ->getFrameIndexReference(MF, FrameIndex, FrameReg) 238 .getFixed() + 239 MI->getOperand(FIOperandNum + 1).getImm(); 240 241 if (!isInt<32>(Offset)) 242 report_fatal_error( 243 "Frame offsets outside of the signed 32-bit range not supported"); 244 245 bool FrameRegIsKill = false; 246 MachineBasicBlock::iterator NewII(MI); 247 if (!IsLegalOffset(TII, MI, Offset)) { 248 assert(isInt<32>(Offset) && "Int32 expected"); 249 // The offset won't fit in an immediate, so use a scratch register instead 250 // Modify Offset and FrameReg appropriately 251 assert(Offset >= 0); 252 Register ScratchReg = TII->movImm(MBB, NewII, DL, Offset); 253 BuildMI(MBB, NewII, DL, 254 TII->get(STI.hasE2() ? CSKY::ADDU32 : CSKY::ADDU16XZ), ScratchReg) 255 .addReg(ScratchReg, RegState::Kill) 256 .addReg(FrameReg); 257 258 Offset = 0; 259 FrameReg = ScratchReg; 260 FrameRegIsKill = true; 261 } 262 263 if (Offset == 0 && 264 (MI->getOpcode() == CSKY::ADDI32 || MI->getOpcode() == CSKY::ADDI16XZ)) { 265 MI->setDesc(TII->get(TargetOpcode::COPY)); 266 MI->getOperand(FIOperandNum) 267 .ChangeToRegister(FrameReg, false, false, FrameRegIsKill); 268 MI->RemoveOperand(FIOperandNum + 1); 269 } else { 270 MI->getOperand(FIOperandNum) 271 .ChangeToRegister(FrameReg, false, false, FrameRegIsKill); 272 MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 273 } 274 } 275