blob: ba7a95e92c5c5c04e419a6a2dd7fde9d54a9bac1 [file] [log] [blame]
Dylan McKay6d8078f2016-05-06 10:12:31 +00001//===-- AVRInstrInfo.cpp - AVR Instruction Information --------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Dylan McKay6d8078f2016-05-06 10:12:31 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the AVR implementation of the TargetInstrInfo class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "AVRInstrInfo.h"
14
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/CodeGen/MachineConstantPool.h"
17#include "llvm/CodeGen/MachineFrameInfo.h"
18#include "llvm/CodeGen/MachineInstrBuilder.h"
19#include "llvm/CodeGen/MachineMemOperand.h"
20#include "llvm/IR/Constants.h"
21#include "llvm/IR/Function.h"
22#include "llvm/MC/MCContext.h"
23#include "llvm/Support/Debug.h"
24#include "llvm/Support/ErrorHandling.h"
25#include "llvm/Support/TargetRegistry.h"
26
27#include "AVR.h"
28#include "AVRMachineFunctionInfo.h"
Dylan McKayafff1692016-10-05 13:38:29 +000029#include "AVRRegisterInfo.h"
Dylan McKay6d8078f2016-05-06 10:12:31 +000030#include "AVRTargetMachine.h"
31#include "MCTargetDesc/AVRMCTargetDesc.h"
32
33#define GET_INSTRINFO_CTOR_DTOR
34#include "AVRGenInstrInfo.inc"
35
36namespace llvm {
37
38AVRInstrInfo::AVRInstrInfo()
39 : AVRGenInstrInfo(AVR::ADJCALLSTACKDOWN, AVR::ADJCALLSTACKUP), RI() {}
40
41void AVRInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
Benjamin Kramerbdc49562016-06-12 15:39:02 +000042 MachineBasicBlock::iterator MI,
43 const DebugLoc &DL, unsigned DestReg,
44 unsigned SrcReg, bool KillSrc) const {
Dylan McKayafff1692016-10-05 13:38:29 +000045 const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
46 const AVRRegisterInfo &TRI = *STI.getRegisterInfo();
Dylan McKay6d8078f2016-05-06 10:12:31 +000047 unsigned Opc;
48
Dylan McKayafff1692016-10-05 13:38:29 +000049 // Not all AVR devices support the 16-bit `MOVW` instruction.
50 if (AVR::DREGSRegClass.contains(DestReg, SrcReg)) {
51 if (STI.hasMOVW()) {
52 BuildMI(MBB, MI, DL, get(AVR::MOVWRdRr), DestReg)
53 .addReg(SrcReg, getKillRegState(KillSrc));
54 } else {
55 unsigned DestLo, DestHi, SrcLo, SrcHi;
Dylan McKay6d8078f2016-05-06 10:12:31 +000056
Dylan McKayafff1692016-10-05 13:38:29 +000057 TRI.splitReg(DestReg, DestLo, DestHi);
58 TRI.splitReg(SrcReg, SrcLo, SrcHi);
59
60 // Copy each individual register with the `MOV` instruction.
61 BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestLo)
62 .addReg(SrcLo, getKillRegState(KillSrc));
63 BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestHi)
64 .addReg(SrcHi, getKillRegState(KillSrc));
65 }
66 } else {
67 if (AVR::GPR8RegClass.contains(DestReg, SrcReg)) {
68 Opc = AVR::MOVRdRr;
69 } else if (SrcReg == AVR::SP && AVR::DREGSRegClass.contains(DestReg)) {
70 Opc = AVR::SPREAD;
71 } else if (DestReg == AVR::SP && AVR::DREGSRegClass.contains(SrcReg)) {
72 Opc = AVR::SPWRITE;
73 } else {
74 llvm_unreachable("Impossible reg-to-reg copy");
75 }
76
77 BuildMI(MBB, MI, DL, get(Opc), DestReg)
78 .addReg(SrcReg, getKillRegState(KillSrc));
79 }
Dylan McKay6d8078f2016-05-06 10:12:31 +000080}
81
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +000082unsigned AVRInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
Dylan McKay6d8078f2016-05-06 10:12:31 +000083 int &FrameIndex) const {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +000084 switch (MI.getOpcode()) {
Dylan McKay6d8078f2016-05-06 10:12:31 +000085 case AVR::LDDRdPtrQ:
86 case AVR::LDDWRdYQ: { //:FIXME: remove this once PR13375 gets fixed
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +000087 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
88 MI.getOperand(2).getImm() == 0) {
89 FrameIndex = MI.getOperand(1).getIndex();
90 return MI.getOperand(0).getReg();
Dylan McKay6d8078f2016-05-06 10:12:31 +000091 }
92 break;
93 }
94 default:
95 break;
96 }
97
98 return 0;
99}
100
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000101unsigned AVRInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
Dylan McKay6d8078f2016-05-06 10:12:31 +0000102 int &FrameIndex) const {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000103 switch (MI.getOpcode()) {
Dylan McKay6d8078f2016-05-06 10:12:31 +0000104 case AVR::STDPtrQRr:
105 case AVR::STDWPtrQRr: {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000106 if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
107 MI.getOperand(1).getImm() == 0) {
108 FrameIndex = MI.getOperand(0).getIndex();
109 return MI.getOperand(2).getReg();
Dylan McKay6d8078f2016-05-06 10:12:31 +0000110 }
111 break;
112 }
113 default:
114 break;
115 }
116
117 return 0;
118}
119
120void AVRInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
121 MachineBasicBlock::iterator MI,
122 unsigned SrcReg, bool isKill,
123 int FrameIndex,
124 const TargetRegisterClass *RC,
125 const TargetRegisterInfo *TRI) const {
126 MachineFunction &MF = *MBB.getParent();
Dylan McKayafff1692016-10-05 13:38:29 +0000127 AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
128
129 AFI->setHasSpills(true);
Dylan McKay6d8078f2016-05-06 10:12:31 +0000130
131 DebugLoc DL;
132 if (MI != MBB.end()) {
133 DL = MI->getDebugLoc();
134 }
135
Matthias Braun941a7052016-07-28 18:40:00 +0000136 const MachineFrameInfo &MFI = MF.getFrameInfo();
Dylan McKay6d8078f2016-05-06 10:12:31 +0000137
138 MachineMemOperand *MMO = MF.getMachineMemOperand(
139 MachinePointerInfo::getFixedStack(MF, FrameIndex),
140 MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),
141 MFI.getObjectAlignment(FrameIndex));
142
143 unsigned Opcode = 0;
Krzysztof Parzyszekc8e8e2a2017-04-24 19:51:12 +0000144 if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {
Dylan McKay6d8078f2016-05-06 10:12:31 +0000145 Opcode = AVR::STDPtrQRr;
Krzysztof Parzyszekc8e8e2a2017-04-24 19:51:12 +0000146 } else if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {
Dylan McKay6d8078f2016-05-06 10:12:31 +0000147 Opcode = AVR::STDWPtrQRr;
148 } else {
149 llvm_unreachable("Cannot store this register into a stack slot!");
150 }
151
152 BuildMI(MBB, MI, DL, get(Opcode))
153 .addFrameIndex(FrameIndex)
154 .addImm(0)
155 .addReg(SrcReg, getKillRegState(isKill))
156 .addMemOperand(MMO);
157}
158
159void AVRInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
160 MachineBasicBlock::iterator MI,
161 unsigned DestReg, int FrameIndex,
162 const TargetRegisterClass *RC,
163 const TargetRegisterInfo *TRI) const {
164 DebugLoc DL;
165 if (MI != MBB.end()) {
166 DL = MI->getDebugLoc();
167 }
168
169 MachineFunction &MF = *MBB.getParent();
Matthias Braun941a7052016-07-28 18:40:00 +0000170 const MachineFrameInfo &MFI = MF.getFrameInfo();
Dylan McKay6d8078f2016-05-06 10:12:31 +0000171
172 MachineMemOperand *MMO = MF.getMachineMemOperand(
173 MachinePointerInfo::getFixedStack(MF, FrameIndex),
174 MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
175 MFI.getObjectAlignment(FrameIndex));
176
177 unsigned Opcode = 0;
Krzysztof Parzyszekc8e8e2a2017-04-24 19:51:12 +0000178 if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {
Dylan McKay6d8078f2016-05-06 10:12:31 +0000179 Opcode = AVR::LDDRdPtrQ;
Krzysztof Parzyszekc8e8e2a2017-04-24 19:51:12 +0000180 } else if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {
Dylan McKay6d8078f2016-05-06 10:12:31 +0000181 // Opcode = AVR::LDDWRdPtrQ;
182 //:FIXME: remove this once PR13375 gets fixed
183 Opcode = AVR::LDDWRdYQ;
184 } else {
185 llvm_unreachable("Cannot load this register from a stack slot!");
186 }
187
188 BuildMI(MBB, MI, DL, get(Opcode), DestReg)
189 .addFrameIndex(FrameIndex)
190 .addImm(0)
191 .addMemOperand(MMO);
192}
193
194const MCInstrDesc &AVRInstrInfo::getBrCond(AVRCC::CondCodes CC) const {
195 switch (CC) {
196 default:
197 llvm_unreachable("Unknown condition code!");
198 case AVRCC::COND_EQ:
199 return get(AVR::BREQk);
200 case AVRCC::COND_NE:
201 return get(AVR::BRNEk);
202 case AVRCC::COND_GE:
203 return get(AVR::BRGEk);
204 case AVRCC::COND_LT:
205 return get(AVR::BRLTk);
206 case AVRCC::COND_SH:
207 return get(AVR::BRSHk);
208 case AVRCC::COND_LO:
209 return get(AVR::BRLOk);
210 case AVRCC::COND_MI:
211 return get(AVR::BRMIk);
212 case AVRCC::COND_PL:
213 return get(AVR::BRPLk);
214 }
215}
216
217AVRCC::CondCodes AVRInstrInfo::getCondFromBranchOpc(unsigned Opc) const {
218 switch (Opc) {
219 default:
220 return AVRCC::COND_INVALID;
221 case AVR::BREQk:
222 return AVRCC::COND_EQ;
223 case AVR::BRNEk:
224 return AVRCC::COND_NE;
225 case AVR::BRSHk:
226 return AVRCC::COND_SH;
227 case AVR::BRLOk:
228 return AVRCC::COND_LO;
229 case AVR::BRMIk:
230 return AVRCC::COND_MI;
231 case AVR::BRPLk:
232 return AVRCC::COND_PL;
233 case AVR::BRGEk:
234 return AVRCC::COND_GE;
235 case AVR::BRLTk:
236 return AVRCC::COND_LT;
237 }
238}
239
240AVRCC::CondCodes AVRInstrInfo::getOppositeCondition(AVRCC::CondCodes CC) const {
241 switch (CC) {
242 default:
243 llvm_unreachable("Invalid condition!");
244 case AVRCC::COND_EQ:
245 return AVRCC::COND_NE;
246 case AVRCC::COND_NE:
247 return AVRCC::COND_EQ;
248 case AVRCC::COND_SH:
249 return AVRCC::COND_LO;
250 case AVRCC::COND_LO:
251 return AVRCC::COND_SH;
252 case AVRCC::COND_GE:
253 return AVRCC::COND_LT;
254 case AVRCC::COND_LT:
255 return AVRCC::COND_GE;
256 case AVRCC::COND_MI:
257 return AVRCC::COND_PL;
258 case AVRCC::COND_PL:
259 return AVRCC::COND_MI;
260 }
261}
262
Jacques Pienaar71c30a12016-07-15 14:41:04 +0000263bool AVRInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
Dylan McKay6d8078f2016-05-06 10:12:31 +0000264 MachineBasicBlock *&TBB,
265 MachineBasicBlock *&FBB,
266 SmallVectorImpl<MachineOperand> &Cond,
267 bool AllowModify) const {
268 // Start from the bottom of the block and work up, examining the
269 // terminator instructions.
270 MachineBasicBlock::iterator I = MBB.end();
271 MachineBasicBlock::iterator UnCondBrIter = MBB.end();
272
273 while (I != MBB.begin()) {
274 --I;
Shiva Chen801bf7e2018-05-09 02:42:00 +0000275 if (I->isDebugInstr()) {
Dylan McKay6d8078f2016-05-06 10:12:31 +0000276 continue;
277 }
278
279 // Working from the bottom, when we see a non-terminator
280 // instruction, we're done.
281 if (!isUnpredicatedTerminator(*I)) {
282 break;
283 }
284
285 // A terminator that isn't a branch can't easily be handled
286 // by this analysis.
287 if (!I->getDesc().isBranch()) {
288 return true;
289 }
290
291 // Handle unconditional branches.
292 //:TODO: add here jmp
293 if (I->getOpcode() == AVR::RJMPk) {
294 UnCondBrIter = I;
295
296 if (!AllowModify) {
297 TBB = I->getOperand(0).getMBB();
298 continue;
299 }
300
301 // If the block has any instructions after a JMP, delete them.
302 while (std::next(I) != MBB.end()) {
303 std::next(I)->eraseFromParent();
304 }
305
306 Cond.clear();
307 FBB = 0;
308
309 // Delete the JMP if it's equivalent to a fall-through.
310 if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
311 TBB = 0;
312 I->eraseFromParent();
313 I = MBB.end();
314 UnCondBrIter = MBB.end();
315 continue;
316 }
317
318 // TBB is used to indicate the unconditinal destination.
319 TBB = I->getOperand(0).getMBB();
320 continue;
321 }
322
323 // Handle conditional branches.
324 AVRCC::CondCodes BranchCode = getCondFromBranchOpc(I->getOpcode());
325 if (BranchCode == AVRCC::COND_INVALID) {
326 return true; // Can't handle indirect branch.
327 }
328
329 // Working from the bottom, handle the first conditional branch.
330 if (Cond.empty()) {
331 MachineBasicBlock *TargetBB = I->getOperand(0).getMBB();
332 if (AllowModify && UnCondBrIter != MBB.end() &&
333 MBB.isLayoutSuccessor(TargetBB)) {
334 // If we can modify the code and it ends in something like:
335 //
336 // jCC L1
337 // jmp L2
338 // L1:
339 // ...
340 // L2:
341 //
342 // Then we can change this to:
343 //
344 // jnCC L2
345 // L1:
346 // ...
347 // L2:
348 //
349 // Which is a bit more efficient.
350 // We conditionally jump to the fall-through block.
351 BranchCode = getOppositeCondition(BranchCode);
352 unsigned JNCC = getBrCond(BranchCode).getOpcode();
353 MachineBasicBlock::iterator OldInst = I;
354
355 BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(JNCC))
356 .addMBB(UnCondBrIter->getOperand(0).getMBB());
357 BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(AVR::RJMPk))
358 .addMBB(TargetBB);
359
360 OldInst->eraseFromParent();
361 UnCondBrIter->eraseFromParent();
362
363 // Restart the analysis.
364 UnCondBrIter = MBB.end();
365 I = MBB.end();
366 continue;
367 }
368
369 FBB = TBB;
370 TBB = I->getOperand(0).getMBB();
371 Cond.push_back(MachineOperand::CreateImm(BranchCode));
372 continue;
373 }
374
375 // Handle subsequent conditional branches. Only handle the case where all
376 // conditional branches branch to the same destination.
377 assert(Cond.size() == 1);
378 assert(TBB);
379
380 // Only handle the case where all conditional branches branch to
381 // the same destination.
382 if (TBB != I->getOperand(0).getMBB()) {
383 return true;
384 }
385
386 AVRCC::CondCodes OldBranchCode = (AVRCC::CondCodes)Cond[0].getImm();
387 // If the conditions are the same, we can leave them alone.
388 if (OldBranchCode == BranchCode) {
389 continue;
390 }
391
392 return true;
393 }
394
395 return false;
396}
397
Matt Arsenaulte8e0f5c2016-09-14 17:24:15 +0000398unsigned AVRInstrInfo::insertBranch(MachineBasicBlock &MBB,
Dylan McKay6d8078f2016-05-06 10:12:31 +0000399 MachineBasicBlock *TBB,
400 MachineBasicBlock *FBB,
401 ArrayRef<MachineOperand> Cond,
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000402 const DebugLoc &DL,
403 int *BytesAdded) const {
Dylan McKay9cf1dc12017-07-11 04:17:13 +0000404 if (BytesAdded) *BytesAdded = 0;
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000405
Dylan McKay6d8078f2016-05-06 10:12:31 +0000406 // Shouldn't be a fall through.
Matt Arsenaulte8e0f5c2016-09-14 17:24:15 +0000407 assert(TBB && "insertBranch must not be told to insert a fallthrough");
Dylan McKay6d8078f2016-05-06 10:12:31 +0000408 assert((Cond.size() == 1 || Cond.size() == 0) &&
409 "AVR branch conditions have one component!");
410
411 if (Cond.empty()) {
412 assert(!FBB && "Unconditional branch with multiple successors!");
Dylan McKay9cf1dc12017-07-11 04:17:13 +0000413 auto &MI = *BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(TBB);
414 if (BytesAdded)
415 *BytesAdded += getInstSizeInBytes(MI);
Dylan McKay6d8078f2016-05-06 10:12:31 +0000416 return 1;
417 }
418
419 // Conditional branch.
420 unsigned Count = 0;
421 AVRCC::CondCodes CC = (AVRCC::CondCodes)Cond[0].getImm();
Dylan McKay9cf1dc12017-07-11 04:17:13 +0000422 auto &CondMI = *BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);
423
424 if (BytesAdded) *BytesAdded += getInstSizeInBytes(CondMI);
Dylan McKay6d8078f2016-05-06 10:12:31 +0000425 ++Count;
426
427 if (FBB) {
428 // Two-way Conditional branch. Insert the second branch.
Dylan McKay9cf1dc12017-07-11 04:17:13 +0000429 auto &MI = *BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(FBB);
430 if (BytesAdded) *BytesAdded += getInstSizeInBytes(MI);
Dylan McKay6d8078f2016-05-06 10:12:31 +0000431 ++Count;
432 }
433
434 return Count;
435}
436
Matt Arsenault1b9fc8e2016-09-14 20:43:16 +0000437unsigned AVRInstrInfo::removeBranch(MachineBasicBlock &MBB,
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000438 int *BytesRemoved) const {
Dylan McKay9cf1dc12017-07-11 04:17:13 +0000439 if (BytesRemoved) *BytesRemoved = 0;
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000440
Dylan McKay6d8078f2016-05-06 10:12:31 +0000441 MachineBasicBlock::iterator I = MBB.end();
442 unsigned Count = 0;
443
444 while (I != MBB.begin()) {
445 --I;
Shiva Chen801bf7e2018-05-09 02:42:00 +0000446 if (I->isDebugInstr()) {
Dylan McKay6d8078f2016-05-06 10:12:31 +0000447 continue;
448 }
449 //:TODO: add here the missing jmp instructions once they are implemented
450 // like jmp, {e}ijmp, and other cond branches, ...
451 if (I->getOpcode() != AVR::RJMPk &&
452 getCondFromBranchOpc(I->getOpcode()) == AVRCC::COND_INVALID) {
453 break;
454 }
455
456 // Remove the branch.
Dylan McKay9cf1dc12017-07-11 04:17:13 +0000457 if (BytesRemoved) *BytesRemoved += getInstSizeInBytes(*I);
Dylan McKay6d8078f2016-05-06 10:12:31 +0000458 I->eraseFromParent();
459 I = MBB.end();
460 ++Count;
461 }
462
463 return Count;
464}
465
Matt Arsenault1b9fc8e2016-09-14 20:43:16 +0000466bool AVRInstrInfo::reverseBranchCondition(
Dylan McKay6d8078f2016-05-06 10:12:31 +0000467 SmallVectorImpl<MachineOperand> &Cond) const {
468 assert(Cond.size() == 1 && "Invalid AVR branch condition!");
469
470 AVRCC::CondCodes CC = static_cast<AVRCC::CondCodes>(Cond[0].getImm());
471 Cond[0].setImm(getOppositeCondition(CC));
472
473 return false;
474}
475
Job Noorman6cd8c9a2016-08-16 08:41:35 +0000476unsigned AVRInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
477 unsigned Opcode = MI.getOpcode();
Dylan McKay6d8078f2016-05-06 10:12:31 +0000478
479 switch (Opcode) {
480 // A regular instruction
481 default: {
482 const MCInstrDesc &Desc = get(Opcode);
483 return Desc.getSize();
484 }
485 case TargetOpcode::EH_LABEL:
486 case TargetOpcode::IMPLICIT_DEF:
487 case TargetOpcode::KILL:
488 case TargetOpcode::DBG_VALUE:
489 return 0;
Craig Topper784929d2019-02-08 20:48:56 +0000490 case TargetOpcode::INLINEASM:
491 case TargetOpcode::INLINEASM_BR: {
Dylan McKayafff1692016-10-05 13:38:29 +0000492 const MachineFunction &MF = *MI.getParent()->getParent();
493 const AVRTargetMachine &TM = static_cast<const AVRTargetMachine&>(MF.getTarget());
494 const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
495 const TargetInstrInfo &TII = *STI.getInstrInfo();
496
Job Noorman6cd8c9a2016-08-16 08:41:35 +0000497 return TII.getInlineAsmLength(MI.getOperand(0).getSymbolName(),
Dylan McKay6d8078f2016-05-06 10:12:31 +0000498 *TM.getMCAsmInfo());
499 }
500 }
501}
502
Dylan McKay9cf1dc12017-07-11 04:17:13 +0000503MachineBasicBlock *
504AVRInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
505 switch (MI.getOpcode()) {
506 default:
507 llvm_unreachable("unexpected opcode!");
508 case AVR::JMPk:
509 case AVR::CALLk:
510 case AVR::RCALLk:
511 case AVR::RJMPk:
512 case AVR::BREQk:
513 case AVR::BRNEk:
514 case AVR::BRSHk:
515 case AVR::BRLOk:
516 case AVR::BRMIk:
517 case AVR::BRPLk:
518 case AVR::BRGEk:
519 case AVR::BRLTk:
520 return MI.getOperand(0).getMBB();
521 case AVR::BRBSsk:
522 case AVR::BRBCsk:
523 return MI.getOperand(1).getMBB();
524 case AVR::SBRCRrB:
525 case AVR::SBRSRrB:
526 case AVR::SBICAb:
527 case AVR::SBISAb:
528 llvm_unreachable("unimplemented branch instructions");
529 }
530}
531
532bool AVRInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
533 int64_t BrOffset) const {
534
535 switch (BranchOp) {
536 default:
537 llvm_unreachable("unexpected opcode!");
538 case AVR::JMPk:
539 case AVR::CALLk:
Dylan McKay39069202017-10-04 09:51:28 +0000540 return true;
Dylan McKay9cf1dc12017-07-11 04:17:13 +0000541 case AVR::RCALLk:
542 case AVR::RJMPk:
543 return isIntN(13, BrOffset);
544 case AVR::BRBSsk:
545 case AVR::BRBCsk:
546 case AVR::BREQk:
547 case AVR::BRNEk:
548 case AVR::BRSHk:
549 case AVR::BRLOk:
550 case AVR::BRMIk:
551 case AVR::BRPLk:
552 case AVR::BRGEk:
553 case AVR::BRLTk:
554 return isIntN(7, BrOffset);
555 }
556}
557
Dylan McKay39069202017-10-04 09:51:28 +0000558unsigned AVRInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
559 MachineBasicBlock &NewDestBB,
560 const DebugLoc &DL,
561 int64_t BrOffset,
562 RegScavenger *RS) const {
563 // This method inserts a *direct* branch (JMP), despite its name.
564 // LLVM calls this method to fixup unconditional branches; it never calls
565 // insertBranch or some hypothetical "insertDirectBranch".
566 // See lib/CodeGen/RegisterRelaxation.cpp for details.
567 // We end up here when a jump is too long for a RJMP instruction.
568 auto &MI = *BuildMI(&MBB, DL, get(AVR::JMPk)).addMBB(&NewDestBB);
569
570 return getInstSizeInBytes(MI);
571}
572
Dylan McKay6d8078f2016-05-06 10:12:31 +0000573} // end of namespace llvm
Dylan McKayafff1692016-10-05 13:38:29 +0000574