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 bool 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   return false;
291 }
292