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