1dff0c46cSDimitry Andric //===-- XCoreInstrInfo.cpp - XCore Instruction Information ----------------===//
2f22ef01cSRoman Divacky //
3f22ef01cSRoman Divacky // The LLVM Compiler Infrastructure
4f22ef01cSRoman Divacky //
5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source
6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details.
7f22ef01cSRoman Divacky //
8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
9f22ef01cSRoman Divacky //
10f22ef01cSRoman Divacky // This file contains the XCore implementation of the TargetInstrInfo class.
11f22ef01cSRoman Divacky //
12f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
13f22ef01cSRoman Divacky
14f22ef01cSRoman Divacky #include "XCoreInstrInfo.h"
15f22ef01cSRoman Divacky #include "XCore.h"
16139f7f9bSDimitry Andric #include "XCoreMachineFunctionInfo.h"
17f22ef01cSRoman Divacky #include "llvm/ADT/STLExtras.h"
1891bc56edSDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
19139f7f9bSDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
20139f7f9bSDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
2191bc56edSDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
2291bc56edSDimitry Andric #include "llvm/IR/Constants.h"
2391bc56edSDimitry Andric #include "llvm/IR/Function.h"
24139f7f9bSDimitry Andric #include "llvm/MC/MCContext.h"
25f22ef01cSRoman Divacky #include "llvm/Support/Debug.h"
26f22ef01cSRoman Divacky #include "llvm/Support/ErrorHandling.h"
276122f3e6SDimitry Andric #include "llvm/Support/TargetRegistry.h"
28f22ef01cSRoman Divacky
2991bc56edSDimitry Andric using namespace llvm;
3091bc56edSDimitry Andric
31f785676fSDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
3217a519f9SDimitry Andric #include "XCoreGenInstrInfo.inc"
3317a519f9SDimitry Andric
34f22ef01cSRoman Divacky namespace llvm {
35f22ef01cSRoman Divacky namespace XCore {
36f22ef01cSRoman Divacky
37f22ef01cSRoman Divacky // XCore Condition Codes
38f22ef01cSRoman Divacky enum CondCode {
39f22ef01cSRoman Divacky COND_TRUE,
40f22ef01cSRoman Divacky COND_FALSE,
41f22ef01cSRoman Divacky COND_INVALID
42f22ef01cSRoman Divacky };
43f22ef01cSRoman Divacky }
443dac3a9bSDimitry Andric }
45f22ef01cSRoman Divacky
46f785676fSDimitry Andric // Pin the vtable to this file.
anchor()47f785676fSDimitry Andric void XCoreInstrInfo::anchor() {}
48f785676fSDimitry Andric
XCoreInstrInfo()49f22ef01cSRoman Divacky XCoreInstrInfo::XCoreInstrInfo()
5017a519f9SDimitry Andric : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP),
51f785676fSDimitry Andric RI() {
52f22ef01cSRoman Divacky }
53f22ef01cSRoman Divacky
isZeroImm(const MachineOperand & op)54f22ef01cSRoman Divacky static bool isZeroImm(const MachineOperand &op) {
55f22ef01cSRoman Divacky return op.isImm() && op.getImm() == 0;
56f22ef01cSRoman Divacky }
57f22ef01cSRoman Divacky
58f22ef01cSRoman Divacky /// isLoadFromStackSlot - If the specified machine instruction is a direct
59f22ef01cSRoman Divacky /// load from a stack slot, return the virtual or physical register number of
60f22ef01cSRoman Divacky /// the destination along with the FrameIndex of the loaded stack slot. If
61f22ef01cSRoman Divacky /// not, return 0. This predicate must return 0 if the instruction has
62f22ef01cSRoman Divacky /// any side effects other than loading from the stack slot.
isLoadFromStackSlot(const MachineInstr & MI,int & FrameIndex) const633ca95b02SDimitry Andric unsigned XCoreInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
643ca95b02SDimitry Andric int &FrameIndex) const {
653ca95b02SDimitry Andric int Opcode = MI.getOpcode();
66f22ef01cSRoman Divacky if (Opcode == XCore::LDWFI)
67f22ef01cSRoman Divacky {
683ca95b02SDimitry Andric if ((MI.getOperand(1).isFI()) && // is a stack slot
693ca95b02SDimitry Andric (MI.getOperand(2).isImm()) && // the imm is zero
703ca95b02SDimitry Andric (isZeroImm(MI.getOperand(2)))) {
713ca95b02SDimitry Andric FrameIndex = MI.getOperand(1).getIndex();
723ca95b02SDimitry Andric return MI.getOperand(0).getReg();
73f22ef01cSRoman Divacky }
74f22ef01cSRoman Divacky }
75f22ef01cSRoman Divacky return 0;
76f22ef01cSRoman Divacky }
77f22ef01cSRoman Divacky
78f22ef01cSRoman Divacky /// isStoreToStackSlot - If the specified machine instruction is a direct
79f22ef01cSRoman Divacky /// store to a stack slot, return the virtual or physical register number of
80f22ef01cSRoman Divacky /// the source reg along with the FrameIndex of the loaded stack slot. If
81f22ef01cSRoman Divacky /// not, return 0. This predicate must return 0 if the instruction has
82f22ef01cSRoman Divacky /// any side effects other than storing to the stack slot.
isStoreToStackSlot(const MachineInstr & MI,int & FrameIndex) const833ca95b02SDimitry Andric unsigned XCoreInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
84f22ef01cSRoman Divacky int &FrameIndex) const {
853ca95b02SDimitry Andric int Opcode = MI.getOpcode();
86f22ef01cSRoman Divacky if (Opcode == XCore::STWFI)
87f22ef01cSRoman Divacky {
883ca95b02SDimitry Andric if ((MI.getOperand(1).isFI()) && // is a stack slot
893ca95b02SDimitry Andric (MI.getOperand(2).isImm()) && // the imm is zero
903ca95b02SDimitry Andric (isZeroImm(MI.getOperand(2)))) {
913ca95b02SDimitry Andric FrameIndex = MI.getOperand(1).getIndex();
923ca95b02SDimitry Andric return MI.getOperand(0).getReg();
93f22ef01cSRoman Divacky }
94f22ef01cSRoman Divacky }
95f22ef01cSRoman Divacky return 0;
96f22ef01cSRoman Divacky }
97f22ef01cSRoman Divacky
98f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
99f22ef01cSRoman Divacky // Branch Analysis
100f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
101f22ef01cSRoman Divacky
IsBRU(unsigned BrOpc)102f22ef01cSRoman Divacky static inline bool IsBRU(unsigned BrOpc) {
103f22ef01cSRoman Divacky return BrOpc == XCore::BRFU_u6
104f22ef01cSRoman Divacky || BrOpc == XCore::BRFU_lu6
105f22ef01cSRoman Divacky || BrOpc == XCore::BRBU_u6
106f22ef01cSRoman Divacky || BrOpc == XCore::BRBU_lu6;
107f22ef01cSRoman Divacky }
108f22ef01cSRoman Divacky
IsBRT(unsigned BrOpc)109f22ef01cSRoman Divacky static inline bool IsBRT(unsigned BrOpc) {
110f22ef01cSRoman Divacky return BrOpc == XCore::BRFT_ru6
111f22ef01cSRoman Divacky || BrOpc == XCore::BRFT_lru6
112f22ef01cSRoman Divacky || BrOpc == XCore::BRBT_ru6
113f22ef01cSRoman Divacky || BrOpc == XCore::BRBT_lru6;
114f22ef01cSRoman Divacky }
115f22ef01cSRoman Divacky
IsBRF(unsigned BrOpc)116f22ef01cSRoman Divacky static inline bool IsBRF(unsigned BrOpc) {
117f22ef01cSRoman Divacky return BrOpc == XCore::BRFF_ru6
118f22ef01cSRoman Divacky || BrOpc == XCore::BRFF_lru6
119f22ef01cSRoman Divacky || BrOpc == XCore::BRBF_ru6
120f22ef01cSRoman Divacky || BrOpc == XCore::BRBF_lru6;
121f22ef01cSRoman Divacky }
122f22ef01cSRoman Divacky
IsCondBranch(unsigned BrOpc)123f22ef01cSRoman Divacky static inline bool IsCondBranch(unsigned BrOpc) {
124f22ef01cSRoman Divacky return IsBRF(BrOpc) || IsBRT(BrOpc);
125f22ef01cSRoman Divacky }
126f22ef01cSRoman Divacky
IsBR_JT(unsigned BrOpc)127f22ef01cSRoman Divacky static inline bool IsBR_JT(unsigned BrOpc) {
128f22ef01cSRoman Divacky return BrOpc == XCore::BR_JT
129f22ef01cSRoman Divacky || BrOpc == XCore::BR_JT32;
130f22ef01cSRoman Divacky }
131f22ef01cSRoman Divacky
132f22ef01cSRoman Divacky /// GetCondFromBranchOpc - Return the XCore CC that matches
133f22ef01cSRoman Divacky /// the correspondent Branch instruction opcode.
GetCondFromBranchOpc(unsigned BrOpc)134f22ef01cSRoman Divacky static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc)
135f22ef01cSRoman Divacky {
136f22ef01cSRoman Divacky if (IsBRT(BrOpc)) {
137f22ef01cSRoman Divacky return XCore::COND_TRUE;
138f22ef01cSRoman Divacky } else if (IsBRF(BrOpc)) {
139f22ef01cSRoman Divacky return XCore::COND_FALSE;
140f22ef01cSRoman Divacky } else {
141f22ef01cSRoman Divacky return XCore::COND_INVALID;
142f22ef01cSRoman Divacky }
143f22ef01cSRoman Divacky }
144f22ef01cSRoman Divacky
145f22ef01cSRoman Divacky /// GetCondBranchFromCond - Return the Branch instruction
146f22ef01cSRoman Divacky /// opcode that matches the cc.
GetCondBranchFromCond(XCore::CondCode CC)147f22ef01cSRoman Divacky static inline unsigned GetCondBranchFromCond(XCore::CondCode CC)
148f22ef01cSRoman Divacky {
149f22ef01cSRoman Divacky switch (CC) {
150f22ef01cSRoman Divacky default: llvm_unreachable("Illegal condition code!");
151f22ef01cSRoman Divacky case XCore::COND_TRUE : return XCore::BRFT_lru6;
152f22ef01cSRoman Divacky case XCore::COND_FALSE : return XCore::BRFF_lru6;
153f22ef01cSRoman Divacky }
154f22ef01cSRoman Divacky }
155f22ef01cSRoman Divacky
156f22ef01cSRoman Divacky /// GetOppositeBranchCondition - Return the inverse of the specified
157f22ef01cSRoman Divacky /// condition, e.g. turning COND_E to COND_NE.
GetOppositeBranchCondition(XCore::CondCode CC)158f22ef01cSRoman Divacky static inline XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC)
159f22ef01cSRoman Divacky {
160f22ef01cSRoman Divacky switch (CC) {
161f22ef01cSRoman Divacky default: llvm_unreachable("Illegal condition code!");
162f22ef01cSRoman Divacky case XCore::COND_TRUE : return XCore::COND_FALSE;
163f22ef01cSRoman Divacky case XCore::COND_FALSE : return XCore::COND_TRUE;
164f22ef01cSRoman Divacky }
165f22ef01cSRoman Divacky }
166f22ef01cSRoman Divacky
167f22ef01cSRoman Divacky /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
168f22ef01cSRoman Divacky /// true if it cannot be understood (e.g. it's a switch dispatch or isn't
169f22ef01cSRoman Divacky /// implemented for a target). Upon success, this returns false and returns
170f22ef01cSRoman Divacky /// with the following information in various cases:
171f22ef01cSRoman Divacky ///
172f22ef01cSRoman Divacky /// 1. If this block ends with no branches (it just falls through to its succ)
173f22ef01cSRoman Divacky /// just return false, leaving TBB/FBB null.
174f22ef01cSRoman Divacky /// 2. If this block ends with only an unconditional branch, it sets TBB to be
175f22ef01cSRoman Divacky /// the destination block.
176f22ef01cSRoman Divacky /// 3. If this block ends with an conditional branch and it falls through to
177f22ef01cSRoman Divacky /// an successor block, it sets TBB to be the branch destination block and a
178f22ef01cSRoman Divacky /// list of operands that evaluate the condition. These
179f22ef01cSRoman Divacky /// operands can be passed to other TargetInstrInfo methods to create new
180f22ef01cSRoman Divacky /// branches.
181f22ef01cSRoman Divacky /// 4. If this block ends with an conditional branch and an unconditional
182f22ef01cSRoman Divacky /// block, it returns the 'true' destination in TBB, the 'false' destination
183f22ef01cSRoman Divacky /// in FBB, and a list of operands that evaluate the condition. These
184f22ef01cSRoman Divacky /// operands can be passed to other TargetInstrInfo methods to create new
185f22ef01cSRoman Divacky /// branches.
186f22ef01cSRoman Divacky ///
187d88c1a5aSDimitry Andric /// Note that removeBranch and insertBranch must be implemented to support
188f22ef01cSRoman Divacky /// cases where this method returns success.
189f22ef01cSRoman Divacky ///
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const1903ca95b02SDimitry Andric bool XCoreInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
1913ca95b02SDimitry Andric MachineBasicBlock *&TBB,
192f22ef01cSRoman Divacky MachineBasicBlock *&FBB,
193f22ef01cSRoman Divacky SmallVectorImpl<MachineOperand> &Cond,
194f22ef01cSRoman Divacky bool AllowModify) const {
195f22ef01cSRoman Divacky // If the block has no terminators, it just falls into the block after it.
1963dac3a9bSDimitry Andric MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
1973dac3a9bSDimitry Andric if (I == MBB.end())
198f22ef01cSRoman Divacky return false;
1993dac3a9bSDimitry Andric
2003ca95b02SDimitry Andric if (!isUnpredicatedTerminator(*I))
201f22ef01cSRoman Divacky return false;
202f22ef01cSRoman Divacky
203f22ef01cSRoman Divacky // Get the last instruction in the block.
204d88c1a5aSDimitry Andric MachineInstr *LastInst = &*I;
205f22ef01cSRoman Divacky
206f22ef01cSRoman Divacky // If there is only one terminator instruction, process it.
2073ca95b02SDimitry Andric if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
208f22ef01cSRoman Divacky if (IsBRU(LastInst->getOpcode())) {
209f22ef01cSRoman Divacky TBB = LastInst->getOperand(0).getMBB();
210f22ef01cSRoman Divacky return false;
211f22ef01cSRoman Divacky }
212f22ef01cSRoman Divacky
213f22ef01cSRoman Divacky XCore::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode());
214f22ef01cSRoman Divacky if (BranchCode == XCore::COND_INVALID)
215f22ef01cSRoman Divacky return true; // Can't handle indirect branch.
216f22ef01cSRoman Divacky
217f22ef01cSRoman Divacky // Conditional branch
218f22ef01cSRoman Divacky // Block ends with fall-through condbranch.
219f22ef01cSRoman Divacky
220f22ef01cSRoman Divacky TBB = LastInst->getOperand(1).getMBB();
221f22ef01cSRoman Divacky Cond.push_back(MachineOperand::CreateImm(BranchCode));
222f22ef01cSRoman Divacky Cond.push_back(LastInst->getOperand(0));
223f22ef01cSRoman Divacky return false;
224f22ef01cSRoman Divacky }
225f22ef01cSRoman Divacky
226f22ef01cSRoman Divacky // Get the instruction before it if it's a terminator.
227d88c1a5aSDimitry Andric MachineInstr *SecondLastInst = &*I;
228f22ef01cSRoman Divacky
229f22ef01cSRoman Divacky // If there are three terminators, we don't know what sort of block this is.
2303ca95b02SDimitry Andric if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))
231f22ef01cSRoman Divacky return true;
232f22ef01cSRoman Divacky
233f22ef01cSRoman Divacky unsigned SecondLastOpc = SecondLastInst->getOpcode();
234f22ef01cSRoman Divacky XCore::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc);
235f22ef01cSRoman Divacky
236f22ef01cSRoman Divacky // If the block ends with conditional branch followed by unconditional,
237f22ef01cSRoman Divacky // handle it.
238f22ef01cSRoman Divacky if (BranchCode != XCore::COND_INVALID
239f22ef01cSRoman Divacky && IsBRU(LastInst->getOpcode())) {
240f22ef01cSRoman Divacky
241f22ef01cSRoman Divacky TBB = SecondLastInst->getOperand(1).getMBB();
242f22ef01cSRoman Divacky Cond.push_back(MachineOperand::CreateImm(BranchCode));
243f22ef01cSRoman Divacky Cond.push_back(SecondLastInst->getOperand(0));
244f22ef01cSRoman Divacky
245f22ef01cSRoman Divacky FBB = LastInst->getOperand(0).getMBB();
246f22ef01cSRoman Divacky return false;
247f22ef01cSRoman Divacky }
248f22ef01cSRoman Divacky
249f22ef01cSRoman Divacky // If the block ends with two unconditional branches, handle it. The second
250f22ef01cSRoman Divacky // one is not executed, so remove it.
251f22ef01cSRoman Divacky if (IsBRU(SecondLastInst->getOpcode()) &&
252f22ef01cSRoman Divacky IsBRU(LastInst->getOpcode())) {
253f22ef01cSRoman Divacky TBB = SecondLastInst->getOperand(0).getMBB();
254f22ef01cSRoman Divacky I = LastInst;
255f22ef01cSRoman Divacky if (AllowModify)
256f22ef01cSRoman Divacky I->eraseFromParent();
257f22ef01cSRoman Divacky return false;
258f22ef01cSRoman Divacky }
259f22ef01cSRoman Divacky
260f22ef01cSRoman Divacky // Likewise if it ends with a branch table followed by an unconditional branch.
261f22ef01cSRoman Divacky if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) {
262f22ef01cSRoman Divacky I = LastInst;
263f22ef01cSRoman Divacky if (AllowModify)
264f22ef01cSRoman Divacky I->eraseFromParent();
265f22ef01cSRoman Divacky return true;
266f22ef01cSRoman Divacky }
267f22ef01cSRoman Divacky
268f22ef01cSRoman Divacky // Otherwise, can't handle this.
269f22ef01cSRoman Divacky return true;
270f22ef01cSRoman Divacky }
271f22ef01cSRoman Divacky
insertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL,int * BytesAdded) const272d88c1a5aSDimitry Andric unsigned XCoreInstrInfo::insertBranch(MachineBasicBlock &MBB,
2733ca95b02SDimitry Andric MachineBasicBlock *TBB,
274f22ef01cSRoman Divacky MachineBasicBlock *FBB,
2758f0fd8f6SDimitry Andric ArrayRef<MachineOperand> Cond,
276d88c1a5aSDimitry Andric const DebugLoc &DL,
277d88c1a5aSDimitry Andric int *BytesAdded) const {
278f22ef01cSRoman Divacky // Shouldn't be a fall through.
279d88c1a5aSDimitry Andric assert(TBB && "insertBranch must not be told to insert a fallthrough");
280f22ef01cSRoman Divacky assert((Cond.size() == 2 || Cond.size() == 0) &&
281f22ef01cSRoman Divacky "Unexpected number of components!");
282d88c1a5aSDimitry Andric assert(!BytesAdded && "code size not handled");
283f22ef01cSRoman Divacky
28491bc56edSDimitry Andric if (!FBB) { // One way branch.
285f22ef01cSRoman Divacky if (Cond.empty()) {
286f22ef01cSRoman Divacky // Unconditional branch
287ffd1746dSEd Schouten BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(TBB);
288f22ef01cSRoman Divacky } else {
289f22ef01cSRoman Divacky // Conditional branch.
290f22ef01cSRoman Divacky unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
291ffd1746dSEd Schouten BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
292f22ef01cSRoman Divacky .addMBB(TBB);
293f22ef01cSRoman Divacky }
294f22ef01cSRoman Divacky return 1;
295f22ef01cSRoman Divacky }
296f22ef01cSRoman Divacky
297f22ef01cSRoman Divacky // Two-way Conditional branch.
298f22ef01cSRoman Divacky assert(Cond.size() == 2 && "Unexpected number of components!");
299f22ef01cSRoman Divacky unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
300ffd1746dSEd Schouten BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
301f22ef01cSRoman Divacky .addMBB(TBB);
302ffd1746dSEd Schouten BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(FBB);
303f22ef01cSRoman Divacky return 2;
304f22ef01cSRoman Divacky }
305f22ef01cSRoman Divacky
306f22ef01cSRoman Divacky unsigned
removeBranch(MachineBasicBlock & MBB,int * BytesRemoved) const307d88c1a5aSDimitry Andric XCoreInstrInfo::removeBranch(MachineBasicBlock &MBB, int *BytesRemoved) const {
308d88c1a5aSDimitry Andric assert(!BytesRemoved && "code size not handled");
309d88c1a5aSDimitry Andric
3103dac3a9bSDimitry Andric MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
3113dac3a9bSDimitry Andric if (I == MBB.end())
312f22ef01cSRoman Divacky return 0;
3133dac3a9bSDimitry Andric
314f22ef01cSRoman Divacky if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode()))
315f22ef01cSRoman Divacky return 0;
316f22ef01cSRoman Divacky
317f22ef01cSRoman Divacky // Remove the branch.
318f22ef01cSRoman Divacky I->eraseFromParent();
319f22ef01cSRoman Divacky
320f22ef01cSRoman Divacky I = MBB.end();
321f22ef01cSRoman Divacky
322f22ef01cSRoman Divacky if (I == MBB.begin()) return 1;
323f22ef01cSRoman Divacky --I;
324f22ef01cSRoman Divacky if (!IsCondBranch(I->getOpcode()))
325f22ef01cSRoman Divacky return 1;
326f22ef01cSRoman Divacky
327f22ef01cSRoman Divacky // Remove the branch.
328f22ef01cSRoman Divacky I->eraseFromParent();
329f22ef01cSRoman Divacky return 2;
330f22ef01cSRoman Divacky }
331f22ef01cSRoman Divacky
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,const DebugLoc & DL,unsigned DestReg,unsigned SrcReg,bool KillSrc) const332ffd1746dSEd Schouten void XCoreInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
3333ca95b02SDimitry Andric MachineBasicBlock::iterator I,
3343ca95b02SDimitry Andric const DebugLoc &DL, unsigned DestReg,
3353ca95b02SDimitry Andric unsigned SrcReg, bool KillSrc) const {
336ffd1746dSEd Schouten bool GRDest = XCore::GRRegsRegClass.contains(DestReg);
337ffd1746dSEd Schouten bool GRSrc = XCore::GRRegsRegClass.contains(SrcReg);
338f22ef01cSRoman Divacky
339ffd1746dSEd Schouten if (GRDest && GRSrc) {
340f22ef01cSRoman Divacky BuildMI(MBB, I, DL, get(XCore::ADD_2rus), DestReg)
341ffd1746dSEd Schouten .addReg(SrcReg, getKillRegState(KillSrc))
342f22ef01cSRoman Divacky .addImm(0);
343ffd1746dSEd Schouten return;
344f22ef01cSRoman Divacky }
345f22ef01cSRoman Divacky
346ffd1746dSEd Schouten if (GRDest && SrcReg == XCore::SP) {
347ffd1746dSEd Schouten BuildMI(MBB, I, DL, get(XCore::LDAWSP_ru6), DestReg).addImm(0);
348ffd1746dSEd Schouten return;
349f22ef01cSRoman Divacky }
350ffd1746dSEd Schouten
351ffd1746dSEd Schouten if (DestReg == XCore::SP && GRSrc) {
352f22ef01cSRoman Divacky BuildMI(MBB, I, DL, get(XCore::SETSP_1r))
353ffd1746dSEd Schouten .addReg(SrcReg, getKillRegState(KillSrc));
354ffd1746dSEd Schouten return;
355f22ef01cSRoman Divacky }
356ffd1746dSEd Schouten llvm_unreachable("Impossible reg-to-reg copy");
357f22ef01cSRoman Divacky }
358f22ef01cSRoman Divacky
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned SrcReg,bool isKill,int FrameIndex,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const359f22ef01cSRoman Divacky void XCoreInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
360f22ef01cSRoman Divacky MachineBasicBlock::iterator I,
361f22ef01cSRoman Divacky unsigned SrcReg, bool isKill,
362f22ef01cSRoman Divacky int FrameIndex,
363f22ef01cSRoman Divacky const TargetRegisterClass *RC,
364f22ef01cSRoman Divacky const TargetRegisterInfo *TRI) const
365f22ef01cSRoman Divacky {
366f22ef01cSRoman Divacky DebugLoc DL;
367*4ba319b5SDimitry Andric if (I != MBB.end() && !I->isDebugInstr())
36891bc56edSDimitry Andric DL = I->getDebugLoc();
36991bc56edSDimitry Andric MachineFunction *MF = MBB.getParent();
370d88c1a5aSDimitry Andric const MachineFrameInfo &MFI = MF->getFrameInfo();
3717d523365SDimitry Andric MachineMemOperand *MMO = MF->getMachineMemOperand(
3727d523365SDimitry Andric MachinePointerInfo::getFixedStack(*MF, FrameIndex),
3737d523365SDimitry Andric MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),
37491bc56edSDimitry Andric MFI.getObjectAlignment(FrameIndex));
375f22ef01cSRoman Divacky BuildMI(MBB, I, DL, get(XCore::STWFI))
376f22ef01cSRoman Divacky .addReg(SrcReg, getKillRegState(isKill))
377f22ef01cSRoman Divacky .addFrameIndex(FrameIndex)
37891bc56edSDimitry Andric .addImm(0)
37991bc56edSDimitry Andric .addMemOperand(MMO);
380f22ef01cSRoman Divacky }
381f22ef01cSRoman Divacky
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned DestReg,int FrameIndex,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const382f22ef01cSRoman Divacky void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
383f22ef01cSRoman Divacky MachineBasicBlock::iterator I,
384f22ef01cSRoman Divacky unsigned DestReg, int FrameIndex,
385f22ef01cSRoman Divacky const TargetRegisterClass *RC,
386f22ef01cSRoman Divacky const TargetRegisterInfo *TRI) const
387f22ef01cSRoman Divacky {
388f22ef01cSRoman Divacky DebugLoc DL;
389*4ba319b5SDimitry Andric if (I != MBB.end() && !I->isDebugInstr())
39091bc56edSDimitry Andric DL = I->getDebugLoc();
39191bc56edSDimitry Andric MachineFunction *MF = MBB.getParent();
392d88c1a5aSDimitry Andric const MachineFrameInfo &MFI = MF->getFrameInfo();
3937d523365SDimitry Andric MachineMemOperand *MMO = MF->getMachineMemOperand(
3947d523365SDimitry Andric MachinePointerInfo::getFixedStack(*MF, FrameIndex),
3957d523365SDimitry Andric MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
39691bc56edSDimitry Andric MFI.getObjectAlignment(FrameIndex));
397f22ef01cSRoman Divacky BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg)
398f22ef01cSRoman Divacky .addFrameIndex(FrameIndex)
39991bc56edSDimitry Andric .addImm(0)
40091bc56edSDimitry Andric .addMemOperand(MMO);
401f22ef01cSRoman Divacky }
402f22ef01cSRoman Divacky
403f22ef01cSRoman Divacky bool XCoreInstrInfo::
reverseBranchCondition(SmallVectorImpl<MachineOperand> & Cond) const404d88c1a5aSDimitry Andric reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
405f22ef01cSRoman Divacky assert((Cond.size() == 2) &&
406f22ef01cSRoman Divacky "Invalid XCore branch condition!");
407f22ef01cSRoman Divacky Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));
408f22ef01cSRoman Divacky return false;
409f22ef01cSRoman Divacky }
41091bc56edSDimitry Andric
isImmU6(unsigned val)41191bc56edSDimitry Andric static inline bool isImmU6(unsigned val) {
41291bc56edSDimitry Andric return val < (1 << 6);
41391bc56edSDimitry Andric }
41491bc56edSDimitry Andric
isImmU16(unsigned val)41591bc56edSDimitry Andric static inline bool isImmU16(unsigned val) {
41691bc56edSDimitry Andric return val < (1 << 16);
41791bc56edSDimitry Andric }
41891bc56edSDimitry Andric
isImmMskBitp(unsigned val)41991bc56edSDimitry Andric static bool isImmMskBitp(unsigned val) {
42091bc56edSDimitry Andric if (!isMask_32(val)) {
42191bc56edSDimitry Andric return false;
42291bc56edSDimitry Andric }
42391bc56edSDimitry Andric int N = Log2_32(val) + 1;
42491bc56edSDimitry Andric return (N >= 1 && N <= 8) || N == 16 || N == 24 || N == 32;
42591bc56edSDimitry Andric }
42691bc56edSDimitry Andric
loadImmediate(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,unsigned Reg,uint64_t Value) const42791bc56edSDimitry Andric MachineBasicBlock::iterator XCoreInstrInfo::loadImmediate(
42891bc56edSDimitry Andric MachineBasicBlock &MBB,
42991bc56edSDimitry Andric MachineBasicBlock::iterator MI,
43091bc56edSDimitry Andric unsigned Reg, uint64_t Value) const {
43191bc56edSDimitry Andric DebugLoc dl;
432*4ba319b5SDimitry Andric if (MI != MBB.end() && !MI->isDebugInstr())
43391bc56edSDimitry Andric dl = MI->getDebugLoc();
43491bc56edSDimitry Andric if (isImmMskBitp(Value)) {
43591bc56edSDimitry Andric int N = Log2_32(Value) + 1;
43639d628a0SDimitry Andric return BuildMI(MBB, MI, dl, get(XCore::MKMSK_rus), Reg)
43739d628a0SDimitry Andric .addImm(N)
43839d628a0SDimitry Andric .getInstr();
43991bc56edSDimitry Andric }
44091bc56edSDimitry Andric if (isImmU16(Value)) {
44191bc56edSDimitry Andric int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6;
44239d628a0SDimitry Andric return BuildMI(MBB, MI, dl, get(Opcode), Reg).addImm(Value).getInstr();
44391bc56edSDimitry Andric }
44491bc56edSDimitry Andric MachineConstantPool *ConstantPool = MBB.getParent()->getConstantPool();
44591bc56edSDimitry Andric const Constant *C = ConstantInt::get(
4462cab237bSDimitry Andric Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), Value);
44791bc56edSDimitry Andric unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
44891bc56edSDimitry Andric return BuildMI(MBB, MI, dl, get(XCore::LDWCP_lru6), Reg)
44939d628a0SDimitry Andric .addConstantPoolIndex(Idx)
45039d628a0SDimitry Andric .getInstr();
45191bc56edSDimitry Andric }
452