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