1 //===-- CSKYRegisterInfo.h - CSKY Register Information Impl ---*- C++ -*---===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains the CSKY implementation of the TargetRegisterInfo class.
11 //===----------------------------------------------------------------------===//
13 #include "CSKYRegisterInfo.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"
21 #define GET_REGINFO_TARGET_DESC
22 #include "CSKYGenRegisterInfo.inc"
26 CSKYRegisterInfo::CSKYRegisterInfo()
27 : CSKYGenRegisterInfo(CSKY::R15
, 0, 0, 0) {}
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
;
40 Register
CSKYRegisterInfo::getFrameRegister(const MachineFunction
&MF
) const {
41 const TargetFrameLowering
*TFI
= getFrameLowering(MF
);
42 return TFI
->hasFP(MF
) ? CSKY::R8
: CSKY::R14
;
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());
50 // Reserve the base register if we need to allocate
51 // variable-sized objects at runtime.
53 markSuperRegs(Reserved
, CSKY::R7
); // bp
56 markSuperRegs(Reserved
, CSKY::R8
); // fp
59 for (unsigned i
= 0; i
< 6; i
++)
60 markSuperRegs(Reserved
, CSKY::R8
+ i
); // R8 - R13
63 markSuperRegs(Reserved
, CSKY::R14
); // sp
64 markSuperRegs(Reserved
, CSKY::R15
); // lr
66 if (!STI
.hasHighRegisters()) {
67 for (unsigned i
= 0; i
< 10; i
++)
68 markSuperRegs(Reserved
, CSKY::R16
+ i
); // R16 - R25
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
78 assert(checkAllSuperRegsMarked(Reserved
));
82 const uint32_t *CSKYRegisterInfo::getNoPreservedMask() const {
83 return CSR_NoRegs_RegMask
;
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
;
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
;
108 static bool IsLegalOffset(const CSKYInstrInfo
*TII
, MachineInstr
*MI
,
110 const MCInstrDesc
&Desc
= MI
->getDesc();
111 unsigned AddrMode
= (Desc
.TSFlags
& CSKYII::AddrModeMask
);
113 for (; !MI
->getOperand(i
).isFI(); ++i
) {
114 assert(i
+ 1 < MI
->getNumOperands() &&
115 "Instr doesn't have FrameIndex operand!");
118 if (MI
->getOpcode() == CSKY::ADDI32
) {
119 if (!isUInt
<12>(std::abs(Offset
) - 1))
122 MI
->setDesc(TII
->get(CSKY::SUBI32
));
129 if (MI
->getOpcode() == CSKY::ADDI16XZ
)
135 unsigned NumBits
= 0;
138 case CSKYII::AddrMode32B
:
142 case CSKYII::AddrMode32H
:
146 case CSKYII::AddrMode32WD
:
150 case CSKYII::AddrMode16B
:
154 case CSKYII::AddrMode16H
:
158 case CSKYII::AddrMode16W
:
162 case CSKYII::AddrMode32SDF
:
167 llvm_unreachable("Unsupported addressing mode!");
170 // Cannot encode offset.
171 if ((Offset
& (Scale
- 1)) != 0)
174 unsigned Mask
= (1 << NumBits
) - 1;
175 if ((unsigned)Offset
<= Mask
* Scale
)
178 // Offset out of range.
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");
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
>();
195 switch (MI
->getOpcode()) {
198 case CSKY::RESTORE_CARRY
: {
199 Register NewReg
= STI
.hasE2()
200 ? MRI
.createVirtualRegister(&CSKY::GPRRegClass
)
201 : MRI
.createVirtualRegister(&CSKY::mGPRRegClass
);
203 auto *Temp
= BuildMI(MBB
, II
, DL
, TII
->get(CSKY::LD32W
), NewReg
)
204 .add(MI
->getOperand(1))
205 .add(MI
->getOperand(2))
208 BuildMI(MBB
, II
, DL
, TII
->get(STI
.hasE2() ? CSKY::BTSTI32
: CSKY::BTSTI16
),
209 MI
->getOperand(0).getReg())
210 .addReg(NewReg
, getKillRegState(true))
218 case CSKY::SPILL_CARRY
: {
221 NewReg
= MRI
.createVirtualRegister(&CSKY::GPRRegClass
);
222 BuildMI(MBB
, II
, DL
, TII
->get(CSKY::MVC32
), NewReg
)
223 .add(MI
->getOperand(0));
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());
234 BuildMI(MBB
, II
, DL
, TII
->get(CSKY::BTSTI16
), MI
->getOperand(0).getReg())
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))
251 int FrameIndex
= MI
->getOperand(FIOperandNum
).getIndex();
253 int Offset
= getFrameLowering(MF
)
254 ->getFrameIndexReference(MF
, FrameIndex
, FrameReg
)
256 MI
->getOperand(FIOperandNum
+ 1).getImm();
258 if (!isInt
<32>(Offset
))
260 "Frame offsets outside of the signed 32-bit range not supported");
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
)
275 FrameReg
= ScratchReg
;
276 FrameRegIsKill
= true;
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);
286 MI
->getOperand(FIOperandNum
)
287 .ChangeToRegister(FrameReg
, false, false, FrameRegIsKill
);
288 MI
->getOperand(FIOperandNum
+ 1).ChangeToImmediate(Offset
);