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