xref: /freebsd/contrib/llvm-project/llvm/lib/Target/M68k/M68kExpandPseudo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
104eeddc0SDimitry Andric //===-- M68kExpandPseudo.cpp - Expand pseudo instructions -------*- 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 a pass that expands pseudo instructions into target
11fe6060f1SDimitry Andric /// instructions to allow proper scheduling, if-conversion, other late
12fe6060f1SDimitry Andric /// optimizations, or simply the encoding of the instructions.
13fe6060f1SDimitry Andric ///
14fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
15fe6060f1SDimitry Andric 
16fe6060f1SDimitry Andric #include "M68k.h"
17fe6060f1SDimitry Andric #include "M68kFrameLowering.h"
18fe6060f1SDimitry Andric #include "M68kInstrInfo.h"
19fe6060f1SDimitry Andric #include "M68kMachineFunction.h"
20fe6060f1SDimitry Andric #include "M68kSubtarget.h"
21fe6060f1SDimitry Andric 
22fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
23fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
24fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
25fe6060f1SDimitry Andric #include "llvm/CodeGen/Passes.h" // For IDs of passes that are preserved.
2606c3fb27SDimitry Andric #include "llvm/IR/EHPersonalities.h"
27fe6060f1SDimitry Andric #include "llvm/IR/GlobalValue.h"
28fe6060f1SDimitry Andric 
29fe6060f1SDimitry Andric using namespace llvm;
30fe6060f1SDimitry Andric 
3106c3fb27SDimitry Andric #define DEBUG_TYPE "m68k-expand-pseudo"
3206c3fb27SDimitry Andric #define PASS_NAME "M68k pseudo instruction expansion pass"
33fe6060f1SDimitry Andric 
34fe6060f1SDimitry Andric namespace {
35fe6060f1SDimitry Andric class M68kExpandPseudo : public MachineFunctionPass {
36fe6060f1SDimitry Andric public:
37fe6060f1SDimitry Andric   static char ID;
M68kExpandPseudo()38fe6060f1SDimitry Andric   M68kExpandPseudo() : MachineFunctionPass(ID) {}
39fe6060f1SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const40fe6060f1SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
41fe6060f1SDimitry Andric     AU.setPreservesCFG();
42fe6060f1SDimitry Andric     AU.addPreservedID(MachineLoopInfoID);
43fe6060f1SDimitry Andric     AU.addPreservedID(MachineDominatorsID);
44fe6060f1SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
45fe6060f1SDimitry Andric   }
46fe6060f1SDimitry Andric 
47fe6060f1SDimitry Andric   const M68kSubtarget *STI;
48fe6060f1SDimitry Andric   const M68kInstrInfo *TII;
49fe6060f1SDimitry Andric   const M68kRegisterInfo *TRI;
50fe6060f1SDimitry Andric   const M68kMachineFunctionInfo *MFI;
51fe6060f1SDimitry Andric   const M68kFrameLowering *FL;
52fe6060f1SDimitry Andric 
53fe6060f1SDimitry Andric   bool runOnMachineFunction(MachineFunction &Fn) override;
54fe6060f1SDimitry Andric 
getRequiredProperties() const55fe6060f1SDimitry Andric   MachineFunctionProperties getRequiredProperties() const override {
56fe6060f1SDimitry Andric     return MachineFunctionProperties().set(
57fe6060f1SDimitry Andric         MachineFunctionProperties::Property::NoVRegs);
58fe6060f1SDimitry Andric   }
59fe6060f1SDimitry Andric 
60fe6060f1SDimitry Andric private:
61fe6060f1SDimitry Andric   bool ExpandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);
62fe6060f1SDimitry Andric   bool ExpandMBB(MachineBasicBlock &MBB);
63fe6060f1SDimitry Andric };
64fe6060f1SDimitry Andric char M68kExpandPseudo::ID = 0;
65fe6060f1SDimitry Andric } // End anonymous namespace.
66fe6060f1SDimitry Andric 
INITIALIZE_PASS(M68kExpandPseudo,DEBUG_TYPE,PASS_NAME,false,false)6706c3fb27SDimitry Andric INITIALIZE_PASS(M68kExpandPseudo, DEBUG_TYPE, PASS_NAME, false, false)
6806c3fb27SDimitry Andric 
69fe6060f1SDimitry Andric /// If \p MBBI is a pseudo instruction, this method expands
70fe6060f1SDimitry Andric /// it to the corresponding (sequence of) actual instruction(s).
71fe6060f1SDimitry Andric /// \returns true if \p MBBI has been expanded.
72fe6060f1SDimitry Andric bool M68kExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
73fe6060f1SDimitry Andric                                 MachineBasicBlock::iterator MBBI) {
74fe6060f1SDimitry Andric   MachineInstr &MI = *MBBI;
75fe6060f1SDimitry Andric   MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
76fe6060f1SDimitry Andric   unsigned Opcode = MI.getOpcode();
77fe6060f1SDimitry Andric   DebugLoc DL = MBBI->getDebugLoc();
78fe6060f1SDimitry Andric   /// TODO infer argument size to create less switch cases
79fe6060f1SDimitry Andric   switch (Opcode) {
80fe6060f1SDimitry Andric   default:
81fe6060f1SDimitry Andric     return false;
82fe6060f1SDimitry Andric 
83*0fca6ea1SDimitry Andric   case M68k::MOVI8di:
84*0fca6ea1SDimitry Andric     return TII->ExpandMOVI(MIB, MVT::i8);
85*0fca6ea1SDimitry Andric   case M68k::MOVI16ri:
86*0fca6ea1SDimitry Andric     return TII->ExpandMOVI(MIB, MVT::i16);
87*0fca6ea1SDimitry Andric   case M68k::MOVI32ri:
88*0fca6ea1SDimitry Andric     return TII->ExpandMOVI(MIB, MVT::i32);
89*0fca6ea1SDimitry Andric 
90fe6060f1SDimitry Andric   case M68k::MOVXd16d8:
91fe6060f1SDimitry Andric     return TII->ExpandMOVX_RR(MIB, MVT::i16, MVT::i8);
92fe6060f1SDimitry Andric   case M68k::MOVXd32d8:
93fe6060f1SDimitry Andric     return TII->ExpandMOVX_RR(MIB, MVT::i32, MVT::i8);
94fe6060f1SDimitry Andric   case M68k::MOVXd32d16:
95fe6060f1SDimitry Andric     return TII->ExpandMOVX_RR(MIB, MVT::i32, MVT::i16);
96fe6060f1SDimitry Andric 
97fe6060f1SDimitry Andric   case M68k::MOVSXd16d8:
98fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RR(MIB, true, MVT::i16, MVT::i8);
99fe6060f1SDimitry Andric   case M68k::MOVSXd32d8:
100fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RR(MIB, true, MVT::i32, MVT::i8);
101fe6060f1SDimitry Andric   case M68k::MOVSXd32d16:
102fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RR(MIB, true, MVT::i32, MVT::i16);
103fe6060f1SDimitry Andric 
104fe6060f1SDimitry Andric   case M68k::MOVZXd16d8:
105fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RR(MIB, false, MVT::i16, MVT::i8);
106fe6060f1SDimitry Andric   case M68k::MOVZXd32d8:
107fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RR(MIB, false, MVT::i32, MVT::i8);
108fe6060f1SDimitry Andric   case M68k::MOVZXd32d16:
109fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RR(MIB, false, MVT::i32, MVT::i16);
110fe6060f1SDimitry Andric 
111fe6060f1SDimitry Andric   case M68k::MOVSXd16j8:
112fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dj), MVT::i16,
113fe6060f1SDimitry Andric                                 MVT::i8);
114fe6060f1SDimitry Andric   case M68k::MOVSXd32j8:
115fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dj), MVT::i32,
116fe6060f1SDimitry Andric                                 MVT::i8);
117fe6060f1SDimitry Andric   case M68k::MOVSXd32j16:
118fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rj), MVT::i32,
119fe6060f1SDimitry Andric                                 MVT::i16);
120fe6060f1SDimitry Andric 
121fe6060f1SDimitry Andric   case M68k::MOVZXd16j8:
122fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dj), MVT::i16,
123fe6060f1SDimitry Andric                                 MVT::i8);
124fe6060f1SDimitry Andric   case M68k::MOVZXd32j8:
125fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dj), MVT::i32,
126fe6060f1SDimitry Andric                                 MVT::i8);
127fe6060f1SDimitry Andric   case M68k::MOVZXd32j16:
128fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rj), MVT::i32,
129fe6060f1SDimitry Andric                                 MVT::i16);
130fe6060f1SDimitry Andric 
131fe6060f1SDimitry Andric   case M68k::MOVSXd16p8:
132fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dp), MVT::i16,
133fe6060f1SDimitry Andric                                 MVT::i8);
134fe6060f1SDimitry Andric   case M68k::MOVSXd32p8:
135fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dp), MVT::i32,
136fe6060f1SDimitry Andric                                 MVT::i8);
137fe6060f1SDimitry Andric   case M68k::MOVSXd32p16:
138fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rp), MVT::i32,
139fe6060f1SDimitry Andric                                 MVT::i16);
140fe6060f1SDimitry Andric 
141fe6060f1SDimitry Andric   case M68k::MOVZXd16p8:
142fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dp), MVT::i16,
143fe6060f1SDimitry Andric                                 MVT::i8);
144fe6060f1SDimitry Andric   case M68k::MOVZXd32p8:
145fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dp), MVT::i32,
146fe6060f1SDimitry Andric                                 MVT::i8);
147fe6060f1SDimitry Andric   case M68k::MOVZXd32p16:
148fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rp), MVT::i32,
149fe6060f1SDimitry Andric                                 MVT::i16);
150fe6060f1SDimitry Andric 
151fe6060f1SDimitry Andric   case M68k::MOVSXd16f8:
152fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8df), MVT::i16,
153fe6060f1SDimitry Andric                                 MVT::i8);
154fe6060f1SDimitry Andric   case M68k::MOVSXd32f8:
155fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8df), MVT::i32,
156fe6060f1SDimitry Andric                                 MVT::i8);
157fe6060f1SDimitry Andric   case M68k::MOVSXd32f16:
158fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rf), MVT::i32,
159fe6060f1SDimitry Andric                                 MVT::i16);
160fe6060f1SDimitry Andric 
161fe6060f1SDimitry Andric   case M68k::MOVZXd16f8:
162fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8df), MVT::i16,
163fe6060f1SDimitry Andric                                 MVT::i8);
164fe6060f1SDimitry Andric   case M68k::MOVZXd32f8:
165fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8df), MVT::i32,
166fe6060f1SDimitry Andric                                 MVT::i8);
167fe6060f1SDimitry Andric   case M68k::MOVZXd32f16:
168fe6060f1SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rf), MVT::i32,
169fe6060f1SDimitry Andric                                 MVT::i16);
170fe6060f1SDimitry Andric 
171647cbc5dSDimitry Andric   case M68k::MOVSXd16q8:
172647cbc5dSDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dq), MVT::i16,
173647cbc5dSDimitry Andric                                 MVT::i8);
174647cbc5dSDimitry Andric   case M68k::MOVSXd32q8:
175647cbc5dSDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dq), MVT::i32,
176647cbc5dSDimitry Andric                                 MVT::i8);
177647cbc5dSDimitry Andric   case M68k::MOVSXd32q16:
178647cbc5dSDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16dq), MVT::i32,
179647cbc5dSDimitry Andric                                 MVT::i16);
180647cbc5dSDimitry Andric 
18106c3fb27SDimitry Andric   case M68k::MOVZXd16q8:
18206c3fb27SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dq), MVT::i16,
18306c3fb27SDimitry Andric                                 MVT::i8);
18406c3fb27SDimitry Andric   case M68k::MOVZXd32q8:
18506c3fb27SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dq), MVT::i32,
18606c3fb27SDimitry Andric                                 MVT::i8);
18706c3fb27SDimitry Andric   case M68k::MOVZXd32q16:
18806c3fb27SDimitry Andric     return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16dq), MVT::i32,
18906c3fb27SDimitry Andric                                 MVT::i16);
19006c3fb27SDimitry Andric 
191fe6060f1SDimitry Andric   case M68k::MOV8cd:
192fe6060f1SDimitry Andric     return TII->ExpandCCR(MIB, /*IsToCCR=*/true);
193fe6060f1SDimitry Andric   case M68k::MOV8dc:
194fe6060f1SDimitry Andric     return TII->ExpandCCR(MIB, /*IsToCCR=*/false);
195fe6060f1SDimitry Andric 
196fe6060f1SDimitry Andric   case M68k::MOVM8jm_P:
197fe6060f1SDimitry Andric     return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);
198fe6060f1SDimitry Andric   case M68k::MOVM16jm_P:
199fe6060f1SDimitry Andric     return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);
200fe6060f1SDimitry Andric   case M68k::MOVM32jm_P:
201fe6060f1SDimitry Andric     return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);
202fe6060f1SDimitry Andric 
203fe6060f1SDimitry Andric   case M68k::MOVM8pm_P:
204fe6060f1SDimitry Andric     return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);
205fe6060f1SDimitry Andric   case M68k::MOVM16pm_P:
206fe6060f1SDimitry Andric     return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);
207fe6060f1SDimitry Andric   case M68k::MOVM32pm_P:
208fe6060f1SDimitry Andric     return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);
209fe6060f1SDimitry Andric 
210fe6060f1SDimitry Andric   case M68k::MOVM8mj_P:
211fe6060f1SDimitry Andric     return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);
212fe6060f1SDimitry Andric   case M68k::MOVM16mj_P:
213fe6060f1SDimitry Andric     return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);
214fe6060f1SDimitry Andric   case M68k::MOVM32mj_P:
215fe6060f1SDimitry Andric     return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);
216fe6060f1SDimitry Andric 
217fe6060f1SDimitry Andric   case M68k::MOVM8mp_P:
218fe6060f1SDimitry Andric     return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);
219fe6060f1SDimitry Andric   case M68k::MOVM16mp_P:
220fe6060f1SDimitry Andric     return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);
221fe6060f1SDimitry Andric   case M68k::MOVM32mp_P:
222fe6060f1SDimitry Andric     return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);
223fe6060f1SDimitry Andric 
224fe6060f1SDimitry Andric   case M68k::TCRETURNq:
225fe6060f1SDimitry Andric   case M68k::TCRETURNj: {
226fe6060f1SDimitry Andric     MachineOperand &JumpTarget = MI.getOperand(0);
227fe6060f1SDimitry Andric     MachineOperand &StackAdjust = MI.getOperand(1);
228fe6060f1SDimitry Andric     assert(StackAdjust.isImm() && "Expecting immediate value.");
229fe6060f1SDimitry Andric 
230fe6060f1SDimitry Andric     // Adjust stack pointer.
231fe6060f1SDimitry Andric     int StackAdj = StackAdjust.getImm();
232fe6060f1SDimitry Andric     int MaxTCDelta = MFI->getTCReturnAddrDelta();
233fe6060f1SDimitry Andric     int Offset = 0;
234fe6060f1SDimitry Andric     assert(MaxTCDelta <= 0 && "MaxTCDelta should never be positive");
235fe6060f1SDimitry Andric 
236fe6060f1SDimitry Andric     // Incoporate the retaddr area.
237fe6060f1SDimitry Andric     Offset = StackAdj - MaxTCDelta;
238fe6060f1SDimitry Andric     assert(Offset >= 0 && "Offset should never be negative");
239fe6060f1SDimitry Andric 
240fe6060f1SDimitry Andric     if (Offset) {
241fe6060f1SDimitry Andric       // Check for possible merge with preceding ADD instruction.
242fe6060f1SDimitry Andric       Offset += FL->mergeSPUpdates(MBB, MBBI, true);
243fe6060f1SDimitry Andric       FL->emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true);
244fe6060f1SDimitry Andric     }
245fe6060f1SDimitry Andric 
246fe6060f1SDimitry Andric     // Jump to label or value in register.
247fe6060f1SDimitry Andric     if (Opcode == M68k::TCRETURNq) {
248fe6060f1SDimitry Andric       MachineInstrBuilder MIB =
249fe6060f1SDimitry Andric           BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPq));
250fe6060f1SDimitry Andric       if (JumpTarget.isGlobal()) {
251fe6060f1SDimitry Andric         MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
252fe6060f1SDimitry Andric                              JumpTarget.getTargetFlags());
253fe6060f1SDimitry Andric       } else {
254fe6060f1SDimitry Andric         assert(JumpTarget.isSymbol());
255fe6060f1SDimitry Andric         MIB.addExternalSymbol(JumpTarget.getSymbolName(),
256fe6060f1SDimitry Andric                               JumpTarget.getTargetFlags());
257fe6060f1SDimitry Andric       }
258fe6060f1SDimitry Andric     } else {
259fe6060f1SDimitry Andric       BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPj))
260fe6060f1SDimitry Andric           .addReg(JumpTarget.getReg(), RegState::Kill);
261fe6060f1SDimitry Andric     }
262fe6060f1SDimitry Andric 
263fe6060f1SDimitry Andric     MachineInstr &NewMI = *std::prev(MBBI);
264fe6060f1SDimitry Andric     NewMI.copyImplicitOps(*MBBI->getParent()->getParent(), *MBBI);
265fe6060f1SDimitry Andric 
266fe6060f1SDimitry Andric     // Delete the pseudo instruction TCRETURN.
267fe6060f1SDimitry Andric     MBB.erase(MBBI);
268fe6060f1SDimitry Andric 
269fe6060f1SDimitry Andric     return true;
270fe6060f1SDimitry Andric   }
271fe6060f1SDimitry Andric   case M68k::RET: {
2725f757f3fSDimitry Andric     if (MBB.getParent()->getFunction().getCallingConv() ==
2735f757f3fSDimitry Andric         CallingConv::M68k_INTR) {
2745f757f3fSDimitry Andric       BuildMI(MBB, MBBI, DL, TII->get(M68k::RTE));
2755f757f3fSDimitry Andric     } else if (int64_t StackAdj = MBBI->getOperand(0).getImm(); StackAdj == 0) {
2765f757f3fSDimitry Andric       BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));
277fe6060f1SDimitry Andric     } else {
2785f757f3fSDimitry Andric       // Copy return address from stack to a free address(A0 or A1) register
279fe6060f1SDimitry Andric       // TODO check if pseudo expand uses free address register
280fe6060f1SDimitry Andric       BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32aj), M68k::A1)
281fe6060f1SDimitry Andric           .addReg(M68k::SP);
282fe6060f1SDimitry Andric 
283fe6060f1SDimitry Andric       // Adjust SP
284fe6060f1SDimitry Andric       FL->emitSPUpdate(MBB, MBBI, StackAdj, /*InEpilogue=*/true);
285fe6060f1SDimitry Andric 
286fe6060f1SDimitry Andric       // Put the return address on stack
287fe6060f1SDimitry Andric       BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32ja))
288fe6060f1SDimitry Andric           .addReg(M68k::SP)
289fe6060f1SDimitry Andric           .addReg(M68k::A1);
290fe6060f1SDimitry Andric 
291fe6060f1SDimitry Andric       // RTS
292fe6060f1SDimitry Andric       BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));
293fe6060f1SDimitry Andric     }
294fe6060f1SDimitry Andric 
295fe6060f1SDimitry Andric     // FIXME: Can rest of the operands be ignored, if there is any?
296fe6060f1SDimitry Andric     MBB.erase(MBBI);
297fe6060f1SDimitry Andric     return true;
298fe6060f1SDimitry Andric   }
299fe6060f1SDimitry Andric   }
300fe6060f1SDimitry Andric   llvm_unreachable("Previous switch has a fallthrough?");
301fe6060f1SDimitry Andric }
302fe6060f1SDimitry Andric 
303fe6060f1SDimitry Andric /// Expand all pseudo instructions contained in \p MBB.
304fe6060f1SDimitry Andric /// \returns true if any expansion occurred for \p MBB.
ExpandMBB(MachineBasicBlock & MBB)305fe6060f1SDimitry Andric bool M68kExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
306fe6060f1SDimitry Andric   bool Modified = false;
307fe6060f1SDimitry Andric 
308fe6060f1SDimitry Andric   // MBBI may be invalidated by the expansion.
309fe6060f1SDimitry Andric   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
310fe6060f1SDimitry Andric   while (MBBI != E) {
311fe6060f1SDimitry Andric     MachineBasicBlock::iterator NMBBI = std::next(MBBI);
312fe6060f1SDimitry Andric     Modified |= ExpandMI(MBB, MBBI);
313fe6060f1SDimitry Andric     MBBI = NMBBI;
314fe6060f1SDimitry Andric   }
315fe6060f1SDimitry Andric 
316fe6060f1SDimitry Andric   return Modified;
317fe6060f1SDimitry Andric }
318fe6060f1SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)319fe6060f1SDimitry Andric bool M68kExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
32081ad6265SDimitry Andric   STI = &MF.getSubtarget<M68kSubtarget>();
321fe6060f1SDimitry Andric   TII = STI->getInstrInfo();
322fe6060f1SDimitry Andric   TRI = STI->getRegisterInfo();
323fe6060f1SDimitry Andric   MFI = MF.getInfo<M68kMachineFunctionInfo>();
324fe6060f1SDimitry Andric   FL = STI->getFrameLowering();
325fe6060f1SDimitry Andric 
326fe6060f1SDimitry Andric   bool Modified = false;
327fe6060f1SDimitry Andric   for (MachineBasicBlock &MBB : MF)
328fe6060f1SDimitry Andric     Modified |= ExpandMBB(MBB);
329fe6060f1SDimitry Andric   return Modified;
330fe6060f1SDimitry Andric }
331fe6060f1SDimitry Andric 
332fe6060f1SDimitry Andric /// Returns an instance of the pseudo instruction expansion pass.
createM68kExpandPseudoPass()333fe6060f1SDimitry Andric FunctionPass *llvm::createM68kExpandPseudoPass() {
334fe6060f1SDimitry Andric   return new M68kExpandPseudo();
335fe6060f1SDimitry Andric }
336