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
24using namespace llvm;
25
26CSKYRegisterInfo::CSKYRegisterInfo()
27 : CSKYGenRegisterInfo(CSKY::R15, 0, 0, 0) {}
28
29const uint32_t *
30CSKYRegisterInfo::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
40Register CSKYRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
41 const TargetFrameLowering *TFI = getFrameLowering(MF);
42 return TFI->hasFP(MF) ? CSKY::R8 : CSKY::R14;
43}
44
45BitVector 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
82const uint32_t *CSKYRegisterInfo::getNoPreservedMask() const {
83 return CSR_NoRegs_RegMask;
84}
85
86const MCPhysReg *
87CSKYRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
88 const CSKYSubtarget &STI = MF->getSubtarget<CSKYSubtarget>();
89 if (MF->getFunction().hasFnAttribute(Kind: "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
108static 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>(x: std::abs(x: 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
182bool 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(I: 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(I: II);
246
247 break;
248 }
249 }
250
251 int FrameIndex = MI->getOperand(i: FIOperandNum).getIndex();
252 Register FrameReg;
253 int Offset = getFrameLowering(MF)
254 ->getFrameIndexReference(MF, FrameIndex, FrameReg)
255 .getFixed() +
256 MI->getOperand(i: FIOperandNum + 1).getImm();
257
258 if (!isInt<32>(x: Offset))
259 report_fatal_error(
260 reason: "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, MBBI: NewII, DL, Val: 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(i: FIOperandNum)
283 .ChangeToRegister(Reg: FrameReg, isDef: false, isImp: false, isKill: FrameRegIsKill);
284 MI->removeOperand(OpNo: FIOperandNum + 1);
285 } else {
286 MI->getOperand(i: FIOperandNum)
287 .ChangeToRegister(Reg: FrameReg, isDef: false, isImp: false, isKill: FrameRegIsKill);
288 MI->getOperand(i: FIOperandNum + 1).ChangeToImmediate(ImmVal: Offset);
289 }
290 return false;
291}
292

source code of llvm/lib/Target/CSKY/CSKYRegisterInfo.cpp