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