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