xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/M68k/M68kInstrInfo.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
104eeddc0SDimitry Andric //===-- M68kInstrInfo.cpp - M68k Instruction Information --------*- C++ -*-===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric ///
9fe6060f1SDimitry Andric /// \file
10fe6060f1SDimitry Andric /// This file contains the M68k declaration of the TargetInstrInfo class.
11fe6060f1SDimitry Andric ///
12fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
13fe6060f1SDimitry Andric 
14fe6060f1SDimitry Andric #include "M68kInstrInfo.h"
15fe6060f1SDimitry Andric 
16fe6060f1SDimitry Andric #include "M68kInstrBuilder.h"
17fe6060f1SDimitry Andric #include "M68kMachineFunction.h"
18fe6060f1SDimitry Andric #include "M68kTargetMachine.h"
19fe6060f1SDimitry Andric #include "MCTargetDesc/M68kMCCodeEmitter.h"
20fe6060f1SDimitry Andric 
21fe6060f1SDimitry Andric #include "llvm/ADT/STLExtras.h"
22fe6060f1SDimitry Andric #include "llvm/ADT/ScopeExit.h"
23fe6060f1SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h"
24fe6060f1SDimitry Andric #include "llvm/CodeGen/LiveVariables.h"
25fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
26fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
27349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
28fe6060f1SDimitry Andric #include "llvm/Support/ErrorHandling.h"
2981ad6265SDimitry Andric #include "llvm/Support/Regex.h"
30fe6060f1SDimitry Andric 
31fe6060f1SDimitry Andric #include <functional>
32fe6060f1SDimitry Andric 
33fe6060f1SDimitry Andric using namespace llvm;
34fe6060f1SDimitry Andric 
35fe6060f1SDimitry Andric #define DEBUG_TYPE "M68k-instr-info"
36fe6060f1SDimitry Andric 
37fe6060f1SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
38fe6060f1SDimitry Andric #include "M68kGenInstrInfo.inc"
39fe6060f1SDimitry Andric 
40fe6060f1SDimitry Andric // Pin the vtable to this file.
41fe6060f1SDimitry Andric void M68kInstrInfo::anchor() {}
42fe6060f1SDimitry Andric 
43fe6060f1SDimitry Andric M68kInstrInfo::M68kInstrInfo(const M68kSubtarget &STI)
44fe6060f1SDimitry Andric     : M68kGenInstrInfo(M68k::ADJCALLSTACKDOWN, M68k::ADJCALLSTACKUP, 0,
45fe6060f1SDimitry Andric                        M68k::RET),
46fe6060f1SDimitry Andric       Subtarget(STI), RI(STI) {}
47fe6060f1SDimitry Andric 
48fe6060f1SDimitry Andric static M68k::CondCode getCondFromBranchOpc(unsigned BrOpc) {
49fe6060f1SDimitry Andric   switch (BrOpc) {
50fe6060f1SDimitry Andric   default:
51fe6060f1SDimitry Andric     return M68k::COND_INVALID;
52fe6060f1SDimitry Andric   case M68k::Beq8:
53fe6060f1SDimitry Andric     return M68k::COND_EQ;
54fe6060f1SDimitry Andric   case M68k::Bne8:
55fe6060f1SDimitry Andric     return M68k::COND_NE;
56fe6060f1SDimitry Andric   case M68k::Blt8:
57fe6060f1SDimitry Andric     return M68k::COND_LT;
58fe6060f1SDimitry Andric   case M68k::Ble8:
59fe6060f1SDimitry Andric     return M68k::COND_LE;
60fe6060f1SDimitry Andric   case M68k::Bgt8:
61fe6060f1SDimitry Andric     return M68k::COND_GT;
62fe6060f1SDimitry Andric   case M68k::Bge8:
63fe6060f1SDimitry Andric     return M68k::COND_GE;
64fe6060f1SDimitry Andric   case M68k::Bcs8:
65fe6060f1SDimitry Andric     return M68k::COND_CS;
66fe6060f1SDimitry Andric   case M68k::Bls8:
67fe6060f1SDimitry Andric     return M68k::COND_LS;
68fe6060f1SDimitry Andric   case M68k::Bhi8:
69fe6060f1SDimitry Andric     return M68k::COND_HI;
70fe6060f1SDimitry Andric   case M68k::Bcc8:
71fe6060f1SDimitry Andric     return M68k::COND_CC;
72fe6060f1SDimitry Andric   case M68k::Bmi8:
73fe6060f1SDimitry Andric     return M68k::COND_MI;
74fe6060f1SDimitry Andric   case M68k::Bpl8:
75fe6060f1SDimitry Andric     return M68k::COND_PL;
76fe6060f1SDimitry Andric   case M68k::Bvs8:
77fe6060f1SDimitry Andric     return M68k::COND_VS;
78fe6060f1SDimitry Andric   case M68k::Bvc8:
79fe6060f1SDimitry Andric     return M68k::COND_VC;
80fe6060f1SDimitry Andric   }
81fe6060f1SDimitry Andric }
82fe6060f1SDimitry Andric 
83fe6060f1SDimitry Andric bool M68kInstrInfo::AnalyzeBranchImpl(MachineBasicBlock &MBB,
84fe6060f1SDimitry Andric                                       MachineBasicBlock *&TBB,
85fe6060f1SDimitry Andric                                       MachineBasicBlock *&FBB,
86fe6060f1SDimitry Andric                                       SmallVectorImpl<MachineOperand> &Cond,
87fe6060f1SDimitry Andric                                       bool AllowModify) const {
88fe6060f1SDimitry Andric 
89fe6060f1SDimitry Andric   auto UncondBranch =
90fe6060f1SDimitry Andric       std::pair<MachineBasicBlock::reverse_iterator, MachineBasicBlock *>{
91fe6060f1SDimitry Andric           MBB.rend(), nullptr};
92fe6060f1SDimitry Andric 
93fe6060f1SDimitry Andric   // Erase any instructions if allowed at the end of the scope.
94fe6060f1SDimitry Andric   std::vector<std::reference_wrapper<llvm::MachineInstr>> EraseList;
95fe6060f1SDimitry Andric   auto FinalizeOnReturn = llvm::make_scope_exit([&EraseList] {
96fe6060f1SDimitry Andric     std::for_each(EraseList.begin(), EraseList.end(),
97fe6060f1SDimitry Andric                   [](auto &ref) { ref.get().eraseFromParent(); });
98fe6060f1SDimitry Andric   });
99fe6060f1SDimitry Andric 
100fe6060f1SDimitry Andric   // Start from the bottom of the block and work up, examining the
101fe6060f1SDimitry Andric   // terminator instructions.
102fe6060f1SDimitry Andric   for (auto iter = MBB.rbegin(); iter != MBB.rend(); iter = std::next(iter)) {
103fe6060f1SDimitry Andric 
104fe6060f1SDimitry Andric     unsigned Opcode = iter->getOpcode();
105fe6060f1SDimitry Andric 
106fe6060f1SDimitry Andric     if (iter->isDebugInstr())
107fe6060f1SDimitry Andric       continue;
108fe6060f1SDimitry Andric 
109fe6060f1SDimitry Andric     // Working from the bottom, when we see a non-terminator instruction, we're
110fe6060f1SDimitry Andric     // done.
111fe6060f1SDimitry Andric     if (!isUnpredicatedTerminator(*iter))
112fe6060f1SDimitry Andric       break;
113fe6060f1SDimitry Andric 
114fe6060f1SDimitry Andric     // A terminator that isn't a branch can't easily be handled by this
115fe6060f1SDimitry Andric     // analysis.
116fe6060f1SDimitry Andric     if (!iter->isBranch())
117fe6060f1SDimitry Andric       return true;
118fe6060f1SDimitry Andric 
119fe6060f1SDimitry Andric     // Handle unconditional branches.
120fe6060f1SDimitry Andric     if (Opcode == M68k::BRA8 || Opcode == M68k::BRA16) {
121fe6060f1SDimitry Andric       if (!iter->getOperand(0).isMBB())
122fe6060f1SDimitry Andric         return true;
123fe6060f1SDimitry Andric       UncondBranch = {iter, iter->getOperand(0).getMBB()};
124fe6060f1SDimitry Andric 
125fe6060f1SDimitry Andric       // TBB is used to indicate the unconditional destination.
126fe6060f1SDimitry Andric       TBB = UncondBranch.second;
127fe6060f1SDimitry Andric 
128fe6060f1SDimitry Andric       if (!AllowModify)
129fe6060f1SDimitry Andric         continue;
130fe6060f1SDimitry Andric 
131fe6060f1SDimitry Andric       // If the block has any instructions after a JMP, erase them.
132fe6060f1SDimitry Andric       EraseList.insert(EraseList.begin(), MBB.rbegin(), iter);
133fe6060f1SDimitry Andric 
134fe6060f1SDimitry Andric       Cond.clear();
135fe6060f1SDimitry Andric       FBB = nullptr;
136fe6060f1SDimitry Andric 
137fe6060f1SDimitry Andric       // Erase the JMP if it's equivalent to a fall-through.
138fe6060f1SDimitry Andric       if (MBB.isLayoutSuccessor(UncondBranch.second)) {
139fe6060f1SDimitry Andric         TBB = nullptr;
140fe6060f1SDimitry Andric         EraseList.push_back(*iter);
141fe6060f1SDimitry Andric         UncondBranch = {MBB.rend(), nullptr};
142fe6060f1SDimitry Andric       }
143fe6060f1SDimitry Andric 
144fe6060f1SDimitry Andric       continue;
145fe6060f1SDimitry Andric     }
146fe6060f1SDimitry Andric 
147fe6060f1SDimitry Andric     // Handle conditional branches.
148fe6060f1SDimitry Andric     auto BranchCode = M68k::GetCondFromBranchOpc(Opcode);
149fe6060f1SDimitry Andric 
150fe6060f1SDimitry Andric     // Can't handle indirect branch.
151fe6060f1SDimitry Andric     if (BranchCode == M68k::COND_INVALID)
152fe6060f1SDimitry Andric       return true;
153fe6060f1SDimitry Andric 
154fe6060f1SDimitry Andric     // In practice we should never have an undef CCR operand, if we do
155fe6060f1SDimitry Andric     // abort here as we are not prepared to preserve the flag.
156fe6060f1SDimitry Andric     // ??? Is this required?
157fe6060f1SDimitry Andric     // if (iter->getOperand(1).isUndef())
158fe6060f1SDimitry Andric     //   return true;
159fe6060f1SDimitry Andric 
160fe6060f1SDimitry Andric     // Working from the bottom, handle the first conditional branch.
161fe6060f1SDimitry Andric     if (Cond.empty()) {
162fe6060f1SDimitry Andric       if (!iter->getOperand(0).isMBB())
163fe6060f1SDimitry Andric         return true;
164fe6060f1SDimitry Andric       MachineBasicBlock *CondBranchTarget = iter->getOperand(0).getMBB();
165fe6060f1SDimitry Andric 
166fe6060f1SDimitry Andric       // If we see something like this:
167fe6060f1SDimitry Andric       //
168fe6060f1SDimitry Andric       //     bcc l1
169fe6060f1SDimitry Andric       //     bra l2
170fe6060f1SDimitry Andric       //     ...
171fe6060f1SDimitry Andric       //   l1:
172fe6060f1SDimitry Andric       //     ...
173fe6060f1SDimitry Andric       //   l2:
174fe6060f1SDimitry Andric       if (UncondBranch.first != MBB.rend()) {
175fe6060f1SDimitry Andric 
176fe6060f1SDimitry Andric         assert(std::next(UncondBranch.first) == iter && "Wrong block layout.");
177fe6060f1SDimitry Andric 
178fe6060f1SDimitry Andric         // And we are allowed to modify the block and the target block of the
179fe6060f1SDimitry Andric         // conditional branch is the direct successor of this block:
180fe6060f1SDimitry Andric         //
181fe6060f1SDimitry Andric         //     bcc l1
182fe6060f1SDimitry Andric         //     bra l2
183fe6060f1SDimitry Andric         //   l1:
184fe6060f1SDimitry Andric         //     ...
185fe6060f1SDimitry Andric         //   l2:
186fe6060f1SDimitry Andric         //
187fe6060f1SDimitry Andric         // we change it to this if allowed:
188fe6060f1SDimitry Andric         //
189fe6060f1SDimitry Andric         //     bncc l2
190fe6060f1SDimitry Andric         //   l1:
191fe6060f1SDimitry Andric         //     ...
192fe6060f1SDimitry Andric         //   l2:
193fe6060f1SDimitry Andric         //
194fe6060f1SDimitry Andric         // Which is a bit more efficient.
195fe6060f1SDimitry Andric         if (AllowModify && MBB.isLayoutSuccessor(CondBranchTarget)) {
196fe6060f1SDimitry Andric 
197fe6060f1SDimitry Andric           BranchCode = GetOppositeBranchCondition(BranchCode);
198fe6060f1SDimitry Andric           unsigned BNCC = GetCondBranchFromCond(BranchCode);
199fe6060f1SDimitry Andric 
200fe6060f1SDimitry Andric           BuildMI(MBB, *UncondBranch.first, MBB.rfindDebugLoc(iter), get(BNCC))
201fe6060f1SDimitry Andric               .addMBB(UncondBranch.second);
202fe6060f1SDimitry Andric 
203fe6060f1SDimitry Andric           EraseList.push_back(*iter);
204fe6060f1SDimitry Andric           EraseList.push_back(*UncondBranch.first);
205fe6060f1SDimitry Andric 
206fe6060f1SDimitry Andric           TBB = UncondBranch.second;
207fe6060f1SDimitry Andric           FBB = nullptr;
208fe6060f1SDimitry Andric           Cond.push_back(MachineOperand::CreateImm(BranchCode));
209fe6060f1SDimitry Andric 
210fe6060f1SDimitry Andric           // Otherwise preserve TBB, FBB and Cond as requested
211fe6060f1SDimitry Andric         } else {
212fe6060f1SDimitry Andric           TBB = CondBranchTarget;
213fe6060f1SDimitry Andric           FBB = UncondBranch.second;
214fe6060f1SDimitry Andric           Cond.push_back(MachineOperand::CreateImm(BranchCode));
215fe6060f1SDimitry Andric         }
216fe6060f1SDimitry Andric 
217fe6060f1SDimitry Andric         UncondBranch = {MBB.rend(), nullptr};
218fe6060f1SDimitry Andric         continue;
219fe6060f1SDimitry Andric       }
220fe6060f1SDimitry Andric 
221fe6060f1SDimitry Andric       TBB = CondBranchTarget;
222fe6060f1SDimitry Andric       FBB = nullptr;
223fe6060f1SDimitry Andric       Cond.push_back(MachineOperand::CreateImm(BranchCode));
224fe6060f1SDimitry Andric 
225fe6060f1SDimitry Andric       continue;
226fe6060f1SDimitry Andric     }
227fe6060f1SDimitry Andric 
228fe6060f1SDimitry Andric     // Handle subsequent conditional branches. Only handle the case where all
229fe6060f1SDimitry Andric     // conditional branches branch to the same destination and their condition
230fe6060f1SDimitry Andric     // opcodes fit one of the special multi-branch idioms.
231fe6060f1SDimitry Andric     assert(Cond.size() == 1);
232fe6060f1SDimitry Andric     assert(TBB);
233fe6060f1SDimitry Andric 
234fe6060f1SDimitry Andric     // If the conditions are the same, we can leave them alone.
235fe6060f1SDimitry Andric     auto OldBranchCode = static_cast<M68k::CondCode>(Cond[0].getImm());
236fe6060f1SDimitry Andric     if (!iter->getOperand(0).isMBB())
237fe6060f1SDimitry Andric       return true;
238fe6060f1SDimitry Andric     auto NewTBB = iter->getOperand(0).getMBB();
239fe6060f1SDimitry Andric     if (OldBranchCode == BranchCode && TBB == NewTBB)
240fe6060f1SDimitry Andric       continue;
241fe6060f1SDimitry Andric 
242fe6060f1SDimitry Andric     // If they differ we cannot do much here.
243fe6060f1SDimitry Andric     return true;
244fe6060f1SDimitry Andric   }
245fe6060f1SDimitry Andric 
246fe6060f1SDimitry Andric   return false;
247fe6060f1SDimitry Andric }
248fe6060f1SDimitry Andric 
249fe6060f1SDimitry Andric bool M68kInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
250fe6060f1SDimitry Andric                                   MachineBasicBlock *&TBB,
251fe6060f1SDimitry Andric                                   MachineBasicBlock *&FBB,
252fe6060f1SDimitry Andric                                   SmallVectorImpl<MachineOperand> &Cond,
253fe6060f1SDimitry Andric                                   bool AllowModify) const {
254fe6060f1SDimitry Andric   return AnalyzeBranchImpl(MBB, TBB, FBB, Cond, AllowModify);
255fe6060f1SDimitry Andric }
256fe6060f1SDimitry Andric 
257fe6060f1SDimitry Andric unsigned M68kInstrInfo::removeBranch(MachineBasicBlock &MBB,
258fe6060f1SDimitry Andric                                      int *BytesRemoved) const {
259fe6060f1SDimitry Andric   assert(!BytesRemoved && "code size not handled");
260fe6060f1SDimitry Andric 
261fe6060f1SDimitry Andric   MachineBasicBlock::iterator I = MBB.end();
262fe6060f1SDimitry Andric   unsigned Count = 0;
263fe6060f1SDimitry Andric 
264fe6060f1SDimitry Andric   while (I != MBB.begin()) {
265fe6060f1SDimitry Andric     --I;
266fe6060f1SDimitry Andric     if (I->isDebugValue())
267fe6060f1SDimitry Andric       continue;
268fe6060f1SDimitry Andric     if (I->getOpcode() != M68k::BRA8 &&
269fe6060f1SDimitry Andric         getCondFromBranchOpc(I->getOpcode()) == M68k::COND_INVALID)
270fe6060f1SDimitry Andric       break;
271fe6060f1SDimitry Andric     // Remove the branch.
272fe6060f1SDimitry Andric     I->eraseFromParent();
273fe6060f1SDimitry Andric     I = MBB.end();
274fe6060f1SDimitry Andric     ++Count;
275fe6060f1SDimitry Andric   }
276fe6060f1SDimitry Andric 
277fe6060f1SDimitry Andric   return Count;
278fe6060f1SDimitry Andric }
279fe6060f1SDimitry Andric 
280fe6060f1SDimitry Andric unsigned M68kInstrInfo::insertBranch(
281fe6060f1SDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
282fe6060f1SDimitry Andric     ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
283fe6060f1SDimitry Andric   // Shouldn't be a fall through.
284fe6060f1SDimitry Andric   assert(TBB && "InsertBranch must not be told to insert a fallthrough");
285fe6060f1SDimitry Andric   assert((Cond.size() == 1 || Cond.size() == 0) &&
286fe6060f1SDimitry Andric          "M68k branch conditions have one component!");
287fe6060f1SDimitry Andric   assert(!BytesAdded && "code size not handled");
288fe6060f1SDimitry Andric 
289fe6060f1SDimitry Andric   if (Cond.empty()) {
290fe6060f1SDimitry Andric     // Unconditional branch?
291fe6060f1SDimitry Andric     assert(!FBB && "Unconditional branch with multiple successors!");
292fe6060f1SDimitry Andric     BuildMI(&MBB, DL, get(M68k::BRA8)).addMBB(TBB);
293fe6060f1SDimitry Andric     return 1;
294fe6060f1SDimitry Andric   }
295fe6060f1SDimitry Andric 
296fe6060f1SDimitry Andric   // If FBB is null, it is implied to be a fall-through block.
297fe6060f1SDimitry Andric   bool FallThru = FBB == nullptr;
298fe6060f1SDimitry Andric 
299fe6060f1SDimitry Andric   // Conditional branch.
300fe6060f1SDimitry Andric   unsigned Count = 0;
301fe6060f1SDimitry Andric   M68k::CondCode CC = (M68k::CondCode)Cond[0].getImm();
302fe6060f1SDimitry Andric   unsigned Opc = GetCondBranchFromCond(CC);
303fe6060f1SDimitry Andric   BuildMI(&MBB, DL, get(Opc)).addMBB(TBB);
304fe6060f1SDimitry Andric   ++Count;
305fe6060f1SDimitry Andric   if (!FallThru) {
306fe6060f1SDimitry Andric     // Two-way Conditional branch. Insert the second branch.
307fe6060f1SDimitry Andric     BuildMI(&MBB, DL, get(M68k::BRA8)).addMBB(FBB);
308fe6060f1SDimitry Andric     ++Count;
309fe6060f1SDimitry Andric   }
310fe6060f1SDimitry Andric   return Count;
311fe6060f1SDimitry Andric }
312fe6060f1SDimitry Andric 
313fe6060f1SDimitry Andric void M68kInstrInfo::AddSExt(MachineBasicBlock &MBB,
314fe6060f1SDimitry Andric                             MachineBasicBlock::iterator I, DebugLoc DL,
315fe6060f1SDimitry Andric                             unsigned Reg, MVT From, MVT To) const {
316fe6060f1SDimitry Andric   if (From == MVT::i8) {
317fe6060f1SDimitry Andric     unsigned R = Reg;
318fe6060f1SDimitry Andric     // EXT16 requires i16 register
319fe6060f1SDimitry Andric     if (To == MVT::i32) {
320fe6060f1SDimitry Andric       R = RI.getSubReg(Reg, M68k::MxSubRegIndex16Lo);
321fe6060f1SDimitry Andric       assert(R && "No viable SUB register available");
322fe6060f1SDimitry Andric     }
323fe6060f1SDimitry Andric     BuildMI(MBB, I, DL, get(M68k::EXT16), R).addReg(R);
324fe6060f1SDimitry Andric   }
325fe6060f1SDimitry Andric 
326fe6060f1SDimitry Andric   if (To == MVT::i32)
327fe6060f1SDimitry Andric     BuildMI(MBB, I, DL, get(M68k::EXT32), Reg).addReg(Reg);
328fe6060f1SDimitry Andric }
329fe6060f1SDimitry Andric 
330fe6060f1SDimitry Andric void M68kInstrInfo::AddZExt(MachineBasicBlock &MBB,
331fe6060f1SDimitry Andric                             MachineBasicBlock::iterator I, DebugLoc DL,
332fe6060f1SDimitry Andric                             unsigned Reg, MVT From, MVT To) const {
333fe6060f1SDimitry Andric 
334fe6060f1SDimitry Andric   unsigned Mask, And;
335fe6060f1SDimitry Andric   if (From == MVT::i8)
336fe6060f1SDimitry Andric     Mask = 0xFF;
337fe6060f1SDimitry Andric   else
338fe6060f1SDimitry Andric     Mask = 0xFFFF;
339fe6060f1SDimitry Andric 
340fe6060f1SDimitry Andric   if (To == MVT::i16)
341fe6060f1SDimitry Andric     And = M68k::AND16di;
342fe6060f1SDimitry Andric   else // i32
343fe6060f1SDimitry Andric     And = M68k::AND32di;
344fe6060f1SDimitry Andric 
345fe6060f1SDimitry Andric   // TODO use xor r,r to decrease size
346fe6060f1SDimitry Andric   BuildMI(MBB, I, DL, get(And), Reg).addReg(Reg).addImm(Mask);
347fe6060f1SDimitry Andric }
348fe6060f1SDimitry Andric 
349fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandMOVX_RR(MachineInstrBuilder &MIB, MVT MVTDst,
350fe6060f1SDimitry Andric                                   MVT MVTSrc) const {
351fe6060f1SDimitry Andric   unsigned Move = MVTDst == MVT::i16 ? M68k::MOV16rr : M68k::MOV32rr;
35204eeddc0SDimitry Andric   Register Dst = MIB->getOperand(0).getReg();
35304eeddc0SDimitry Andric   Register Src = MIB->getOperand(1).getReg();
354fe6060f1SDimitry Andric 
355fe6060f1SDimitry Andric   assert(Dst != Src && "You cannot use the same Regs with MOVX_RR");
356fe6060f1SDimitry Andric 
357fe6060f1SDimitry Andric   const auto &TRI = getRegisterInfo();
358fe6060f1SDimitry Andric 
359fe6060f1SDimitry Andric   const auto *RCDst = TRI.getMaximalPhysRegClass(Dst, MVTDst);
360fe6060f1SDimitry Andric   const auto *RCSrc = TRI.getMaximalPhysRegClass(Src, MVTSrc);
361fe6060f1SDimitry Andric 
362fe6060f1SDimitry Andric   assert(RCDst && RCSrc && "Wrong use of MOVX_RR");
363fe6060f1SDimitry Andric   assert(RCDst != RCSrc && "You cannot use the same Reg Classes with MOVX_RR");
364fe6060f1SDimitry Andric 
365fe6060f1SDimitry Andric   // We need to find the super source register that matches the size of Dst
366fe6060f1SDimitry Andric   unsigned SSrc = RI.getMatchingMegaReg(Src, RCDst);
367fe6060f1SDimitry Andric   assert(SSrc && "No viable MEGA register available");
368fe6060f1SDimitry Andric 
369fe6060f1SDimitry Andric   DebugLoc DL = MIB->getDebugLoc();
370fe6060f1SDimitry Andric 
371fe6060f1SDimitry Andric   // If it happens to that super source register is the destination register
372fe6060f1SDimitry Andric   // we do nothing
373fe6060f1SDimitry Andric   if (Dst == SSrc) {
374fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Remove " << *MIB.getInstr() << '\n');
375fe6060f1SDimitry Andric     MIB->eraseFromParent();
376fe6060f1SDimitry Andric   } else { // otherwise we need to MOV
377fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to MOV\n");
378fe6060f1SDimitry Andric     MIB->setDesc(get(Move));
379fe6060f1SDimitry Andric     MIB->getOperand(1).setReg(SSrc);
380fe6060f1SDimitry Andric   }
381fe6060f1SDimitry Andric 
382fe6060f1SDimitry Andric   return true;
383fe6060f1SDimitry Andric }
384fe6060f1SDimitry Andric 
385fe6060f1SDimitry Andric /// Expand SExt MOVE pseudos into a MOV and a EXT if the operands are two
386fe6060f1SDimitry Andric /// different registers or just EXT if it is the same register
387fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandMOVSZX_RR(MachineInstrBuilder &MIB, bool IsSigned,
388fe6060f1SDimitry Andric                                     MVT MVTDst, MVT MVTSrc) const {
389fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to ");
390fe6060f1SDimitry Andric 
391fe6060f1SDimitry Andric   unsigned Move;
392fe6060f1SDimitry Andric 
393fe6060f1SDimitry Andric   if (MVTDst == MVT::i16)
394fe6060f1SDimitry Andric     Move = M68k::MOV16rr;
395fe6060f1SDimitry Andric   else // i32
396fe6060f1SDimitry Andric     Move = M68k::MOV32rr;
397fe6060f1SDimitry Andric 
39804eeddc0SDimitry Andric   Register Dst = MIB->getOperand(0).getReg();
39904eeddc0SDimitry Andric   Register Src = MIB->getOperand(1).getReg();
400fe6060f1SDimitry Andric 
401fe6060f1SDimitry Andric   assert(Dst != Src && "You cannot use the same Regs with MOVSX_RR");
402fe6060f1SDimitry Andric 
403fe6060f1SDimitry Andric   const auto &TRI = getRegisterInfo();
404fe6060f1SDimitry Andric 
405fe6060f1SDimitry Andric   const auto *RCDst = TRI.getMaximalPhysRegClass(Dst, MVTDst);
406fe6060f1SDimitry Andric   const auto *RCSrc = TRI.getMaximalPhysRegClass(Src, MVTSrc);
407fe6060f1SDimitry Andric 
408fe6060f1SDimitry Andric   assert(RCDst && RCSrc && "Wrong use of MOVSX_RR");
409fe6060f1SDimitry Andric   assert(RCDst != RCSrc && "You cannot use the same Reg Classes with MOVSX_RR");
410fe6060f1SDimitry Andric 
411fe6060f1SDimitry Andric   // We need to find the super source register that matches the size of Dst
412fe6060f1SDimitry Andric   unsigned SSrc = RI.getMatchingMegaReg(Src, RCDst);
413fe6060f1SDimitry Andric   assert(SSrc && "No viable MEGA register available");
414fe6060f1SDimitry Andric 
415fe6060f1SDimitry Andric   MachineBasicBlock &MBB = *MIB->getParent();
416fe6060f1SDimitry Andric   DebugLoc DL = MIB->getDebugLoc();
417fe6060f1SDimitry Andric 
418fe6060f1SDimitry Andric   if (Dst != SSrc) {
419fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Move and " << '\n');
420fe6060f1SDimitry Andric     BuildMI(MBB, MIB.getInstr(), DL, get(Move), Dst).addReg(SSrc);
421fe6060f1SDimitry Andric   }
422fe6060f1SDimitry Andric 
423fe6060f1SDimitry Andric   if (IsSigned) {
424fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Sign Extend" << '\n');
425fe6060f1SDimitry Andric     AddSExt(MBB, MIB.getInstr(), DL, Dst, MVTSrc, MVTDst);
426fe6060f1SDimitry Andric   } else {
427fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Zero Extend" << '\n');
428fe6060f1SDimitry Andric     AddZExt(MBB, MIB.getInstr(), DL, Dst, MVTSrc, MVTDst);
429fe6060f1SDimitry Andric   }
430fe6060f1SDimitry Andric 
431fe6060f1SDimitry Andric   MIB->eraseFromParent();
432fe6060f1SDimitry Andric 
433fe6060f1SDimitry Andric   return true;
434fe6060f1SDimitry Andric }
435fe6060f1SDimitry Andric 
436fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandMOVSZX_RM(MachineInstrBuilder &MIB, bool IsSigned,
437fe6060f1SDimitry Andric                                     const MCInstrDesc &Desc, MVT MVTDst,
438fe6060f1SDimitry Andric                                     MVT MVTSrc) const {
439fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to LOAD and ");
440fe6060f1SDimitry Andric 
44104eeddc0SDimitry Andric   Register Dst = MIB->getOperand(0).getReg();
442fe6060f1SDimitry Andric 
443fe6060f1SDimitry Andric   // We need the subreg of Dst to make instruction verifier happy because the
444fe6060f1SDimitry Andric   // real machine instruction consumes and produces values of the same size and
445fe6060f1SDimitry Andric   // the registers the will be used here fall into different classes and this
446fe6060f1SDimitry Andric   // makes IV cry. We could use a bigger operation, but this will put some
447fe6060f1SDimitry Andric   // pressure on cache and memory, so no.
448fe6060f1SDimitry Andric   unsigned SubDst =
449fe6060f1SDimitry Andric       RI.getSubReg(Dst, MVTSrc == MVT::i8 ? M68k::MxSubRegIndex8Lo
450fe6060f1SDimitry Andric                                           : M68k::MxSubRegIndex16Lo);
451fe6060f1SDimitry Andric   assert(SubDst && "No viable SUB register available");
452fe6060f1SDimitry Andric 
453fe6060f1SDimitry Andric   // Make this a plain move
454fe6060f1SDimitry Andric   MIB->setDesc(Desc);
455fe6060f1SDimitry Andric   MIB->getOperand(0).setReg(SubDst);
456fe6060f1SDimitry Andric 
457fe6060f1SDimitry Andric   MachineBasicBlock::iterator I = MIB.getInstr();
458fe6060f1SDimitry Andric   I++;
459fe6060f1SDimitry Andric   MachineBasicBlock &MBB = *MIB->getParent();
460fe6060f1SDimitry Andric   DebugLoc DL = MIB->getDebugLoc();
461fe6060f1SDimitry Andric 
462fe6060f1SDimitry Andric   if (IsSigned) {
463fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Sign Extend" << '\n');
464fe6060f1SDimitry Andric     AddSExt(MBB, I, DL, Dst, MVTSrc, MVTDst);
465fe6060f1SDimitry Andric   } else {
466fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Zero Extend" << '\n');
467fe6060f1SDimitry Andric     AddZExt(MBB, I, DL, Dst, MVTSrc, MVTDst);
468fe6060f1SDimitry Andric   }
469fe6060f1SDimitry Andric 
470fe6060f1SDimitry Andric   return true;
471fe6060f1SDimitry Andric }
472fe6060f1SDimitry Andric 
473fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandPUSH_POP(MachineInstrBuilder &MIB,
474fe6060f1SDimitry Andric                                    const MCInstrDesc &Desc, bool IsPush) const {
475fe6060f1SDimitry Andric   MachineBasicBlock::iterator I = MIB.getInstr();
476fe6060f1SDimitry Andric   I++;
477fe6060f1SDimitry Andric   MachineBasicBlock &MBB = *MIB->getParent();
478fe6060f1SDimitry Andric   MachineOperand MO = MIB->getOperand(0);
479fe6060f1SDimitry Andric   DebugLoc DL = MIB->getDebugLoc();
480fe6060f1SDimitry Andric   if (IsPush)
481fe6060f1SDimitry Andric     BuildMI(MBB, I, DL, Desc).addReg(RI.getStackRegister()).add(MO);
482fe6060f1SDimitry Andric   else
483fe6060f1SDimitry Andric     BuildMI(MBB, I, DL, Desc, MO.getReg()).addReg(RI.getStackRegister());
484fe6060f1SDimitry Andric 
485fe6060f1SDimitry Andric   MIB->eraseFromParent();
486fe6060f1SDimitry Andric   return true;
487fe6060f1SDimitry Andric }
488fe6060f1SDimitry Andric 
489fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const {
490fe6060f1SDimitry Andric 
491fe6060f1SDimitry Andric   // Replace the pseudo instruction with the real one
492fe6060f1SDimitry Andric   if (IsToCCR)
493fe6060f1SDimitry Andric     MIB->setDesc(get(M68k::MOV16cd));
494fe6060f1SDimitry Andric   else
495fe6060f1SDimitry Andric     // FIXME M68010 or later is required
496fe6060f1SDimitry Andric     MIB->setDesc(get(M68k::MOV16dc));
497fe6060f1SDimitry Andric 
498fe6060f1SDimitry Andric   // Promote used register to the next class
499fe6060f1SDimitry Andric   auto &Opd = MIB->getOperand(1);
500fe6060f1SDimitry Andric   Opd.setReg(getRegisterInfo().getMatchingSuperReg(
501fe6060f1SDimitry Andric       Opd.getReg(), M68k::MxSubRegIndex8Lo, &M68k::DR16RegClass));
502fe6060f1SDimitry Andric 
503fe6060f1SDimitry Andric   return true;
504fe6060f1SDimitry Andric }
505fe6060f1SDimitry Andric 
506fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandMOVEM(MachineInstrBuilder &MIB,
507fe6060f1SDimitry Andric                                 const MCInstrDesc &Desc, bool IsRM) const {
508fe6060f1SDimitry Andric   int Reg = 0, Offset = 0, Base = 0;
509fe6060f1SDimitry Andric   auto XR32 = RI.getRegClass(M68k::XR32RegClassID);
510fe6060f1SDimitry Andric   auto DL = MIB->getDebugLoc();
511fe6060f1SDimitry Andric   auto MI = MIB.getInstr();
512fe6060f1SDimitry Andric   auto &MBB = *MIB->getParent();
513fe6060f1SDimitry Andric 
514fe6060f1SDimitry Andric   if (IsRM) {
515fe6060f1SDimitry Andric     Reg = MIB->getOperand(0).getReg();
516fe6060f1SDimitry Andric     Offset = MIB->getOperand(1).getImm();
517fe6060f1SDimitry Andric     Base = MIB->getOperand(2).getReg();
518fe6060f1SDimitry Andric   } else {
519fe6060f1SDimitry Andric     Offset = MIB->getOperand(0).getImm();
520fe6060f1SDimitry Andric     Base = MIB->getOperand(1).getReg();
521fe6060f1SDimitry Andric     Reg = MIB->getOperand(2).getReg();
522fe6060f1SDimitry Andric   }
523fe6060f1SDimitry Andric 
524fe6060f1SDimitry Andric   // If the register is not in XR32 then it is smaller than 32 bit, we
525fe6060f1SDimitry Andric   // implicitly promote it to 32
526fe6060f1SDimitry Andric   if (!XR32->contains(Reg)) {
527fe6060f1SDimitry Andric     Reg = RI.getMatchingMegaReg(Reg, XR32);
528fe6060f1SDimitry Andric     assert(Reg && "Has not meaningful MEGA register");
529fe6060f1SDimitry Andric   }
530fe6060f1SDimitry Andric 
531fe6060f1SDimitry Andric   unsigned Mask = 1 << RI.getSpillRegisterOrder(Reg);
532fe6060f1SDimitry Andric   if (IsRM) {
533fe6060f1SDimitry Andric     BuildMI(MBB, MI, DL, Desc)
534fe6060f1SDimitry Andric         .addImm(Mask)
535fe6060f1SDimitry Andric         .addImm(Offset)
536fe6060f1SDimitry Andric         .addReg(Base)
537fe6060f1SDimitry Andric         .addReg(Reg, RegState::ImplicitDefine)
538fe6060f1SDimitry Andric         .copyImplicitOps(*MIB);
539fe6060f1SDimitry Andric   } else {
540fe6060f1SDimitry Andric     BuildMI(MBB, MI, DL, Desc)
541fe6060f1SDimitry Andric         .addImm(Offset)
542fe6060f1SDimitry Andric         .addReg(Base)
543fe6060f1SDimitry Andric         .addImm(Mask)
544fe6060f1SDimitry Andric         .addReg(Reg, RegState::Implicit)
545fe6060f1SDimitry Andric         .copyImplicitOps(*MIB);
546fe6060f1SDimitry Andric   }
547fe6060f1SDimitry Andric 
548fe6060f1SDimitry Andric   MIB->eraseFromParent();
549fe6060f1SDimitry Andric 
550fe6060f1SDimitry Andric   return true;
551fe6060f1SDimitry Andric }
552fe6060f1SDimitry Andric 
553fe6060f1SDimitry Andric /// Expand a single-def pseudo instruction to a two-addr
554fe6060f1SDimitry Andric /// instruction with two undef reads of the register being defined.
555fe6060f1SDimitry Andric /// This is used for mapping:
556fe6060f1SDimitry Andric ///   %d0 = SETCS_C32d
557fe6060f1SDimitry Andric /// to:
558fe6060f1SDimitry Andric ///   %d0 = SUBX32dd %d0<undef>, %d0<undef>
559fe6060f1SDimitry Andric ///
560fe6060f1SDimitry Andric static bool Expand2AddrUndef(MachineInstrBuilder &MIB,
561fe6060f1SDimitry Andric                              const MCInstrDesc &Desc) {
562fe6060f1SDimitry Andric   assert(Desc.getNumOperands() == 3 && "Expected two-addr instruction.");
56304eeddc0SDimitry Andric   Register Reg = MIB->getOperand(0).getReg();
564fe6060f1SDimitry Andric   MIB->setDesc(Desc);
565fe6060f1SDimitry Andric 
566fe6060f1SDimitry Andric   // MachineInstr::addOperand() will insert explicit operands before any
567fe6060f1SDimitry Andric   // implicit operands.
568fe6060f1SDimitry Andric   MIB.addReg(Reg, RegState::Undef).addReg(Reg, RegState::Undef);
569fe6060f1SDimitry Andric   // But we don't trust that.
570fe6060f1SDimitry Andric   assert(MIB->getOperand(1).getReg() == Reg &&
571fe6060f1SDimitry Andric          MIB->getOperand(2).getReg() == Reg && "Misplaced operand");
572fe6060f1SDimitry Andric   return true;
573fe6060f1SDimitry Andric }
574fe6060f1SDimitry Andric 
575fe6060f1SDimitry Andric bool M68kInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
576fe6060f1SDimitry Andric   MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
577fe6060f1SDimitry Andric   switch (MI.getOpcode()) {
578fe6060f1SDimitry Andric   case M68k::PUSH8d:
579fe6060f1SDimitry Andric     return ExpandPUSH_POP(MIB, get(M68k::MOV8ed), true);
580fe6060f1SDimitry Andric   case M68k::PUSH16d:
581fe6060f1SDimitry Andric     return ExpandPUSH_POP(MIB, get(M68k::MOV16er), true);
582fe6060f1SDimitry Andric   case M68k::PUSH32r:
583fe6060f1SDimitry Andric     return ExpandPUSH_POP(MIB, get(M68k::MOV32er), true);
584fe6060f1SDimitry Andric 
585fe6060f1SDimitry Andric   case M68k::POP8d:
586fe6060f1SDimitry Andric     return ExpandPUSH_POP(MIB, get(M68k::MOV8do), false);
587fe6060f1SDimitry Andric   case M68k::POP16d:
588fe6060f1SDimitry Andric     return ExpandPUSH_POP(MIB, get(M68k::MOV16ro), false);
589fe6060f1SDimitry Andric   case M68k::POP32r:
590fe6060f1SDimitry Andric     return ExpandPUSH_POP(MIB, get(M68k::MOV32ro), false);
591fe6060f1SDimitry Andric 
592fe6060f1SDimitry Andric   case M68k::SETCS_C8d:
593fe6060f1SDimitry Andric     return Expand2AddrUndef(MIB, get(M68k::SUBX8dd));
594fe6060f1SDimitry Andric   case M68k::SETCS_C16d:
595fe6060f1SDimitry Andric     return Expand2AddrUndef(MIB, get(M68k::SUBX16dd));
596fe6060f1SDimitry Andric   case M68k::SETCS_C32d:
597fe6060f1SDimitry Andric     return Expand2AddrUndef(MIB, get(M68k::SUBX32dd));
598fe6060f1SDimitry Andric   }
599fe6060f1SDimitry Andric   return false;
600fe6060f1SDimitry Andric }
601fe6060f1SDimitry Andric 
602fe6060f1SDimitry Andric bool M68kInstrInfo::isPCRelRegisterOperandLegal(
603fe6060f1SDimitry Andric     const MachineOperand &MO) const {
604fe6060f1SDimitry Andric   assert(MO.isReg());
605fe6060f1SDimitry Andric 
60681ad6265SDimitry Andric   // Check whether this MO belongs to an instruction with addressing mode 'k',
60781ad6265SDimitry Andric   // Refer to TargetInstrInfo.h for more information about this function.
608fe6060f1SDimitry Andric 
60981ad6265SDimitry Andric   const MachineInstr *MI = MO.getParent();
61081ad6265SDimitry Andric   const unsigned NameIndices = M68kInstrNameIndices[MI->getOpcode()];
61181ad6265SDimitry Andric   StringRef InstrName(&M68kInstrNameData[NameIndices]);
61281ad6265SDimitry Andric   const unsigned OperandNo = MI->getOperandNo(&MO);
61381ad6265SDimitry Andric 
61481ad6265SDimitry Andric   // If this machine operand is the 2nd operand, then check
61581ad6265SDimitry Andric   // whether the instruction has destination addressing mode 'k'.
61681ad6265SDimitry Andric   if (OperandNo == 1)
61781ad6265SDimitry Andric     return Regex("[A-Z]+(8|16|32)k[a-z](_TC)?$").match(InstrName);
61881ad6265SDimitry Andric 
61981ad6265SDimitry Andric   // If this machine operand is the last one, then check
62081ad6265SDimitry Andric   // whether the instruction has source addressing mode 'k'.
62181ad6265SDimitry Andric   if (OperandNo == MI->getNumExplicitOperands() - 1)
62281ad6265SDimitry Andric     return Regex("[A-Z]+(8|16|32)[a-z]k(_TC)?$").match(InstrName);
62381ad6265SDimitry Andric 
624fe6060f1SDimitry Andric   return false;
625fe6060f1SDimitry Andric }
626fe6060f1SDimitry Andric 
627fe6060f1SDimitry Andric void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
628fe6060f1SDimitry Andric                                 MachineBasicBlock::iterator MI,
629fe6060f1SDimitry Andric                                 const DebugLoc &DL, MCRegister DstReg,
630fe6060f1SDimitry Andric                                 MCRegister SrcReg, bool KillSrc) const {
631fe6060f1SDimitry Andric   unsigned Opc = 0;
632fe6060f1SDimitry Andric 
633fe6060f1SDimitry Andric   // First deal with the normal symmetric copies.
634fe6060f1SDimitry Andric   if (M68k::XR32RegClass.contains(DstReg, SrcReg))
635fe6060f1SDimitry Andric     Opc = M68k::MOV32rr;
636fe6060f1SDimitry Andric   else if (M68k::XR16RegClass.contains(DstReg, SrcReg))
637fe6060f1SDimitry Andric     Opc = M68k::MOV16rr;
638fe6060f1SDimitry Andric   else if (M68k::DR8RegClass.contains(DstReg, SrcReg))
639fe6060f1SDimitry Andric     Opc = M68k::MOV8dd;
640fe6060f1SDimitry Andric 
641fe6060f1SDimitry Andric   if (Opc) {
642fe6060f1SDimitry Andric     BuildMI(MBB, MI, DL, get(Opc), DstReg)
643fe6060f1SDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc));
644fe6060f1SDimitry Andric     return;
645fe6060f1SDimitry Andric   }
646fe6060f1SDimitry Andric 
647fe6060f1SDimitry Andric   // Now deal with asymmetrically sized copies. The cases that follow are upcast
648fe6060f1SDimitry Andric   // moves.
649fe6060f1SDimitry Andric   //
650fe6060f1SDimitry Andric   // NOTE
651fe6060f1SDimitry Andric   // These moves are not aware of type nature of these values and thus
652fe6060f1SDimitry Andric   // won't do any SExt or ZExt and upper bits will basically contain garbage.
653fe6060f1SDimitry Andric   MachineInstrBuilder MIB(*MBB.getParent(), MI);
654fe6060f1SDimitry Andric   if (M68k::DR8RegClass.contains(SrcReg)) {
655fe6060f1SDimitry Andric     if (M68k::XR16RegClass.contains(DstReg))
656fe6060f1SDimitry Andric       Opc = M68k::MOVXd16d8;
657fe6060f1SDimitry Andric     else if (M68k::XR32RegClass.contains(DstReg))
658fe6060f1SDimitry Andric       Opc = M68k::MOVXd32d8;
659fe6060f1SDimitry Andric   } else if (M68k::XR16RegClass.contains(SrcReg) &&
660fe6060f1SDimitry Andric              M68k::XR32RegClass.contains(DstReg))
661fe6060f1SDimitry Andric     Opc = M68k::MOVXd32d16;
662fe6060f1SDimitry Andric 
663fe6060f1SDimitry Andric   if (Opc) {
664fe6060f1SDimitry Andric     BuildMI(MBB, MI, DL, get(Opc), DstReg)
665fe6060f1SDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc));
666fe6060f1SDimitry Andric     return;
667fe6060f1SDimitry Andric   }
668fe6060f1SDimitry Andric 
669fe6060f1SDimitry Andric   bool FromCCR = SrcReg == M68k::CCR;
670fe6060f1SDimitry Andric   bool FromSR = SrcReg == M68k::SR;
671fe6060f1SDimitry Andric   bool ToCCR = DstReg == M68k::CCR;
672fe6060f1SDimitry Andric   bool ToSR = DstReg == M68k::SR;
673fe6060f1SDimitry Andric 
674fe6060f1SDimitry Andric   if (FromCCR) {
675fe6060f1SDimitry Andric     assert(M68k::DR8RegClass.contains(DstReg) &&
676fe6060f1SDimitry Andric            "Need DR8 register to copy CCR");
677fe6060f1SDimitry Andric     Opc = M68k::MOV8dc;
678fe6060f1SDimitry Andric   } else if (ToCCR) {
679fe6060f1SDimitry Andric     assert(M68k::DR8RegClass.contains(SrcReg) &&
680fe6060f1SDimitry Andric            "Need DR8 register to copy CCR");
681fe6060f1SDimitry Andric     Opc = M68k::MOV8cd;
682fe6060f1SDimitry Andric   } else if (FromSR || ToSR)
683fe6060f1SDimitry Andric     llvm_unreachable("Cannot emit SR copy instruction");
684fe6060f1SDimitry Andric 
685fe6060f1SDimitry Andric   if (Opc) {
686fe6060f1SDimitry Andric     BuildMI(MBB, MI, DL, get(Opc), DstReg)
687fe6060f1SDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc));
688fe6060f1SDimitry Andric     return;
689fe6060f1SDimitry Andric   }
690fe6060f1SDimitry Andric 
691fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to "
692fe6060f1SDimitry Andric                     << RI.getName(DstReg) << '\n');
693fe6060f1SDimitry Andric   llvm_unreachable("Cannot emit physreg copy instruction");
694fe6060f1SDimitry Andric }
695fe6060f1SDimitry Andric 
696fe6060f1SDimitry Andric namespace {
697fe6060f1SDimitry Andric unsigned getLoadStoreRegOpcode(unsigned Reg, const TargetRegisterClass *RC,
698fe6060f1SDimitry Andric                                const TargetRegisterInfo *TRI,
699fe6060f1SDimitry Andric                                const M68kSubtarget &STI, bool load) {
700fe6060f1SDimitry Andric   switch (TRI->getRegSizeInBits(*RC)) {
701fe6060f1SDimitry Andric   default:
702fe6060f1SDimitry Andric     llvm_unreachable("Unknown spill size");
703fe6060f1SDimitry Andric   case 8:
704fe6060f1SDimitry Andric     if (M68k::DR8RegClass.hasSubClassEq(RC))
705*bdd1243dSDimitry Andric       return load ? M68k::MOV8dp : M68k::MOV8pd;
706fe6060f1SDimitry Andric     if (M68k::CCRCRegClass.hasSubClassEq(RC))
707fe6060f1SDimitry Andric       return load ? M68k::MOV16cp : M68k::MOV16pc;
708fe6060f1SDimitry Andric 
709fe6060f1SDimitry Andric     llvm_unreachable("Unknown 1-byte regclass");
710fe6060f1SDimitry Andric   case 16:
711fe6060f1SDimitry Andric     assert(M68k::XR16RegClass.hasSubClassEq(RC) && "Unknown 2-byte regclass");
712fe6060f1SDimitry Andric     return load ? M68k::MOVM16mp_P : M68k::MOVM16pm_P;
713fe6060f1SDimitry Andric   case 32:
714fe6060f1SDimitry Andric     assert(M68k::XR32RegClass.hasSubClassEq(RC) && "Unknown 4-byte regclass");
715fe6060f1SDimitry Andric     return load ? M68k::MOVM32mp_P : M68k::MOVM32pm_P;
716fe6060f1SDimitry Andric   }
717fe6060f1SDimitry Andric }
718fe6060f1SDimitry Andric 
719fe6060f1SDimitry Andric unsigned getStoreRegOpcode(unsigned SrcReg, const TargetRegisterClass *RC,
720fe6060f1SDimitry Andric                            const TargetRegisterInfo *TRI,
721fe6060f1SDimitry Andric                            const M68kSubtarget &STI) {
722fe6060f1SDimitry Andric   return getLoadStoreRegOpcode(SrcReg, RC, TRI, STI, false);
723fe6060f1SDimitry Andric }
724fe6060f1SDimitry Andric 
725fe6060f1SDimitry Andric unsigned getLoadRegOpcode(unsigned DstReg, const TargetRegisterClass *RC,
726fe6060f1SDimitry Andric                           const TargetRegisterInfo *TRI,
727fe6060f1SDimitry Andric                           const M68kSubtarget &STI) {
728fe6060f1SDimitry Andric   return getLoadStoreRegOpcode(DstReg, RC, TRI, STI, true);
729fe6060f1SDimitry Andric }
730fe6060f1SDimitry Andric } // end anonymous namespace
731fe6060f1SDimitry Andric 
732fe6060f1SDimitry Andric bool M68kInstrInfo::getStackSlotRange(const TargetRegisterClass *RC,
733fe6060f1SDimitry Andric                                       unsigned SubIdx, unsigned &Size,
734fe6060f1SDimitry Andric                                       unsigned &Offset,
735fe6060f1SDimitry Andric                                       const MachineFunction &MF) const {
736fe6060f1SDimitry Andric   // The slot size must be the maximum size so we can easily use MOVEM.L
737fe6060f1SDimitry Andric   Size = 4;
738fe6060f1SDimitry Andric   Offset = 0;
739fe6060f1SDimitry Andric   return true;
740fe6060f1SDimitry Andric }
741fe6060f1SDimitry Andric 
742*bdd1243dSDimitry Andric void M68kInstrInfo::storeRegToStackSlot(
743*bdd1243dSDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,
744*bdd1243dSDimitry Andric     bool IsKill, int FrameIndex, const TargetRegisterClass *RC,
745*bdd1243dSDimitry Andric     const TargetRegisterInfo *TRI, Register VReg) const {
746*bdd1243dSDimitry Andric   const MachineFrameInfo &MFI = MBB.getParent()->getFrameInfo();
747*bdd1243dSDimitry Andric   assert(MFI.getObjectSize(FrameIndex) >= TRI->getSpillSize(*RC) &&
748*bdd1243dSDimitry Andric          "Stack slot is too small to store");
749*bdd1243dSDimitry Andric 
750fe6060f1SDimitry Andric   unsigned Opc = getStoreRegOpcode(SrcReg, RC, TRI, Subtarget);
751fe6060f1SDimitry Andric   DebugLoc DL = MBB.findDebugLoc(MI);
752fe6060f1SDimitry Andric   // (0,FrameIndex) <- $reg
753fe6060f1SDimitry Andric   M68k::addFrameReference(BuildMI(MBB, MI, DL, get(Opc)), FrameIndex)
754fe6060f1SDimitry Andric       .addReg(SrcReg, getKillRegState(IsKill));
755fe6060f1SDimitry Andric }
756fe6060f1SDimitry Andric 
757fe6060f1SDimitry Andric void M68kInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
758fe6060f1SDimitry Andric                                          MachineBasicBlock::iterator MI,
759fe6060f1SDimitry Andric                                          Register DstReg, int FrameIndex,
760fe6060f1SDimitry Andric                                          const TargetRegisterClass *RC,
761*bdd1243dSDimitry Andric                                          const TargetRegisterInfo *TRI,
762*bdd1243dSDimitry Andric                                          Register VReg) const {
763*bdd1243dSDimitry Andric   const MachineFrameInfo &MFI = MBB.getParent()->getFrameInfo();
764*bdd1243dSDimitry Andric   assert(MFI.getObjectSize(FrameIndex) >= TRI->getSpillSize(*RC) &&
765*bdd1243dSDimitry Andric          "Stack slot is too small to load");
766*bdd1243dSDimitry Andric 
767fe6060f1SDimitry Andric   unsigned Opc = getLoadRegOpcode(DstReg, RC, TRI, Subtarget);
768fe6060f1SDimitry Andric   DebugLoc DL = MBB.findDebugLoc(MI);
769fe6060f1SDimitry Andric   M68k::addFrameReference(BuildMI(MBB, MI, DL, get(Opc), DstReg), FrameIndex);
770fe6060f1SDimitry Andric }
771fe6060f1SDimitry Andric 
772fe6060f1SDimitry Andric /// Return a virtual register initialized with the the global base register
773fe6060f1SDimitry Andric /// value. Output instructions required to initialize the register in the
774fe6060f1SDimitry Andric /// function entry block, if necessary.
775fe6060f1SDimitry Andric ///
776fe6060f1SDimitry Andric /// TODO Move this function to M68kMachineFunctionInfo.
777fe6060f1SDimitry Andric unsigned M68kInstrInfo::getGlobalBaseReg(MachineFunction *MF) const {
778fe6060f1SDimitry Andric   M68kMachineFunctionInfo *MxFI = MF->getInfo<M68kMachineFunctionInfo>();
779fe6060f1SDimitry Andric   unsigned GlobalBaseReg = MxFI->getGlobalBaseReg();
780fe6060f1SDimitry Andric   if (GlobalBaseReg != 0)
781fe6060f1SDimitry Andric     return GlobalBaseReg;
782fe6060f1SDimitry Andric 
783fe6060f1SDimitry Andric   // Create the register. The code to initialize it is inserted later,
784fe6060f1SDimitry Andric   // by the CGBR pass (below).
785fe6060f1SDimitry Andric   //
786fe6060f1SDimitry Andric   // NOTE
787fe6060f1SDimitry Andric   // Normally M68k uses A5 register as global base pointer but this will
788fe6060f1SDimitry Andric   // create unnecessary spill if we use less then 4 registers in code; since A5
789fe6060f1SDimitry Andric   // is callee-save anyway we could try to allocate caller-save first and if
790fe6060f1SDimitry Andric   // lucky get one, otherwise it does not really matter which callee-save to
791fe6060f1SDimitry Andric   // use.
792fe6060f1SDimitry Andric   MachineRegisterInfo &RegInfo = MF->getRegInfo();
793fe6060f1SDimitry Andric   GlobalBaseReg = RegInfo.createVirtualRegister(&M68k::AR32_NOSPRegClass);
794fe6060f1SDimitry Andric   MxFI->setGlobalBaseReg(GlobalBaseReg);
795fe6060f1SDimitry Andric   return GlobalBaseReg;
796fe6060f1SDimitry Andric }
797fe6060f1SDimitry Andric 
798fe6060f1SDimitry Andric std::pair<unsigned, unsigned>
799fe6060f1SDimitry Andric M68kInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
800fe6060f1SDimitry Andric   return std::make_pair(TF, 0u);
801fe6060f1SDimitry Andric }
802fe6060f1SDimitry Andric 
803fe6060f1SDimitry Andric ArrayRef<std::pair<unsigned, const char *>>
804fe6060f1SDimitry Andric M68kInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
805fe6060f1SDimitry Andric   using namespace M68kII;
806fe6060f1SDimitry Andric   static const std::pair<unsigned, const char *> TargetFlags[] = {
807fe6060f1SDimitry Andric       {MO_ABSOLUTE_ADDRESS, "m68k-absolute"},
808fe6060f1SDimitry Andric       {MO_PC_RELATIVE_ADDRESS, "m68k-pcrel"},
809fe6060f1SDimitry Andric       {MO_GOT, "m68k-got"},
810fe6060f1SDimitry Andric       {MO_GOTOFF, "m68k-gotoff"},
811fe6060f1SDimitry Andric       {MO_GOTPCREL, "m68k-gotpcrel"},
812fe6060f1SDimitry Andric       {MO_PLT, "m68k-plt"}};
813*bdd1243dSDimitry Andric   return ArrayRef(TargetFlags);
814fe6060f1SDimitry Andric }
815fe6060f1SDimitry Andric 
816fe6060f1SDimitry Andric namespace {
817fe6060f1SDimitry Andric /// Create Global Base Reg pass. This initializes the PIC global base register
818fe6060f1SDimitry Andric struct CGBR : public MachineFunctionPass {
819fe6060f1SDimitry Andric   static char ID;
820fe6060f1SDimitry Andric   CGBR() : MachineFunctionPass(ID) {}
821fe6060f1SDimitry Andric 
822fe6060f1SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override {
823fe6060f1SDimitry Andric     const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>();
824fe6060f1SDimitry Andric     M68kMachineFunctionInfo *MxFI = MF.getInfo<M68kMachineFunctionInfo>();
825fe6060f1SDimitry Andric 
826fe6060f1SDimitry Andric     unsigned GlobalBaseReg = MxFI->getGlobalBaseReg();
827fe6060f1SDimitry Andric 
828fe6060f1SDimitry Andric     // If we didn't need a GlobalBaseReg, don't insert code.
829fe6060f1SDimitry Andric     if (GlobalBaseReg == 0)
830fe6060f1SDimitry Andric       return false;
831fe6060f1SDimitry Andric 
832fe6060f1SDimitry Andric     // Insert the set of GlobalBaseReg into the first MBB of the function
833fe6060f1SDimitry Andric     MachineBasicBlock &FirstMBB = MF.front();
834fe6060f1SDimitry Andric     MachineBasicBlock::iterator MBBI = FirstMBB.begin();
835fe6060f1SDimitry Andric     DebugLoc DL = FirstMBB.findDebugLoc(MBBI);
836fe6060f1SDimitry Andric     const M68kInstrInfo *TII = STI.getInstrInfo();
837fe6060f1SDimitry Andric 
838fe6060f1SDimitry Andric     // Generate lea (__GLOBAL_OFFSET_TABLE_,%PC), %A5
839fe6060f1SDimitry Andric     BuildMI(FirstMBB, MBBI, DL, TII->get(M68k::LEA32q), GlobalBaseReg)
840fe6060f1SDimitry Andric         .addExternalSymbol("_GLOBAL_OFFSET_TABLE_", M68kII::MO_GOTPCREL);
841fe6060f1SDimitry Andric 
842fe6060f1SDimitry Andric     return true;
843fe6060f1SDimitry Andric   }
844fe6060f1SDimitry Andric 
845fe6060f1SDimitry Andric   StringRef getPassName() const override {
846fe6060f1SDimitry Andric     return "M68k PIC Global Base Reg Initialization";
847fe6060f1SDimitry Andric   }
848fe6060f1SDimitry Andric 
849fe6060f1SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
850fe6060f1SDimitry Andric     AU.setPreservesCFG();
851fe6060f1SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
852fe6060f1SDimitry Andric   }
853fe6060f1SDimitry Andric };
854fe6060f1SDimitry Andric } // namespace
855fe6060f1SDimitry Andric 
856fe6060f1SDimitry Andric char CGBR::ID = 0;
857fe6060f1SDimitry Andric FunctionPass *llvm::createM68kGlobalBaseRegPass() { return new CGBR(); }
858