1*d415bd75Srobert //===-- CSKYInstrInfo.h - CSKY Instruction Information --------*- C++ -*---===//
2*d415bd75Srobert //
3*d415bd75Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*d415bd75Srobert // See https://llvm.org/LICENSE.txt for license information.
5*d415bd75Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*d415bd75Srobert //
7*d415bd75Srobert //===----------------------------------------------------------------------===//
8*d415bd75Srobert //
9*d415bd75Srobert // This file contains the CSKY implementation of the TargetInstrInfo class.
10*d415bd75Srobert //
11*d415bd75Srobert //===----------------------------------------------------------------------===//
12*d415bd75Srobert
13*d415bd75Srobert #include "CSKYInstrInfo.h"
14*d415bd75Srobert #include "CSKYConstantPoolValue.h"
15*d415bd75Srobert #include "CSKYMachineFunctionInfo.h"
16*d415bd75Srobert #include "CSKYTargetMachine.h"
17*d415bd75Srobert #include "llvm/CodeGen/MachineFrameInfo.h"
18*d415bd75Srobert #include "llvm/MC/MCContext.h"
19*d415bd75Srobert
20*d415bd75Srobert #define DEBUG_TYPE "csky-instr-info"
21*d415bd75Srobert
22*d415bd75Srobert using namespace llvm;
23*d415bd75Srobert
24*d415bd75Srobert #define GET_INSTRINFO_CTOR_DTOR
25*d415bd75Srobert #include "CSKYGenInstrInfo.inc"
26*d415bd75Srobert
CSKYInstrInfo(CSKYSubtarget & STI)27*d415bd75Srobert CSKYInstrInfo::CSKYInstrInfo(CSKYSubtarget &STI)
28*d415bd75Srobert : CSKYGenInstrInfo(CSKY::ADJCALLSTACKDOWN, CSKY::ADJCALLSTACKUP), STI(STI) {
29*d415bd75Srobert v2sf = STI.hasFPUv2SingleFloat();
30*d415bd75Srobert v2df = STI.hasFPUv2DoubleFloat();
31*d415bd75Srobert v3sf = STI.hasFPUv3SingleFloat();
32*d415bd75Srobert v3df = STI.hasFPUv3DoubleFloat();
33*d415bd75Srobert }
34*d415bd75Srobert
parseCondBranch(MachineInstr & LastInst,MachineBasicBlock * & Target,SmallVectorImpl<MachineOperand> & Cond)35*d415bd75Srobert static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
36*d415bd75Srobert SmallVectorImpl<MachineOperand> &Cond) {
37*d415bd75Srobert // Block ends with fall-through condbranch.
38*d415bd75Srobert assert(LastInst.getDesc().isConditionalBranch() &&
39*d415bd75Srobert "Unknown conditional branch");
40*d415bd75Srobert Target = LastInst.getOperand(1).getMBB();
41*d415bd75Srobert Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode()));
42*d415bd75Srobert Cond.push_back(LastInst.getOperand(0));
43*d415bd75Srobert }
44*d415bd75Srobert
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const45*d415bd75Srobert bool CSKYInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
46*d415bd75Srobert MachineBasicBlock *&TBB,
47*d415bd75Srobert MachineBasicBlock *&FBB,
48*d415bd75Srobert SmallVectorImpl<MachineOperand> &Cond,
49*d415bd75Srobert bool AllowModify) const {
50*d415bd75Srobert TBB = FBB = nullptr;
51*d415bd75Srobert Cond.clear();
52*d415bd75Srobert
53*d415bd75Srobert // If the block has no terminators, it just falls into the block after it.
54*d415bd75Srobert MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
55*d415bd75Srobert if (I == MBB.end() || !isUnpredicatedTerminator(*I))
56*d415bd75Srobert return false;
57*d415bd75Srobert
58*d415bd75Srobert // Count the number of terminators and find the first unconditional or
59*d415bd75Srobert // indirect branch.
60*d415bd75Srobert MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end();
61*d415bd75Srobert int NumTerminators = 0;
62*d415bd75Srobert for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J);
63*d415bd75Srobert J++) {
64*d415bd75Srobert NumTerminators++;
65*d415bd75Srobert if (J->getDesc().isUnconditionalBranch() ||
66*d415bd75Srobert J->getDesc().isIndirectBranch()) {
67*d415bd75Srobert FirstUncondOrIndirectBr = J.getReverse();
68*d415bd75Srobert }
69*d415bd75Srobert }
70*d415bd75Srobert
71*d415bd75Srobert // If AllowModify is true, we can erase any terminators after
72*d415bd75Srobert // FirstUncondOrIndirectBR.
73*d415bd75Srobert if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) {
74*d415bd75Srobert while (std::next(FirstUncondOrIndirectBr) != MBB.end()) {
75*d415bd75Srobert std::next(FirstUncondOrIndirectBr)->eraseFromParent();
76*d415bd75Srobert NumTerminators--;
77*d415bd75Srobert }
78*d415bd75Srobert I = FirstUncondOrIndirectBr;
79*d415bd75Srobert }
80*d415bd75Srobert
81*d415bd75Srobert // We can't handle blocks that end in an indirect branch.
82*d415bd75Srobert if (I->getDesc().isIndirectBranch())
83*d415bd75Srobert return true;
84*d415bd75Srobert
85*d415bd75Srobert // We can't handle blocks with more than 2 terminators.
86*d415bd75Srobert if (NumTerminators > 2)
87*d415bd75Srobert return true;
88*d415bd75Srobert
89*d415bd75Srobert // Handle a single unconditional branch.
90*d415bd75Srobert if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {
91*d415bd75Srobert TBB = getBranchDestBlock(*I);
92*d415bd75Srobert return false;
93*d415bd75Srobert }
94*d415bd75Srobert
95*d415bd75Srobert // Handle a single conditional branch.
96*d415bd75Srobert if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
97*d415bd75Srobert parseCondBranch(*I, TBB, Cond);
98*d415bd75Srobert return false;
99*d415bd75Srobert }
100*d415bd75Srobert
101*d415bd75Srobert // Handle a conditional branch followed by an unconditional branch.
102*d415bd75Srobert if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() &&
103*d415bd75Srobert I->getDesc().isUnconditionalBranch()) {
104*d415bd75Srobert parseCondBranch(*std::prev(I), TBB, Cond);
105*d415bd75Srobert FBB = getBranchDestBlock(*I);
106*d415bd75Srobert return false;
107*d415bd75Srobert }
108*d415bd75Srobert
109*d415bd75Srobert // Otherwise, we can't handle this.
110*d415bd75Srobert return true;
111*d415bd75Srobert }
112*d415bd75Srobert
removeBranch(MachineBasicBlock & MBB,int * BytesRemoved) const113*d415bd75Srobert unsigned CSKYInstrInfo::removeBranch(MachineBasicBlock &MBB,
114*d415bd75Srobert int *BytesRemoved) const {
115*d415bd75Srobert if (BytesRemoved)
116*d415bd75Srobert *BytesRemoved = 0;
117*d415bd75Srobert MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
118*d415bd75Srobert if (I == MBB.end())
119*d415bd75Srobert return 0;
120*d415bd75Srobert
121*d415bd75Srobert if (!I->getDesc().isUnconditionalBranch() &&
122*d415bd75Srobert !I->getDesc().isConditionalBranch())
123*d415bd75Srobert return 0;
124*d415bd75Srobert
125*d415bd75Srobert // Remove the branch.
126*d415bd75Srobert if (BytesRemoved)
127*d415bd75Srobert *BytesRemoved += getInstSizeInBytes(*I);
128*d415bd75Srobert I->eraseFromParent();
129*d415bd75Srobert
130*d415bd75Srobert I = MBB.end();
131*d415bd75Srobert
132*d415bd75Srobert if (I == MBB.begin())
133*d415bd75Srobert return 1;
134*d415bd75Srobert --I;
135*d415bd75Srobert if (!I->getDesc().isConditionalBranch())
136*d415bd75Srobert return 1;
137*d415bd75Srobert
138*d415bd75Srobert // Remove the branch.
139*d415bd75Srobert if (BytesRemoved)
140*d415bd75Srobert *BytesRemoved += getInstSizeInBytes(*I);
141*d415bd75Srobert I->eraseFromParent();
142*d415bd75Srobert return 2;
143*d415bd75Srobert }
144*d415bd75Srobert
145*d415bd75Srobert MachineBasicBlock *
getBranchDestBlock(const MachineInstr & MI) const146*d415bd75Srobert CSKYInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
147*d415bd75Srobert assert(MI.getDesc().isBranch() && "Unexpected opcode!");
148*d415bd75Srobert // The branch target is always the last operand.
149*d415bd75Srobert int NumOp = MI.getNumExplicitOperands();
150*d415bd75Srobert assert(MI.getOperand(NumOp - 1).isMBB() && "Expected MBB!");
151*d415bd75Srobert return MI.getOperand(NumOp - 1).getMBB();
152*d415bd75Srobert }
153*d415bd75Srobert
insertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL,int * BytesAdded) const154*d415bd75Srobert unsigned CSKYInstrInfo::insertBranch(
155*d415bd75Srobert MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
156*d415bd75Srobert ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
157*d415bd75Srobert if (BytesAdded)
158*d415bd75Srobert *BytesAdded = 0;
159*d415bd75Srobert
160*d415bd75Srobert // Shouldn't be a fall through.
161*d415bd75Srobert assert(TBB && "insertBranch must not be told to insert a fallthrough");
162*d415bd75Srobert assert((Cond.size() == 2 || Cond.size() == 0) &&
163*d415bd75Srobert "CSKY branch conditions have two components!");
164*d415bd75Srobert
165*d415bd75Srobert // Unconditional branch.
166*d415bd75Srobert if (Cond.empty()) {
167*d415bd75Srobert MachineInstr &MI = *BuildMI(&MBB, DL, get(CSKY::BR32)).addMBB(TBB);
168*d415bd75Srobert if (BytesAdded)
169*d415bd75Srobert *BytesAdded += getInstSizeInBytes(MI);
170*d415bd75Srobert return 1;
171*d415bd75Srobert }
172*d415bd75Srobert
173*d415bd75Srobert // Either a one or two-way conditional branch.
174*d415bd75Srobert unsigned Opc = Cond[0].getImm();
175*d415bd75Srobert MachineInstr &CondMI = *BuildMI(&MBB, DL, get(Opc)).add(Cond[1]).addMBB(TBB);
176*d415bd75Srobert if (BytesAdded)
177*d415bd75Srobert *BytesAdded += getInstSizeInBytes(CondMI);
178*d415bd75Srobert
179*d415bd75Srobert // One-way conditional branch.
180*d415bd75Srobert if (!FBB)
181*d415bd75Srobert return 1;
182*d415bd75Srobert
183*d415bd75Srobert // Two-way conditional branch.
184*d415bd75Srobert MachineInstr &MI = *BuildMI(&MBB, DL, get(CSKY::BR32)).addMBB(FBB);
185*d415bd75Srobert if (BytesAdded)
186*d415bd75Srobert *BytesAdded += getInstSizeInBytes(MI);
187*d415bd75Srobert return 2;
188*d415bd75Srobert }
189*d415bd75Srobert
getOppositeBranchOpc(unsigned Opcode)190*d415bd75Srobert static unsigned getOppositeBranchOpc(unsigned Opcode) {
191*d415bd75Srobert switch (Opcode) {
192*d415bd75Srobert default:
193*d415bd75Srobert llvm_unreachable("Unknown conditional branch!");
194*d415bd75Srobert case CSKY::BT32:
195*d415bd75Srobert return CSKY::BF32;
196*d415bd75Srobert case CSKY::BT16:
197*d415bd75Srobert return CSKY::BF16;
198*d415bd75Srobert case CSKY::BF32:
199*d415bd75Srobert return CSKY::BT32;
200*d415bd75Srobert case CSKY::BF16:
201*d415bd75Srobert return CSKY::BT16;
202*d415bd75Srobert case CSKY::BHZ32:
203*d415bd75Srobert return CSKY::BLSZ32;
204*d415bd75Srobert case CSKY::BHSZ32:
205*d415bd75Srobert return CSKY::BLZ32;
206*d415bd75Srobert case CSKY::BLZ32:
207*d415bd75Srobert return CSKY::BHSZ32;
208*d415bd75Srobert case CSKY::BLSZ32:
209*d415bd75Srobert return CSKY::BHZ32;
210*d415bd75Srobert case CSKY::BNEZ32:
211*d415bd75Srobert return CSKY::BEZ32;
212*d415bd75Srobert case CSKY::BEZ32:
213*d415bd75Srobert return CSKY::BNEZ32;
214*d415bd75Srobert }
215*d415bd75Srobert }
216*d415bd75Srobert
reverseBranchCondition(SmallVectorImpl<MachineOperand> & Cond) const217*d415bd75Srobert bool CSKYInstrInfo::reverseBranchCondition(
218*d415bd75Srobert SmallVectorImpl<MachineOperand> &Cond) const {
219*d415bd75Srobert assert((Cond.size() == 2) && "Invalid branch condition!");
220*d415bd75Srobert Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm()));
221*d415bd75Srobert return false;
222*d415bd75Srobert }
223*d415bd75Srobert
movImm(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,uint64_t Val,MachineInstr::MIFlag Flag) const224*d415bd75Srobert Register CSKYInstrInfo::movImm(MachineBasicBlock &MBB,
225*d415bd75Srobert MachineBasicBlock::iterator MBBI,
226*d415bd75Srobert const DebugLoc &DL, uint64_t Val,
227*d415bd75Srobert MachineInstr::MIFlag Flag) const {
228*d415bd75Srobert if (!isInt<32>(Val))
229*d415bd75Srobert report_fatal_error("Should only materialize 32-bit constants.");
230*d415bd75Srobert
231*d415bd75Srobert MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
232*d415bd75Srobert
233*d415bd75Srobert Register DstReg;
234*d415bd75Srobert if (STI.hasE2()) {
235*d415bd75Srobert DstReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);
236*d415bd75Srobert
237*d415bd75Srobert if (isUInt<16>(Val)) {
238*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::MOVI32), DstReg)
239*d415bd75Srobert .addImm(Val & 0xFFFF)
240*d415bd75Srobert .setMIFlags(Flag);
241*d415bd75Srobert } else if (isShiftedUInt<16, 16>(Val)) {
242*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg)
243*d415bd75Srobert .addImm((Val >> 16) & 0xFFFF)
244*d415bd75Srobert .setMIFlags(Flag);
245*d415bd75Srobert } else {
246*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg)
247*d415bd75Srobert .addImm((Val >> 16) & 0xFFFF)
248*d415bd75Srobert .setMIFlags(Flag);
249*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::ORI32), DstReg)
250*d415bd75Srobert .addReg(DstReg)
251*d415bd75Srobert .addImm(Val & 0xFFFF)
252*d415bd75Srobert .setMIFlags(Flag);
253*d415bd75Srobert }
254*d415bd75Srobert
255*d415bd75Srobert } else {
256*d415bd75Srobert DstReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass);
257*d415bd75Srobert if (isUInt<8>(Val)) {
258*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
259*d415bd75Srobert .addImm(Val & 0xFF)
260*d415bd75Srobert .setMIFlags(Flag);
261*d415bd75Srobert } else if (isUInt<16>(Val)) {
262*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
263*d415bd75Srobert .addImm((Val >> 8) & 0xFF)
264*d415bd75Srobert .setMIFlags(Flag);
265*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
266*d415bd75Srobert .addReg(DstReg)
267*d415bd75Srobert .addImm(8)
268*d415bd75Srobert .setMIFlags(Flag);
269*d415bd75Srobert if ((Val & 0xFF) != 0)
270*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
271*d415bd75Srobert .addReg(DstReg)
272*d415bd75Srobert .addImm(Val & 0xFF)
273*d415bd75Srobert .setMIFlags(Flag);
274*d415bd75Srobert } else if (isUInt<24>(Val)) {
275*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
276*d415bd75Srobert .addImm((Val >> 16) & 0xFF)
277*d415bd75Srobert .setMIFlags(Flag);
278*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
279*d415bd75Srobert .addReg(DstReg)
280*d415bd75Srobert .addImm(8)
281*d415bd75Srobert .setMIFlags(Flag);
282*d415bd75Srobert if (((Val >> 8) & 0xFF) != 0)
283*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
284*d415bd75Srobert .addReg(DstReg)
285*d415bd75Srobert .addImm((Val >> 8) & 0xFF)
286*d415bd75Srobert .setMIFlags(Flag);
287*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
288*d415bd75Srobert .addReg(DstReg)
289*d415bd75Srobert .addImm(8)
290*d415bd75Srobert .setMIFlags(Flag);
291*d415bd75Srobert if ((Val & 0xFF) != 0)
292*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
293*d415bd75Srobert .addReg(DstReg)
294*d415bd75Srobert .addImm(Val & 0xFF)
295*d415bd75Srobert .setMIFlags(Flag);
296*d415bd75Srobert } else {
297*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
298*d415bd75Srobert .addImm((Val >> 24) & 0xFF)
299*d415bd75Srobert .setMIFlags(Flag);
300*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
301*d415bd75Srobert .addReg(DstReg)
302*d415bd75Srobert .addImm(8)
303*d415bd75Srobert .setMIFlags(Flag);
304*d415bd75Srobert if (((Val >> 16) & 0xFF) != 0)
305*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
306*d415bd75Srobert .addReg(DstReg)
307*d415bd75Srobert .addImm((Val >> 16) & 0xFF)
308*d415bd75Srobert .setMIFlags(Flag);
309*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
310*d415bd75Srobert .addReg(DstReg)
311*d415bd75Srobert .addImm(8)
312*d415bd75Srobert .setMIFlags(Flag);
313*d415bd75Srobert if (((Val >> 8) & 0xFF) != 0)
314*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
315*d415bd75Srobert .addReg(DstReg)
316*d415bd75Srobert .addImm((Val >> 8) & 0xFF)
317*d415bd75Srobert .setMIFlags(Flag);
318*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
319*d415bd75Srobert .addReg(DstReg)
320*d415bd75Srobert .addImm(8)
321*d415bd75Srobert .setMIFlags(Flag);
322*d415bd75Srobert if ((Val & 0xFF) != 0)
323*d415bd75Srobert BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
324*d415bd75Srobert .addReg(DstReg)
325*d415bd75Srobert .addImm(Val & 0xFF)
326*d415bd75Srobert .setMIFlags(Flag);
327*d415bd75Srobert }
328*d415bd75Srobert }
329*d415bd75Srobert
330*d415bd75Srobert return DstReg;
331*d415bd75Srobert }
332*d415bd75Srobert
isLoadFromStackSlot(const MachineInstr & MI,int & FrameIndex) const333*d415bd75Srobert unsigned CSKYInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
334*d415bd75Srobert int &FrameIndex) const {
335*d415bd75Srobert switch (MI.getOpcode()) {
336*d415bd75Srobert default:
337*d415bd75Srobert return 0;
338*d415bd75Srobert case CSKY::LD16B:
339*d415bd75Srobert case CSKY::LD16H:
340*d415bd75Srobert case CSKY::LD16W:
341*d415bd75Srobert case CSKY::LD32B:
342*d415bd75Srobert case CSKY::LD32BS:
343*d415bd75Srobert case CSKY::LD32H:
344*d415bd75Srobert case CSKY::LD32HS:
345*d415bd75Srobert case CSKY::LD32W:
346*d415bd75Srobert case CSKY::FLD_S:
347*d415bd75Srobert case CSKY::FLD_D:
348*d415bd75Srobert case CSKY::f2FLD_S:
349*d415bd75Srobert case CSKY::f2FLD_D:
350*d415bd75Srobert case CSKY::RESTORE_CARRY:
351*d415bd75Srobert break;
352*d415bd75Srobert }
353*d415bd75Srobert
354*d415bd75Srobert if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
355*d415bd75Srobert MI.getOperand(2).getImm() == 0) {
356*d415bd75Srobert FrameIndex = MI.getOperand(1).getIndex();
357*d415bd75Srobert return MI.getOperand(0).getReg();
358*d415bd75Srobert }
359*d415bd75Srobert
360*d415bd75Srobert return 0;
361*d415bd75Srobert }
362*d415bd75Srobert
isStoreToStackSlot(const MachineInstr & MI,int & FrameIndex) const363*d415bd75Srobert unsigned CSKYInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
364*d415bd75Srobert int &FrameIndex) const {
365*d415bd75Srobert switch (MI.getOpcode()) {
366*d415bd75Srobert default:
367*d415bd75Srobert return 0;
368*d415bd75Srobert case CSKY::ST16B:
369*d415bd75Srobert case CSKY::ST16H:
370*d415bd75Srobert case CSKY::ST16W:
371*d415bd75Srobert case CSKY::ST32B:
372*d415bd75Srobert case CSKY::ST32H:
373*d415bd75Srobert case CSKY::ST32W:
374*d415bd75Srobert case CSKY::FST_S:
375*d415bd75Srobert case CSKY::FST_D:
376*d415bd75Srobert case CSKY::f2FST_S:
377*d415bd75Srobert case CSKY::f2FST_D:
378*d415bd75Srobert case CSKY::SPILL_CARRY:
379*d415bd75Srobert break;
380*d415bd75Srobert }
381*d415bd75Srobert
382*d415bd75Srobert if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
383*d415bd75Srobert MI.getOperand(2).getImm() == 0) {
384*d415bd75Srobert FrameIndex = MI.getOperand(1).getIndex();
385*d415bd75Srobert return MI.getOperand(0).getReg();
386*d415bd75Srobert }
387*d415bd75Srobert
388*d415bd75Srobert return 0;
389*d415bd75Srobert }
390*d415bd75Srobert
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,Register SrcReg,bool IsKill,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg) const391*d415bd75Srobert void CSKYInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
392*d415bd75Srobert MachineBasicBlock::iterator I,
393*d415bd75Srobert Register SrcReg, bool IsKill, int FI,
394*d415bd75Srobert const TargetRegisterClass *RC,
395*d415bd75Srobert const TargetRegisterInfo *TRI,
396*d415bd75Srobert Register VReg) const {
397*d415bd75Srobert DebugLoc DL;
398*d415bd75Srobert if (I != MBB.end())
399*d415bd75Srobert DL = I->getDebugLoc();
400*d415bd75Srobert
401*d415bd75Srobert MachineFunction &MF = *MBB.getParent();
402*d415bd75Srobert CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
403*d415bd75Srobert MachineFrameInfo &MFI = MF.getFrameInfo();
404*d415bd75Srobert
405*d415bd75Srobert unsigned Opcode = 0;
406*d415bd75Srobert
407*d415bd75Srobert if (CSKY::GPRRegClass.hasSubClassEq(RC)) {
408*d415bd75Srobert Opcode = CSKY::ST32W; // Optimize for 16bit
409*d415bd75Srobert } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) {
410*d415bd75Srobert Opcode = CSKY::SPILL_CARRY;
411*d415bd75Srobert CFI->setSpillsCR();
412*d415bd75Srobert } else if (v2sf && CSKY::sFPR32RegClass.hasSubClassEq(RC))
413*d415bd75Srobert Opcode = CSKY::FST_S;
414*d415bd75Srobert else if (v2df && CSKY::sFPR64RegClass.hasSubClassEq(RC))
415*d415bd75Srobert Opcode = CSKY::FST_D;
416*d415bd75Srobert else if (v3sf && CSKY::FPR32RegClass.hasSubClassEq(RC))
417*d415bd75Srobert Opcode = CSKY::f2FST_S;
418*d415bd75Srobert else if (v3df && CSKY::FPR64RegClass.hasSubClassEq(RC))
419*d415bd75Srobert Opcode = CSKY::f2FST_D;
420*d415bd75Srobert else {
421*d415bd75Srobert llvm_unreachable("Unknown RegisterClass");
422*d415bd75Srobert }
423*d415bd75Srobert
424*d415bd75Srobert MachineMemOperand *MMO = MF.getMachineMemOperand(
425*d415bd75Srobert MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,
426*d415bd75Srobert MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
427*d415bd75Srobert
428*d415bd75Srobert BuildMI(MBB, I, DL, get(Opcode))
429*d415bd75Srobert .addReg(SrcReg, getKillRegState(IsKill))
430*d415bd75Srobert .addFrameIndex(FI)
431*d415bd75Srobert .addImm(0)
432*d415bd75Srobert .addMemOperand(MMO);
433*d415bd75Srobert }
434*d415bd75Srobert
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,Register DestReg,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg) const435*d415bd75Srobert void CSKYInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
436*d415bd75Srobert MachineBasicBlock::iterator I,
437*d415bd75Srobert Register DestReg, int FI,
438*d415bd75Srobert const TargetRegisterClass *RC,
439*d415bd75Srobert const TargetRegisterInfo *TRI,
440*d415bd75Srobert Register VReg) const {
441*d415bd75Srobert DebugLoc DL;
442*d415bd75Srobert if (I != MBB.end())
443*d415bd75Srobert DL = I->getDebugLoc();
444*d415bd75Srobert
445*d415bd75Srobert MachineFunction &MF = *MBB.getParent();
446*d415bd75Srobert CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
447*d415bd75Srobert MachineFrameInfo &MFI = MF.getFrameInfo();
448*d415bd75Srobert
449*d415bd75Srobert unsigned Opcode = 0;
450*d415bd75Srobert
451*d415bd75Srobert if (CSKY::GPRRegClass.hasSubClassEq(RC)) {
452*d415bd75Srobert Opcode = CSKY::LD32W;
453*d415bd75Srobert } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) {
454*d415bd75Srobert Opcode = CSKY::RESTORE_CARRY;
455*d415bd75Srobert CFI->setSpillsCR();
456*d415bd75Srobert } else if (v2sf && CSKY::sFPR32RegClass.hasSubClassEq(RC))
457*d415bd75Srobert Opcode = CSKY::FLD_S;
458*d415bd75Srobert else if (v2df && CSKY::sFPR64RegClass.hasSubClassEq(RC))
459*d415bd75Srobert Opcode = CSKY::FLD_D;
460*d415bd75Srobert else if (v3sf && CSKY::FPR32RegClass.hasSubClassEq(RC))
461*d415bd75Srobert Opcode = CSKY::f2FLD_S;
462*d415bd75Srobert else if (v3df && CSKY::FPR64RegClass.hasSubClassEq(RC))
463*d415bd75Srobert Opcode = CSKY::f2FLD_D;
464*d415bd75Srobert else {
465*d415bd75Srobert llvm_unreachable("Unknown RegisterClass");
466*d415bd75Srobert }
467*d415bd75Srobert
468*d415bd75Srobert MachineMemOperand *MMO = MF.getMachineMemOperand(
469*d415bd75Srobert MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,
470*d415bd75Srobert MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
471*d415bd75Srobert
472*d415bd75Srobert BuildMI(MBB, I, DL, get(Opcode), DestReg)
473*d415bd75Srobert .addFrameIndex(FI)
474*d415bd75Srobert .addImm(0)
475*d415bd75Srobert .addMemOperand(MMO);
476*d415bd75Srobert }
477*d415bd75Srobert
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,const DebugLoc & DL,MCRegister DestReg,MCRegister SrcReg,bool KillSrc) const478*d415bd75Srobert void CSKYInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
479*d415bd75Srobert MachineBasicBlock::iterator I,
480*d415bd75Srobert const DebugLoc &DL, MCRegister DestReg,
481*d415bd75Srobert MCRegister SrcReg, bool KillSrc) const {
482*d415bd75Srobert if (CSKY::GPRRegClass.contains(SrcReg) &&
483*d415bd75Srobert CSKY::CARRYRegClass.contains(DestReg)) {
484*d415bd75Srobert if (STI.hasE2()) {
485*d415bd75Srobert BuildMI(MBB, I, DL, get(CSKY::BTSTI32), DestReg)
486*d415bd75Srobert .addReg(SrcReg, getKillRegState(KillSrc))
487*d415bd75Srobert .addImm(0);
488*d415bd75Srobert } else {
489*d415bd75Srobert assert(SrcReg < CSKY::R8);
490*d415bd75Srobert BuildMI(MBB, I, DL, get(CSKY::BTSTI16), DestReg)
491*d415bd75Srobert .addReg(SrcReg, getKillRegState(KillSrc))
492*d415bd75Srobert .addImm(0);
493*d415bd75Srobert }
494*d415bd75Srobert return;
495*d415bd75Srobert }
496*d415bd75Srobert
497*d415bd75Srobert if (CSKY::CARRYRegClass.contains(SrcReg) &&
498*d415bd75Srobert CSKY::GPRRegClass.contains(DestReg)) {
499*d415bd75Srobert
500*d415bd75Srobert if (STI.hasE2()) {
501*d415bd75Srobert BuildMI(MBB, I, DL, get(CSKY::MVC32), DestReg)
502*d415bd75Srobert .addReg(SrcReg, getKillRegState(KillSrc));
503*d415bd75Srobert } else {
504*d415bd75Srobert assert(DestReg < CSKY::R16);
505*d415bd75Srobert assert(DestReg < CSKY::R8);
506*d415bd75Srobert BuildMI(MBB, I, DL, get(CSKY::MOVI16), DestReg).addImm(0);
507*d415bd75Srobert BuildMI(MBB, I, DL, get(CSKY::ADDC16))
508*d415bd75Srobert .addReg(DestReg, RegState::Define)
509*d415bd75Srobert .addReg(SrcReg, RegState::Define)
510*d415bd75Srobert .addReg(DestReg, getKillRegState(true))
511*d415bd75Srobert .addReg(DestReg, getKillRegState(true))
512*d415bd75Srobert .addReg(SrcReg, getKillRegState(true));
513*d415bd75Srobert BuildMI(MBB, I, DL, get(CSKY::BTSTI16))
514*d415bd75Srobert .addReg(SrcReg, RegState::Define | getDeadRegState(KillSrc))
515*d415bd75Srobert .addReg(DestReg)
516*d415bd75Srobert .addImm(0);
517*d415bd75Srobert }
518*d415bd75Srobert return;
519*d415bd75Srobert }
520*d415bd75Srobert
521*d415bd75Srobert unsigned Opcode = 0;
522*d415bd75Srobert if (CSKY::GPRRegClass.contains(DestReg, SrcReg))
523*d415bd75Srobert Opcode = STI.hasE2() ? CSKY::MOV32 : CSKY::MOV16;
524*d415bd75Srobert else if (v2sf && CSKY::sFPR32RegClass.contains(DestReg, SrcReg))
525*d415bd75Srobert Opcode = CSKY::FMOV_S;
526*d415bd75Srobert else if (v3sf && CSKY::FPR32RegClass.contains(DestReg, SrcReg))
527*d415bd75Srobert Opcode = CSKY::f2FMOV_S;
528*d415bd75Srobert else if (v2df && CSKY::sFPR64RegClass.contains(DestReg, SrcReg))
529*d415bd75Srobert Opcode = CSKY::FMOV_D;
530*d415bd75Srobert else if (v3df && CSKY::FPR64RegClass.contains(DestReg, SrcReg))
531*d415bd75Srobert Opcode = CSKY::f2FMOV_D;
532*d415bd75Srobert else if (v2sf && CSKY::sFPR32RegClass.contains(SrcReg) &&
533*d415bd75Srobert CSKY::GPRRegClass.contains(DestReg))
534*d415bd75Srobert Opcode = CSKY::FMFVRL;
535*d415bd75Srobert else if (v3sf && CSKY::FPR32RegClass.contains(SrcReg) &&
536*d415bd75Srobert CSKY::GPRRegClass.contains(DestReg))
537*d415bd75Srobert Opcode = CSKY::f2FMFVRL;
538*d415bd75Srobert else if (v2df && CSKY::sFPR64RegClass.contains(SrcReg) &&
539*d415bd75Srobert CSKY::GPRRegClass.contains(DestReg))
540*d415bd75Srobert Opcode = CSKY::FMFVRL_D;
541*d415bd75Srobert else if (v3df && CSKY::FPR64RegClass.contains(SrcReg) &&
542*d415bd75Srobert CSKY::GPRRegClass.contains(DestReg))
543*d415bd75Srobert Opcode = CSKY::f2FMFVRL_D;
544*d415bd75Srobert else if (v2sf && CSKY::GPRRegClass.contains(SrcReg) &&
545*d415bd75Srobert CSKY::sFPR32RegClass.contains(DestReg))
546*d415bd75Srobert Opcode = CSKY::FMTVRL;
547*d415bd75Srobert else if (v3sf && CSKY::GPRRegClass.contains(SrcReg) &&
548*d415bd75Srobert CSKY::FPR32RegClass.contains(DestReg))
549*d415bd75Srobert Opcode = CSKY::f2FMTVRL;
550*d415bd75Srobert else if (v2df && CSKY::GPRRegClass.contains(SrcReg) &&
551*d415bd75Srobert CSKY::sFPR64RegClass.contains(DestReg))
552*d415bd75Srobert Opcode = CSKY::FMTVRL_D;
553*d415bd75Srobert else if (v3df && CSKY::GPRRegClass.contains(SrcReg) &&
554*d415bd75Srobert CSKY::FPR64RegClass.contains(DestReg))
555*d415bd75Srobert Opcode = CSKY::f2FMTVRL_D;
556*d415bd75Srobert else {
557*d415bd75Srobert LLVM_DEBUG(dbgs() << "src = " << SrcReg << ", dst = " << DestReg);
558*d415bd75Srobert LLVM_DEBUG(I->dump());
559*d415bd75Srobert llvm_unreachable("Unknown RegisterClass");
560*d415bd75Srobert }
561*d415bd75Srobert
562*d415bd75Srobert BuildMI(MBB, I, DL, get(Opcode), DestReg)
563*d415bd75Srobert .addReg(SrcReg, getKillRegState(KillSrc));
564*d415bd75Srobert }
565*d415bd75Srobert
getGlobalBaseReg(MachineFunction & MF) const566*d415bd75Srobert Register CSKYInstrInfo::getGlobalBaseReg(MachineFunction &MF) const {
567*d415bd75Srobert CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
568*d415bd75Srobert MachineConstantPool *MCP = MF.getConstantPool();
569*d415bd75Srobert MachineRegisterInfo &MRI = MF.getRegInfo();
570*d415bd75Srobert
571*d415bd75Srobert Register GlobalBaseReg = CFI->getGlobalBaseReg();
572*d415bd75Srobert if (GlobalBaseReg != 0)
573*d415bd75Srobert return GlobalBaseReg;
574*d415bd75Srobert
575*d415bd75Srobert // Insert a pseudo instruction to set the GlobalBaseReg into the first
576*d415bd75Srobert // MBB of the function
577*d415bd75Srobert MachineBasicBlock &FirstMBB = MF.front();
578*d415bd75Srobert MachineBasicBlock::iterator MBBI = FirstMBB.begin();
579*d415bd75Srobert DebugLoc DL;
580*d415bd75Srobert
581*d415bd75Srobert CSKYConstantPoolValue *CPV = CSKYConstantPoolSymbol::Create(
582*d415bd75Srobert Type::getInt32Ty(MF.getFunction().getContext()), "_GLOBAL_OFFSET_TABLE_",
583*d415bd75Srobert 0, CSKYCP::ADDR);
584*d415bd75Srobert
585*d415bd75Srobert unsigned CPI = MCP->getConstantPoolIndex(CPV, Align(4));
586*d415bd75Srobert
587*d415bd75Srobert MachineMemOperand *MO =
588*d415bd75Srobert MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
589*d415bd75Srobert MachineMemOperand::MOLoad, 4, Align(4));
590*d415bd75Srobert BuildMI(FirstMBB, MBBI, DL, get(CSKY::LRW32), CSKY::R28)
591*d415bd75Srobert .addConstantPoolIndex(CPI)
592*d415bd75Srobert .addMemOperand(MO);
593*d415bd75Srobert
594*d415bd75Srobert GlobalBaseReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);
595*d415bd75Srobert BuildMI(FirstMBB, MBBI, DL, get(TargetOpcode::COPY), GlobalBaseReg)
596*d415bd75Srobert .addReg(CSKY::R28);
597*d415bd75Srobert
598*d415bd75Srobert CFI->setGlobalBaseReg(GlobalBaseReg);
599*d415bd75Srobert return GlobalBaseReg;
600*d415bd75Srobert }
601*d415bd75Srobert
getInstSizeInBytes(const MachineInstr & MI) const602*d415bd75Srobert unsigned CSKYInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
603*d415bd75Srobert switch (MI.getOpcode()) {
604*d415bd75Srobert default:
605*d415bd75Srobert return MI.getDesc().getSize();
606*d415bd75Srobert case CSKY::CONSTPOOL_ENTRY:
607*d415bd75Srobert return MI.getOperand(2).getImm();
608*d415bd75Srobert case CSKY::SPILL_CARRY:
609*d415bd75Srobert case CSKY::RESTORE_CARRY:
610*d415bd75Srobert case CSKY::PseudoTLSLA32:
611*d415bd75Srobert return 8;
612*d415bd75Srobert case TargetOpcode::INLINEASM_BR:
613*d415bd75Srobert case TargetOpcode::INLINEASM: {
614*d415bd75Srobert const MachineFunction *MF = MI.getParent()->getParent();
615*d415bd75Srobert const char *AsmStr = MI.getOperand(0).getSymbolName();
616*d415bd75Srobert return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
617*d415bd75Srobert }
618*d415bd75Srobert }
619*d415bd75Srobert }
620