xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/M68k/M68kInstrInfo.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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");
364*5f757f3fSDimitry Andric   (void)RCSrc;
365fe6060f1SDimitry Andric 
366fe6060f1SDimitry Andric   // We need to find the super source register that matches the size of Dst
367fe6060f1SDimitry Andric   unsigned SSrc = RI.getMatchingMegaReg(Src, RCDst);
368fe6060f1SDimitry Andric   assert(SSrc && "No viable MEGA register available");
369fe6060f1SDimitry Andric 
370fe6060f1SDimitry Andric   DebugLoc DL = MIB->getDebugLoc();
371fe6060f1SDimitry Andric 
372fe6060f1SDimitry Andric   // If it happens to that super source register is the destination register
373fe6060f1SDimitry Andric   // we do nothing
374fe6060f1SDimitry Andric   if (Dst == SSrc) {
375fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Remove " << *MIB.getInstr() << '\n');
376fe6060f1SDimitry Andric     MIB->eraseFromParent();
377fe6060f1SDimitry Andric   } else { // otherwise we need to MOV
378fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to MOV\n");
379fe6060f1SDimitry Andric     MIB->setDesc(get(Move));
380fe6060f1SDimitry Andric     MIB->getOperand(1).setReg(SSrc);
381fe6060f1SDimitry Andric   }
382fe6060f1SDimitry Andric 
383fe6060f1SDimitry Andric   return true;
384fe6060f1SDimitry Andric }
385fe6060f1SDimitry Andric 
386fe6060f1SDimitry Andric /// Expand SExt MOVE pseudos into a MOV and a EXT if the operands are two
387fe6060f1SDimitry Andric /// different registers or just EXT if it is the same register
388fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandMOVSZX_RR(MachineInstrBuilder &MIB, bool IsSigned,
389fe6060f1SDimitry Andric                                     MVT MVTDst, MVT MVTSrc) const {
390fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to ");
391fe6060f1SDimitry Andric 
392fe6060f1SDimitry Andric   unsigned Move;
393fe6060f1SDimitry Andric 
394fe6060f1SDimitry Andric   if (MVTDst == MVT::i16)
395fe6060f1SDimitry Andric     Move = M68k::MOV16rr;
396fe6060f1SDimitry Andric   else // i32
397fe6060f1SDimitry Andric     Move = M68k::MOV32rr;
398fe6060f1SDimitry Andric 
39904eeddc0SDimitry Andric   Register Dst = MIB->getOperand(0).getReg();
40004eeddc0SDimitry Andric   Register Src = MIB->getOperand(1).getReg();
401fe6060f1SDimitry Andric 
402fe6060f1SDimitry Andric   assert(Dst != Src && "You cannot use the same Regs with MOVSX_RR");
403fe6060f1SDimitry Andric 
404fe6060f1SDimitry Andric   const auto &TRI = getRegisterInfo();
405fe6060f1SDimitry Andric 
406fe6060f1SDimitry Andric   const auto *RCDst = TRI.getMaximalPhysRegClass(Dst, MVTDst);
407fe6060f1SDimitry Andric   const auto *RCSrc = TRI.getMaximalPhysRegClass(Src, MVTSrc);
408fe6060f1SDimitry Andric 
409fe6060f1SDimitry Andric   assert(RCDst && RCSrc && "Wrong use of MOVSX_RR");
410fe6060f1SDimitry Andric   assert(RCDst != RCSrc && "You cannot use the same Reg Classes with MOVSX_RR");
411*5f757f3fSDimitry Andric   (void)RCSrc;
412fe6060f1SDimitry Andric 
413fe6060f1SDimitry Andric   // We need to find the super source register that matches the size of Dst
414fe6060f1SDimitry Andric   unsigned SSrc = RI.getMatchingMegaReg(Src, RCDst);
415fe6060f1SDimitry Andric   assert(SSrc && "No viable MEGA register available");
416fe6060f1SDimitry Andric 
417fe6060f1SDimitry Andric   MachineBasicBlock &MBB = *MIB->getParent();
418fe6060f1SDimitry Andric   DebugLoc DL = MIB->getDebugLoc();
419fe6060f1SDimitry Andric 
420fe6060f1SDimitry Andric   if (Dst != SSrc) {
421fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Move and " << '\n');
422fe6060f1SDimitry Andric     BuildMI(MBB, MIB.getInstr(), DL, get(Move), Dst).addReg(SSrc);
423fe6060f1SDimitry Andric   }
424fe6060f1SDimitry Andric 
425fe6060f1SDimitry Andric   if (IsSigned) {
426fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Sign Extend" << '\n');
427fe6060f1SDimitry Andric     AddSExt(MBB, MIB.getInstr(), DL, Dst, MVTSrc, MVTDst);
428fe6060f1SDimitry Andric   } else {
429fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Zero Extend" << '\n');
430fe6060f1SDimitry Andric     AddZExt(MBB, MIB.getInstr(), DL, Dst, MVTSrc, MVTDst);
431fe6060f1SDimitry Andric   }
432fe6060f1SDimitry Andric 
433fe6060f1SDimitry Andric   MIB->eraseFromParent();
434fe6060f1SDimitry Andric 
435fe6060f1SDimitry Andric   return true;
436fe6060f1SDimitry Andric }
437fe6060f1SDimitry Andric 
438fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandMOVSZX_RM(MachineInstrBuilder &MIB, bool IsSigned,
439fe6060f1SDimitry Andric                                     const MCInstrDesc &Desc, MVT MVTDst,
440fe6060f1SDimitry Andric                                     MVT MVTSrc) const {
441fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to LOAD and ");
442fe6060f1SDimitry Andric 
44304eeddc0SDimitry Andric   Register Dst = MIB->getOperand(0).getReg();
444fe6060f1SDimitry Andric 
445fe6060f1SDimitry Andric   // We need the subreg of Dst to make instruction verifier happy because the
446fe6060f1SDimitry Andric   // real machine instruction consumes and produces values of the same size and
447fe6060f1SDimitry Andric   // the registers the will be used here fall into different classes and this
448fe6060f1SDimitry Andric   // makes IV cry. We could use a bigger operation, but this will put some
449fe6060f1SDimitry Andric   // pressure on cache and memory, so no.
450fe6060f1SDimitry Andric   unsigned SubDst =
451fe6060f1SDimitry Andric       RI.getSubReg(Dst, MVTSrc == MVT::i8 ? M68k::MxSubRegIndex8Lo
452fe6060f1SDimitry Andric                                           : M68k::MxSubRegIndex16Lo);
453fe6060f1SDimitry Andric   assert(SubDst && "No viable SUB register available");
454fe6060f1SDimitry Andric 
455fe6060f1SDimitry Andric   // Make this a plain move
456fe6060f1SDimitry Andric   MIB->setDesc(Desc);
457fe6060f1SDimitry Andric   MIB->getOperand(0).setReg(SubDst);
458fe6060f1SDimitry Andric 
459fe6060f1SDimitry Andric   MachineBasicBlock::iterator I = MIB.getInstr();
460fe6060f1SDimitry Andric   I++;
461fe6060f1SDimitry Andric   MachineBasicBlock &MBB = *MIB->getParent();
462fe6060f1SDimitry Andric   DebugLoc DL = MIB->getDebugLoc();
463fe6060f1SDimitry Andric 
464fe6060f1SDimitry Andric   if (IsSigned) {
465fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Sign Extend" << '\n');
466fe6060f1SDimitry Andric     AddSExt(MBB, I, DL, Dst, MVTSrc, MVTDst);
467fe6060f1SDimitry Andric   } else {
468fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Zero Extend" << '\n');
469fe6060f1SDimitry Andric     AddZExt(MBB, I, DL, Dst, MVTSrc, MVTDst);
470fe6060f1SDimitry Andric   }
471fe6060f1SDimitry Andric 
472fe6060f1SDimitry Andric   return true;
473fe6060f1SDimitry Andric }
474fe6060f1SDimitry Andric 
475fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandPUSH_POP(MachineInstrBuilder &MIB,
476fe6060f1SDimitry Andric                                    const MCInstrDesc &Desc, bool IsPush) const {
477fe6060f1SDimitry Andric   MachineBasicBlock::iterator I = MIB.getInstr();
478fe6060f1SDimitry Andric   I++;
479fe6060f1SDimitry Andric   MachineBasicBlock &MBB = *MIB->getParent();
480fe6060f1SDimitry Andric   MachineOperand MO = MIB->getOperand(0);
481fe6060f1SDimitry Andric   DebugLoc DL = MIB->getDebugLoc();
482fe6060f1SDimitry Andric   if (IsPush)
483fe6060f1SDimitry Andric     BuildMI(MBB, I, DL, Desc).addReg(RI.getStackRegister()).add(MO);
484fe6060f1SDimitry Andric   else
485fe6060f1SDimitry Andric     BuildMI(MBB, I, DL, Desc, MO.getReg()).addReg(RI.getStackRegister());
486fe6060f1SDimitry Andric 
487fe6060f1SDimitry Andric   MIB->eraseFromParent();
488fe6060f1SDimitry Andric   return true;
489fe6060f1SDimitry Andric }
490fe6060f1SDimitry Andric 
491fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const {
492fe6060f1SDimitry Andric 
493fe6060f1SDimitry Andric   // Replace the pseudo instruction with the real one
494fe6060f1SDimitry Andric   if (IsToCCR)
495fe6060f1SDimitry Andric     MIB->setDesc(get(M68k::MOV16cd));
496fe6060f1SDimitry Andric   else
497fe6060f1SDimitry Andric     // FIXME M68010 or later is required
498fe6060f1SDimitry Andric     MIB->setDesc(get(M68k::MOV16dc));
499fe6060f1SDimitry Andric 
500fe6060f1SDimitry Andric   // Promote used register to the next class
501fe6060f1SDimitry Andric   auto &Opd = MIB->getOperand(1);
502fe6060f1SDimitry Andric   Opd.setReg(getRegisterInfo().getMatchingSuperReg(
503fe6060f1SDimitry Andric       Opd.getReg(), M68k::MxSubRegIndex8Lo, &M68k::DR16RegClass));
504fe6060f1SDimitry Andric 
505fe6060f1SDimitry Andric   return true;
506fe6060f1SDimitry Andric }
507fe6060f1SDimitry Andric 
508fe6060f1SDimitry Andric bool M68kInstrInfo::ExpandMOVEM(MachineInstrBuilder &MIB,
509fe6060f1SDimitry Andric                                 const MCInstrDesc &Desc, bool IsRM) const {
510fe6060f1SDimitry Andric   int Reg = 0, Offset = 0, Base = 0;
511fe6060f1SDimitry Andric   auto XR32 = RI.getRegClass(M68k::XR32RegClassID);
512fe6060f1SDimitry Andric   auto DL = MIB->getDebugLoc();
513fe6060f1SDimitry Andric   auto MI = MIB.getInstr();
514fe6060f1SDimitry Andric   auto &MBB = *MIB->getParent();
515fe6060f1SDimitry Andric 
516fe6060f1SDimitry Andric   if (IsRM) {
517fe6060f1SDimitry Andric     Reg = MIB->getOperand(0).getReg();
518fe6060f1SDimitry Andric     Offset = MIB->getOperand(1).getImm();
519fe6060f1SDimitry Andric     Base = MIB->getOperand(2).getReg();
520fe6060f1SDimitry Andric   } else {
521fe6060f1SDimitry Andric     Offset = MIB->getOperand(0).getImm();
522fe6060f1SDimitry Andric     Base = MIB->getOperand(1).getReg();
523fe6060f1SDimitry Andric     Reg = MIB->getOperand(2).getReg();
524fe6060f1SDimitry Andric   }
525fe6060f1SDimitry Andric 
526fe6060f1SDimitry Andric   // If the register is not in XR32 then it is smaller than 32 bit, we
527fe6060f1SDimitry Andric   // implicitly promote it to 32
528fe6060f1SDimitry Andric   if (!XR32->contains(Reg)) {
529fe6060f1SDimitry Andric     Reg = RI.getMatchingMegaReg(Reg, XR32);
530fe6060f1SDimitry Andric     assert(Reg && "Has not meaningful MEGA register");
531fe6060f1SDimitry Andric   }
532fe6060f1SDimitry Andric 
533fe6060f1SDimitry Andric   unsigned Mask = 1 << RI.getSpillRegisterOrder(Reg);
534fe6060f1SDimitry Andric   if (IsRM) {
535fe6060f1SDimitry Andric     BuildMI(MBB, MI, DL, Desc)
536fe6060f1SDimitry Andric         .addImm(Mask)
537fe6060f1SDimitry Andric         .addImm(Offset)
538fe6060f1SDimitry Andric         .addReg(Base)
539fe6060f1SDimitry Andric         .addReg(Reg, RegState::ImplicitDefine)
540fe6060f1SDimitry Andric         .copyImplicitOps(*MIB);
541fe6060f1SDimitry Andric   } else {
542fe6060f1SDimitry Andric     BuildMI(MBB, MI, DL, Desc)
543fe6060f1SDimitry Andric         .addImm(Offset)
544fe6060f1SDimitry Andric         .addReg(Base)
545fe6060f1SDimitry Andric         .addImm(Mask)
546fe6060f1SDimitry Andric         .addReg(Reg, RegState::Implicit)
547fe6060f1SDimitry Andric         .copyImplicitOps(*MIB);
548fe6060f1SDimitry Andric   }
549fe6060f1SDimitry Andric 
550fe6060f1SDimitry Andric   MIB->eraseFromParent();
551fe6060f1SDimitry Andric 
552fe6060f1SDimitry Andric   return true;
553fe6060f1SDimitry Andric }
554fe6060f1SDimitry Andric 
555fe6060f1SDimitry Andric /// Expand a single-def pseudo instruction to a two-addr
556fe6060f1SDimitry Andric /// instruction with two undef reads of the register being defined.
557fe6060f1SDimitry Andric /// This is used for mapping:
558fe6060f1SDimitry Andric ///   %d0 = SETCS_C32d
559fe6060f1SDimitry Andric /// to:
560fe6060f1SDimitry Andric ///   %d0 = SUBX32dd %d0<undef>, %d0<undef>
561fe6060f1SDimitry Andric ///
562fe6060f1SDimitry Andric static bool Expand2AddrUndef(MachineInstrBuilder &MIB,
563fe6060f1SDimitry Andric                              const MCInstrDesc &Desc) {
564fe6060f1SDimitry Andric   assert(Desc.getNumOperands() == 3 && "Expected two-addr instruction.");
56504eeddc0SDimitry Andric   Register Reg = MIB->getOperand(0).getReg();
566fe6060f1SDimitry Andric   MIB->setDesc(Desc);
567fe6060f1SDimitry Andric 
568fe6060f1SDimitry Andric   // MachineInstr::addOperand() will insert explicit operands before any
569fe6060f1SDimitry Andric   // implicit operands.
570fe6060f1SDimitry Andric   MIB.addReg(Reg, RegState::Undef).addReg(Reg, RegState::Undef);
571fe6060f1SDimitry Andric   // But we don't trust that.
572fe6060f1SDimitry Andric   assert(MIB->getOperand(1).getReg() == Reg &&
573fe6060f1SDimitry Andric          MIB->getOperand(2).getReg() == Reg && "Misplaced operand");
574fe6060f1SDimitry Andric   return true;
575fe6060f1SDimitry Andric }
576fe6060f1SDimitry Andric 
577fe6060f1SDimitry Andric bool M68kInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
578fe6060f1SDimitry Andric   MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
579fe6060f1SDimitry Andric   switch (MI.getOpcode()) {
580fe6060f1SDimitry Andric   case M68k::PUSH8d:
581fe6060f1SDimitry Andric     return ExpandPUSH_POP(MIB, get(M68k::MOV8ed), true);
582fe6060f1SDimitry Andric   case M68k::PUSH16d:
583fe6060f1SDimitry Andric     return ExpandPUSH_POP(MIB, get(M68k::MOV16er), true);
584fe6060f1SDimitry Andric   case M68k::PUSH32r:
585fe6060f1SDimitry Andric     return ExpandPUSH_POP(MIB, get(M68k::MOV32er), true);
586fe6060f1SDimitry Andric 
587fe6060f1SDimitry Andric   case M68k::POP8d:
588fe6060f1SDimitry Andric     return ExpandPUSH_POP(MIB, get(M68k::MOV8do), false);
589fe6060f1SDimitry Andric   case M68k::POP16d:
590fe6060f1SDimitry Andric     return ExpandPUSH_POP(MIB, get(M68k::MOV16ro), false);
591fe6060f1SDimitry Andric   case M68k::POP32r:
592fe6060f1SDimitry Andric     return ExpandPUSH_POP(MIB, get(M68k::MOV32ro), false);
593fe6060f1SDimitry Andric 
594fe6060f1SDimitry Andric   case M68k::SETCS_C8d:
595fe6060f1SDimitry Andric     return Expand2AddrUndef(MIB, get(M68k::SUBX8dd));
596fe6060f1SDimitry Andric   case M68k::SETCS_C16d:
597fe6060f1SDimitry Andric     return Expand2AddrUndef(MIB, get(M68k::SUBX16dd));
598fe6060f1SDimitry Andric   case M68k::SETCS_C32d:
599fe6060f1SDimitry Andric     return Expand2AddrUndef(MIB, get(M68k::SUBX32dd));
600fe6060f1SDimitry Andric   }
601fe6060f1SDimitry Andric   return false;
602fe6060f1SDimitry Andric }
603fe6060f1SDimitry Andric 
604fe6060f1SDimitry Andric bool M68kInstrInfo::isPCRelRegisterOperandLegal(
605fe6060f1SDimitry Andric     const MachineOperand &MO) const {
606fe6060f1SDimitry Andric   assert(MO.isReg());
607fe6060f1SDimitry Andric 
60881ad6265SDimitry Andric   // Check whether this MO belongs to an instruction with addressing mode 'k',
60981ad6265SDimitry Andric   // Refer to TargetInstrInfo.h for more information about this function.
610fe6060f1SDimitry Andric 
61181ad6265SDimitry Andric   const MachineInstr *MI = MO.getParent();
61281ad6265SDimitry Andric   const unsigned NameIndices = M68kInstrNameIndices[MI->getOpcode()];
61381ad6265SDimitry Andric   StringRef InstrName(&M68kInstrNameData[NameIndices]);
61406c3fb27SDimitry Andric   const unsigned OperandNo = MO.getOperandNo();
61581ad6265SDimitry Andric 
61681ad6265SDimitry Andric   // If this machine operand is the 2nd operand, then check
61781ad6265SDimitry Andric   // whether the instruction has destination addressing mode 'k'.
61881ad6265SDimitry Andric   if (OperandNo == 1)
61981ad6265SDimitry Andric     return Regex("[A-Z]+(8|16|32)k[a-z](_TC)?$").match(InstrName);
62081ad6265SDimitry Andric 
62181ad6265SDimitry Andric   // If this machine operand is the last one, then check
62281ad6265SDimitry Andric   // whether the instruction has source addressing mode 'k'.
62381ad6265SDimitry Andric   if (OperandNo == MI->getNumExplicitOperands() - 1)
62481ad6265SDimitry Andric     return Regex("[A-Z]+(8|16|32)[a-z]k(_TC)?$").match(InstrName);
62581ad6265SDimitry Andric 
626fe6060f1SDimitry Andric   return false;
627fe6060f1SDimitry Andric }
628fe6060f1SDimitry Andric 
629fe6060f1SDimitry Andric void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
630fe6060f1SDimitry Andric                                 MachineBasicBlock::iterator MI,
631fe6060f1SDimitry Andric                                 const DebugLoc &DL, MCRegister DstReg,
632fe6060f1SDimitry Andric                                 MCRegister SrcReg, bool KillSrc) const {
633fe6060f1SDimitry Andric   unsigned Opc = 0;
634fe6060f1SDimitry Andric 
635fe6060f1SDimitry Andric   // First deal with the normal symmetric copies.
636fe6060f1SDimitry Andric   if (M68k::XR32RegClass.contains(DstReg, SrcReg))
637fe6060f1SDimitry Andric     Opc = M68k::MOV32rr;
638fe6060f1SDimitry Andric   else if (M68k::XR16RegClass.contains(DstReg, SrcReg))
639fe6060f1SDimitry Andric     Opc = M68k::MOV16rr;
640fe6060f1SDimitry Andric   else if (M68k::DR8RegClass.contains(DstReg, SrcReg))
641fe6060f1SDimitry Andric     Opc = M68k::MOV8dd;
642fe6060f1SDimitry Andric 
643fe6060f1SDimitry Andric   if (Opc) {
644fe6060f1SDimitry Andric     BuildMI(MBB, MI, DL, get(Opc), DstReg)
645fe6060f1SDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc));
646fe6060f1SDimitry Andric     return;
647fe6060f1SDimitry Andric   }
648fe6060f1SDimitry Andric 
649fe6060f1SDimitry Andric   // Now deal with asymmetrically sized copies. The cases that follow are upcast
650fe6060f1SDimitry Andric   // moves.
651fe6060f1SDimitry Andric   //
652fe6060f1SDimitry Andric   // NOTE
653fe6060f1SDimitry Andric   // These moves are not aware of type nature of these values and thus
654fe6060f1SDimitry Andric   // won't do any SExt or ZExt and upper bits will basically contain garbage.
655fe6060f1SDimitry Andric   MachineInstrBuilder MIB(*MBB.getParent(), MI);
656fe6060f1SDimitry Andric   if (M68k::DR8RegClass.contains(SrcReg)) {
657fe6060f1SDimitry Andric     if (M68k::XR16RegClass.contains(DstReg))
658fe6060f1SDimitry Andric       Opc = M68k::MOVXd16d8;
659fe6060f1SDimitry Andric     else if (M68k::XR32RegClass.contains(DstReg))
660fe6060f1SDimitry Andric       Opc = M68k::MOVXd32d8;
661fe6060f1SDimitry Andric   } else if (M68k::XR16RegClass.contains(SrcReg) &&
662fe6060f1SDimitry Andric              M68k::XR32RegClass.contains(DstReg))
663fe6060f1SDimitry Andric     Opc = M68k::MOVXd32d16;
664fe6060f1SDimitry Andric 
665fe6060f1SDimitry Andric   if (Opc) {
666fe6060f1SDimitry Andric     BuildMI(MBB, MI, DL, get(Opc), DstReg)
667fe6060f1SDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc));
668fe6060f1SDimitry Andric     return;
669fe6060f1SDimitry Andric   }
670fe6060f1SDimitry Andric 
671fe6060f1SDimitry Andric   bool FromCCR = SrcReg == M68k::CCR;
672fe6060f1SDimitry Andric   bool FromSR = SrcReg == M68k::SR;
673fe6060f1SDimitry Andric   bool ToCCR = DstReg == M68k::CCR;
674fe6060f1SDimitry Andric   bool ToSR = DstReg == M68k::SR;
675fe6060f1SDimitry Andric 
676fe6060f1SDimitry Andric   if (FromCCR) {
677fe6060f1SDimitry Andric     assert(M68k::DR8RegClass.contains(DstReg) &&
678fe6060f1SDimitry Andric            "Need DR8 register to copy CCR");
679fe6060f1SDimitry Andric     Opc = M68k::MOV8dc;
680fe6060f1SDimitry Andric   } else if (ToCCR) {
681fe6060f1SDimitry Andric     assert(M68k::DR8RegClass.contains(SrcReg) &&
682fe6060f1SDimitry Andric            "Need DR8 register to copy CCR");
683fe6060f1SDimitry Andric     Opc = M68k::MOV8cd;
684fe6060f1SDimitry Andric   } else if (FromSR || ToSR)
685fe6060f1SDimitry Andric     llvm_unreachable("Cannot emit SR copy instruction");
686fe6060f1SDimitry Andric 
687fe6060f1SDimitry Andric   if (Opc) {
688fe6060f1SDimitry Andric     BuildMI(MBB, MI, DL, get(Opc), DstReg)
689fe6060f1SDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc));
690fe6060f1SDimitry Andric     return;
691fe6060f1SDimitry Andric   }
692fe6060f1SDimitry Andric 
693fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to "
694fe6060f1SDimitry Andric                     << RI.getName(DstReg) << '\n');
695fe6060f1SDimitry Andric   llvm_unreachable("Cannot emit physreg copy instruction");
696fe6060f1SDimitry Andric }
697fe6060f1SDimitry Andric 
698fe6060f1SDimitry Andric namespace {
699fe6060f1SDimitry Andric unsigned getLoadStoreRegOpcode(unsigned Reg, const TargetRegisterClass *RC,
700fe6060f1SDimitry Andric                                const TargetRegisterInfo *TRI,
701fe6060f1SDimitry Andric                                const M68kSubtarget &STI, bool load) {
702fe6060f1SDimitry Andric   switch (TRI->getRegSizeInBits(*RC)) {
703fe6060f1SDimitry Andric   default:
704fe6060f1SDimitry Andric     llvm_unreachable("Unknown spill size");
705fe6060f1SDimitry Andric   case 8:
706fe6060f1SDimitry Andric     if (M68k::DR8RegClass.hasSubClassEq(RC))
707bdd1243dSDimitry Andric       return load ? M68k::MOV8dp : M68k::MOV8pd;
708fe6060f1SDimitry Andric     if (M68k::CCRCRegClass.hasSubClassEq(RC))
709fe6060f1SDimitry Andric       return load ? M68k::MOV16cp : M68k::MOV16pc;
710fe6060f1SDimitry Andric 
711fe6060f1SDimitry Andric     llvm_unreachable("Unknown 1-byte regclass");
712fe6060f1SDimitry Andric   case 16:
713fe6060f1SDimitry Andric     assert(M68k::XR16RegClass.hasSubClassEq(RC) && "Unknown 2-byte regclass");
714fe6060f1SDimitry Andric     return load ? M68k::MOVM16mp_P : M68k::MOVM16pm_P;
715fe6060f1SDimitry Andric   case 32:
716fe6060f1SDimitry Andric     assert(M68k::XR32RegClass.hasSubClassEq(RC) && "Unknown 4-byte regclass");
717fe6060f1SDimitry Andric     return load ? M68k::MOVM32mp_P : M68k::MOVM32pm_P;
718fe6060f1SDimitry Andric   }
719fe6060f1SDimitry Andric }
720fe6060f1SDimitry Andric 
721fe6060f1SDimitry Andric unsigned getStoreRegOpcode(unsigned SrcReg, const TargetRegisterClass *RC,
722fe6060f1SDimitry Andric                            const TargetRegisterInfo *TRI,
723fe6060f1SDimitry Andric                            const M68kSubtarget &STI) {
724fe6060f1SDimitry Andric   return getLoadStoreRegOpcode(SrcReg, RC, TRI, STI, false);
725fe6060f1SDimitry Andric }
726fe6060f1SDimitry Andric 
727fe6060f1SDimitry Andric unsigned getLoadRegOpcode(unsigned DstReg, const TargetRegisterClass *RC,
728fe6060f1SDimitry Andric                           const TargetRegisterInfo *TRI,
729fe6060f1SDimitry Andric                           const M68kSubtarget &STI) {
730fe6060f1SDimitry Andric   return getLoadStoreRegOpcode(DstReg, RC, TRI, STI, true);
731fe6060f1SDimitry Andric }
732fe6060f1SDimitry Andric } // end anonymous namespace
733fe6060f1SDimitry Andric 
734fe6060f1SDimitry Andric bool M68kInstrInfo::getStackSlotRange(const TargetRegisterClass *RC,
735fe6060f1SDimitry Andric                                       unsigned SubIdx, unsigned &Size,
736fe6060f1SDimitry Andric                                       unsigned &Offset,
737fe6060f1SDimitry Andric                                       const MachineFunction &MF) const {
738fe6060f1SDimitry Andric   // The slot size must be the maximum size so we can easily use MOVEM.L
739fe6060f1SDimitry Andric   Size = 4;
740fe6060f1SDimitry Andric   Offset = 0;
741fe6060f1SDimitry Andric   return true;
742fe6060f1SDimitry Andric }
743fe6060f1SDimitry Andric 
744bdd1243dSDimitry Andric void M68kInstrInfo::storeRegToStackSlot(
745bdd1243dSDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,
746bdd1243dSDimitry Andric     bool IsKill, int FrameIndex, const TargetRegisterClass *RC,
747bdd1243dSDimitry Andric     const TargetRegisterInfo *TRI, Register VReg) const {
748bdd1243dSDimitry Andric   const MachineFrameInfo &MFI = MBB.getParent()->getFrameInfo();
749bdd1243dSDimitry Andric   assert(MFI.getObjectSize(FrameIndex) >= TRI->getSpillSize(*RC) &&
750bdd1243dSDimitry Andric          "Stack slot is too small to store");
751*5f757f3fSDimitry Andric   (void)MFI;
752bdd1243dSDimitry Andric 
753fe6060f1SDimitry Andric   unsigned Opc = getStoreRegOpcode(SrcReg, RC, TRI, Subtarget);
754fe6060f1SDimitry Andric   DebugLoc DL = MBB.findDebugLoc(MI);
755fe6060f1SDimitry Andric   // (0,FrameIndex) <- $reg
756fe6060f1SDimitry Andric   M68k::addFrameReference(BuildMI(MBB, MI, DL, get(Opc)), FrameIndex)
757fe6060f1SDimitry Andric       .addReg(SrcReg, getKillRegState(IsKill));
758fe6060f1SDimitry Andric }
759fe6060f1SDimitry Andric 
760fe6060f1SDimitry Andric void M68kInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
761fe6060f1SDimitry Andric                                          MachineBasicBlock::iterator MI,
762fe6060f1SDimitry Andric                                          Register DstReg, int FrameIndex,
763fe6060f1SDimitry Andric                                          const TargetRegisterClass *RC,
764bdd1243dSDimitry Andric                                          const TargetRegisterInfo *TRI,
765bdd1243dSDimitry Andric                                          Register VReg) const {
766bdd1243dSDimitry Andric   const MachineFrameInfo &MFI = MBB.getParent()->getFrameInfo();
767bdd1243dSDimitry Andric   assert(MFI.getObjectSize(FrameIndex) >= TRI->getSpillSize(*RC) &&
768bdd1243dSDimitry Andric          "Stack slot is too small to load");
769*5f757f3fSDimitry Andric   (void)MFI;
770bdd1243dSDimitry Andric 
771fe6060f1SDimitry Andric   unsigned Opc = getLoadRegOpcode(DstReg, RC, TRI, Subtarget);
772fe6060f1SDimitry Andric   DebugLoc DL = MBB.findDebugLoc(MI);
773fe6060f1SDimitry Andric   M68k::addFrameReference(BuildMI(MBB, MI, DL, get(Opc), DstReg), FrameIndex);
774fe6060f1SDimitry Andric }
775fe6060f1SDimitry Andric 
776*5f757f3fSDimitry Andric /// Return a virtual register initialized with the global base register
777fe6060f1SDimitry Andric /// value. Output instructions required to initialize the register in the
778fe6060f1SDimitry Andric /// function entry block, if necessary.
779fe6060f1SDimitry Andric ///
780fe6060f1SDimitry Andric /// TODO Move this function to M68kMachineFunctionInfo.
781fe6060f1SDimitry Andric unsigned M68kInstrInfo::getGlobalBaseReg(MachineFunction *MF) const {
782fe6060f1SDimitry Andric   M68kMachineFunctionInfo *MxFI = MF->getInfo<M68kMachineFunctionInfo>();
783fe6060f1SDimitry Andric   unsigned GlobalBaseReg = MxFI->getGlobalBaseReg();
784fe6060f1SDimitry Andric   if (GlobalBaseReg != 0)
785fe6060f1SDimitry Andric     return GlobalBaseReg;
786fe6060f1SDimitry Andric 
787fe6060f1SDimitry Andric   // Create the register. The code to initialize it is inserted later,
78806c3fb27SDimitry Andric   // by the M68kGlobalBaseReg pass (below).
789fe6060f1SDimitry Andric   //
790fe6060f1SDimitry Andric   // NOTE
791fe6060f1SDimitry Andric   // Normally M68k uses A5 register as global base pointer but this will
792fe6060f1SDimitry Andric   // create unnecessary spill if we use less then 4 registers in code; since A5
793fe6060f1SDimitry Andric   // is callee-save anyway we could try to allocate caller-save first and if
794fe6060f1SDimitry Andric   // lucky get one, otherwise it does not really matter which callee-save to
795fe6060f1SDimitry Andric   // use.
796fe6060f1SDimitry Andric   MachineRegisterInfo &RegInfo = MF->getRegInfo();
797fe6060f1SDimitry Andric   GlobalBaseReg = RegInfo.createVirtualRegister(&M68k::AR32_NOSPRegClass);
798fe6060f1SDimitry Andric   MxFI->setGlobalBaseReg(GlobalBaseReg);
799fe6060f1SDimitry Andric   return GlobalBaseReg;
800fe6060f1SDimitry Andric }
801fe6060f1SDimitry Andric 
802fe6060f1SDimitry Andric std::pair<unsigned, unsigned>
803fe6060f1SDimitry Andric M68kInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
804fe6060f1SDimitry Andric   return std::make_pair(TF, 0u);
805fe6060f1SDimitry Andric }
806fe6060f1SDimitry Andric 
807fe6060f1SDimitry Andric ArrayRef<std::pair<unsigned, const char *>>
808fe6060f1SDimitry Andric M68kInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
809fe6060f1SDimitry Andric   using namespace M68kII;
810fe6060f1SDimitry Andric   static const std::pair<unsigned, const char *> TargetFlags[] = {
811fe6060f1SDimitry Andric       {MO_ABSOLUTE_ADDRESS, "m68k-absolute"},
812fe6060f1SDimitry Andric       {MO_PC_RELATIVE_ADDRESS, "m68k-pcrel"},
813fe6060f1SDimitry Andric       {MO_GOT, "m68k-got"},
814fe6060f1SDimitry Andric       {MO_GOTOFF, "m68k-gotoff"},
815fe6060f1SDimitry Andric       {MO_GOTPCREL, "m68k-gotpcrel"},
81606c3fb27SDimitry Andric       {MO_PLT, "m68k-plt"},
81706c3fb27SDimitry Andric       {MO_TLSGD, "m68k-tlsgd"},
81806c3fb27SDimitry Andric       {MO_TLSLD, "m68k-tlsld"},
81906c3fb27SDimitry Andric       {MO_TLSLDM, "m68k-tlsldm"},
82006c3fb27SDimitry Andric       {MO_TLSIE, "m68k-tlsie"},
82106c3fb27SDimitry Andric       {MO_TLSLE, "m68k-tlsle"}};
822bdd1243dSDimitry Andric   return ArrayRef(TargetFlags);
823fe6060f1SDimitry Andric }
824fe6060f1SDimitry Andric 
82506c3fb27SDimitry Andric #undef DEBUG_TYPE
82606c3fb27SDimitry Andric #define DEBUG_TYPE "m68k-create-global-base-reg"
82706c3fb27SDimitry Andric 
82806c3fb27SDimitry Andric #define PASS_NAME "M68k PIC Global Base Reg Initialization"
82906c3fb27SDimitry Andric 
830fe6060f1SDimitry Andric namespace {
83106c3fb27SDimitry Andric /// This initializes the PIC global base register
83206c3fb27SDimitry Andric struct M68kGlobalBaseReg : public MachineFunctionPass {
833fe6060f1SDimitry Andric   static char ID;
83406c3fb27SDimitry Andric   M68kGlobalBaseReg() : MachineFunctionPass(ID) {}
835fe6060f1SDimitry Andric 
836fe6060f1SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override {
837fe6060f1SDimitry Andric     const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>();
838fe6060f1SDimitry Andric     M68kMachineFunctionInfo *MxFI = MF.getInfo<M68kMachineFunctionInfo>();
839fe6060f1SDimitry Andric 
840fe6060f1SDimitry Andric     unsigned GlobalBaseReg = MxFI->getGlobalBaseReg();
841fe6060f1SDimitry Andric 
842fe6060f1SDimitry Andric     // If we didn't need a GlobalBaseReg, don't insert code.
843fe6060f1SDimitry Andric     if (GlobalBaseReg == 0)
844fe6060f1SDimitry Andric       return false;
845fe6060f1SDimitry Andric 
846fe6060f1SDimitry Andric     // Insert the set of GlobalBaseReg into the first MBB of the function
847fe6060f1SDimitry Andric     MachineBasicBlock &FirstMBB = MF.front();
848fe6060f1SDimitry Andric     MachineBasicBlock::iterator MBBI = FirstMBB.begin();
849fe6060f1SDimitry Andric     DebugLoc DL = FirstMBB.findDebugLoc(MBBI);
850fe6060f1SDimitry Andric     const M68kInstrInfo *TII = STI.getInstrInfo();
851fe6060f1SDimitry Andric 
852fe6060f1SDimitry Andric     // Generate lea (__GLOBAL_OFFSET_TABLE_,%PC), %A5
853fe6060f1SDimitry Andric     BuildMI(FirstMBB, MBBI, DL, TII->get(M68k::LEA32q), GlobalBaseReg)
854fe6060f1SDimitry Andric         .addExternalSymbol("_GLOBAL_OFFSET_TABLE_", M68kII::MO_GOTPCREL);
855fe6060f1SDimitry Andric 
856fe6060f1SDimitry Andric     return true;
857fe6060f1SDimitry Andric   }
858fe6060f1SDimitry Andric 
859fe6060f1SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
860fe6060f1SDimitry Andric     AU.setPreservesCFG();
861fe6060f1SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
862fe6060f1SDimitry Andric   }
863fe6060f1SDimitry Andric };
86406c3fb27SDimitry Andric char M68kGlobalBaseReg::ID = 0;
865fe6060f1SDimitry Andric } // namespace
866fe6060f1SDimitry Andric 
86706c3fb27SDimitry Andric INITIALIZE_PASS(M68kGlobalBaseReg, DEBUG_TYPE, PASS_NAME, false, false)
86806c3fb27SDimitry Andric 
86906c3fb27SDimitry Andric FunctionPass *llvm::createM68kGlobalBaseRegPass() {
87006c3fb27SDimitry Andric   return new M68kGlobalBaseReg();
87106c3fb27SDimitry Andric }
872