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