blob: 0c32334167f06be62239e3516777ef86411e1b85 [file] [log] [blame]
Dylan McKay6d8078f2016-05-06 10:12:31 +00001//===-- AVRInstrInfo.cpp - AVR Instruction Information --------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the AVR implementation of the TargetInstrInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AVRInstrInfo.h"
15
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/CodeGen/MachineConstantPool.h"
18#include "llvm/CodeGen/MachineFrameInfo.h"
19#include "llvm/CodeGen/MachineInstrBuilder.h"
20#include "llvm/CodeGen/MachineMemOperand.h"
21#include "llvm/IR/Constants.h"
22#include "llvm/IR/Function.h"
23#include "llvm/MC/MCContext.h"
24#include "llvm/Support/Debug.h"
25#include "llvm/Support/ErrorHandling.h"
26#include "llvm/Support/TargetRegistry.h"
27
28#include "AVR.h"
29#include "AVRMachineFunctionInfo.h"
Dylan McKayafff1692016-10-05 13:38:29 +000030#include "AVRRegisterInfo.h"
Dylan McKay6d8078f2016-05-06 10:12:31 +000031#include "AVRTargetMachine.h"
32#include "MCTargetDesc/AVRMCTargetDesc.h"
33
34#define GET_INSTRINFO_CTOR_DTOR
35#include "AVRGenInstrInfo.inc"
36
37namespace llvm {
38
39AVRInstrInfo::AVRInstrInfo()
40 : AVRGenInstrInfo(AVR::ADJCALLSTACKDOWN, AVR::ADJCALLSTACKUP), RI() {}
41
42void AVRInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
Benjamin Kramerbdc49562016-06-12 15:39:02 +000043 MachineBasicBlock::iterator MI,
44 const DebugLoc &DL, unsigned DestReg,
45 unsigned SrcReg, bool KillSrc) const {
Dylan McKayafff1692016-10-05 13:38:29 +000046 const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
47 const AVRRegisterInfo &TRI = *STI.getRegisterInfo();
Dylan McKay6d8078f2016-05-06 10:12:31 +000048 unsigned Opc;
49
Dylan McKayafff1692016-10-05 13:38:29 +000050 // Not all AVR devices support the 16-bit `MOVW` instruction.
51 if (AVR::DREGSRegClass.contains(DestReg, SrcReg)) {
52 if (STI.hasMOVW()) {
53 BuildMI(MBB, MI, DL, get(AVR::MOVWRdRr), DestReg)
54 .addReg(SrcReg, getKillRegState(KillSrc));
55 } else {
56 unsigned DestLo, DestHi, SrcLo, SrcHi;
Dylan McKay6d8078f2016-05-06 10:12:31 +000057
Dylan McKayafff1692016-10-05 13:38:29 +000058 TRI.splitReg(DestReg, DestLo, DestHi);
59 TRI.splitReg(SrcReg, SrcLo, SrcHi);
60
61 // Copy each individual register with the `MOV` instruction.
62 BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestLo)
63 .addReg(SrcLo, getKillRegState(KillSrc));
64 BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestHi)
65 .addReg(SrcHi, getKillRegState(KillSrc));
66 }
67 } else {
68 if (AVR::GPR8RegClass.contains(DestReg, SrcReg)) {
69 Opc = AVR::MOVRdRr;
70 } else if (SrcReg == AVR::SP && AVR::DREGSRegClass.contains(DestReg)) {
71 Opc = AVR::SPREAD;
72 } else if (DestReg == AVR::SP && AVR::DREGSRegClass.contains(SrcReg)) {
73 Opc = AVR::SPWRITE;
74 } else {
75 llvm_unreachable("Impossible reg-to-reg copy");
76 }
77
78 BuildMI(MBB, MI, DL, get(Opc), DestReg)
79 .addReg(SrcReg, getKillRegState(KillSrc));
80 }
Dylan McKay6d8078f2016-05-06 10:12:31 +000081}
82
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +000083unsigned AVRInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
Dylan McKay6d8078f2016-05-06 10:12:31 +000084 int &FrameIndex) const {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +000085 switch (MI.getOpcode()) {
Dylan McKay6d8078f2016-05-06 10:12:31 +000086 case AVR::LDDRdPtrQ:
87 case AVR::LDDWRdYQ: { //:FIXME: remove this once PR13375 gets fixed
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +000088 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
89 MI.getOperand(2).getImm() == 0) {
90 FrameIndex = MI.getOperand(1).getIndex();
91 return MI.getOperand(0).getReg();
Dylan McKay6d8078f2016-05-06 10:12:31 +000092 }
93 break;
94 }
95 default:
96 break;
97 }
98
99 return 0;
100}
101
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000102unsigned AVRInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
Dylan McKay6d8078f2016-05-06 10:12:31 +0000103 int &FrameIndex) const {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000104 switch (MI.getOpcode()) {
Dylan McKay6d8078f2016-05-06 10:12:31 +0000105 case AVR::STDPtrQRr:
106 case AVR::STDWPtrQRr: {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000107 if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
108 MI.getOperand(1).getImm() == 0) {
109 FrameIndex = MI.getOperand(0).getIndex();
110 return MI.getOperand(2).getReg();
Dylan McKay6d8078f2016-05-06 10:12:31 +0000111 }
112 break;
113 }
114 default:
115 break;
116 }
117
118 return 0;
119}
120
121void AVRInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
122 MachineBasicBlock::iterator MI,
123 unsigned SrcReg, bool isKill,
124 int FrameIndex,
125 const TargetRegisterClass *RC,
126 const TargetRegisterInfo *TRI) const {
127 MachineFunction &MF = *MBB.getParent();
Dylan McKayafff1692016-10-05 13:38:29 +0000128 AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
129
130 AFI->setHasSpills(true);
Dylan McKay6d8078f2016-05-06 10:12:31 +0000131
132 DebugLoc DL;
133 if (MI != MBB.end()) {
134 DL = MI->getDebugLoc();
135 }
136
Matthias Braun941a7052016-07-28 18:40:00 +0000137 const MachineFrameInfo &MFI = MF.getFrameInfo();
Dylan McKay6d8078f2016-05-06 10:12:31 +0000138
139 MachineMemOperand *MMO = MF.getMachineMemOperand(
140 MachinePointerInfo::getFixedStack(MF, FrameIndex),
141 MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),
142 MFI.getObjectAlignment(FrameIndex));
143
144 unsigned Opcode = 0;
Krzysztof Parzyszekc8e8e2a2017-04-24 19:51:12 +0000145 if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {
Dylan McKay6d8078f2016-05-06 10:12:31 +0000146 Opcode = AVR::STDPtrQRr;
Krzysztof Parzyszekc8e8e2a2017-04-24 19:51:12 +0000147 } else if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {
Dylan McKay6d8078f2016-05-06 10:12:31 +0000148 Opcode = AVR::STDWPtrQRr;
149 } else {
150 llvm_unreachable("Cannot store this register into a stack slot!");
151 }
152
153 BuildMI(MBB, MI, DL, get(Opcode))
154 .addFrameIndex(FrameIndex)
155 .addImm(0)
156 .addReg(SrcReg, getKillRegState(isKill))
157 .addMemOperand(MMO);
158}
159
160void AVRInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
161 MachineBasicBlock::iterator MI,
162 unsigned DestReg, int FrameIndex,
163 const TargetRegisterClass *RC,
164 const TargetRegisterInfo *TRI) const {
165 DebugLoc DL;
166 if (MI != MBB.end()) {
167 DL = MI->getDebugLoc();
168 }
169
170 MachineFunction &MF = *MBB.getParent();
Matthias Braun941a7052016-07-28 18:40:00 +0000171 const MachineFrameInfo &MFI = MF.getFrameInfo();
Dylan McKay6d8078f2016-05-06 10:12:31 +0000172
173 MachineMemOperand *MMO = MF.getMachineMemOperand(
174 MachinePointerInfo::getFixedStack(MF, FrameIndex),
175 MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
176 MFI.getObjectAlignment(FrameIndex));
177
178 unsigned Opcode = 0;
Krzysztof Parzyszekc8e8e2a2017-04-24 19:51:12 +0000179 if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {
Dylan McKay6d8078f2016-05-06 10:12:31 +0000180 Opcode = AVR::LDDRdPtrQ;
Krzysztof Parzyszekc8e8e2a2017-04-24 19:51:12 +0000181 } else if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {
Dylan McKay6d8078f2016-05-06 10:12:31 +0000182 // Opcode = AVR::LDDWRdPtrQ;
183 //:FIXME: remove this once PR13375 gets fixed
184 Opcode = AVR::LDDWRdYQ;
185 } else {
186 llvm_unreachable("Cannot load this register from a stack slot!");
187 }
188
189 BuildMI(MBB, MI, DL, get(Opcode), DestReg)
190 .addFrameIndex(FrameIndex)
191 .addImm(0)
192 .addMemOperand(MMO);
193}
194
195const MCInstrDesc &AVRInstrInfo::getBrCond(AVRCC::CondCodes CC) const {
196 switch (CC) {
197 default:
198 llvm_unreachable("Unknown condition code!");
199 case AVRCC::COND_EQ:
200 return get(AVR::BREQk);
201 case AVRCC::COND_NE:
202 return get(AVR::BRNEk);
203 case AVRCC::COND_GE:
204 return get(AVR::BRGEk);
205 case AVRCC::COND_LT:
206 return get(AVR::BRLTk);
207 case AVRCC::COND_SH:
208 return get(AVR::BRSHk);
209 case AVRCC::COND_LO:
210 return get(AVR::BRLOk);
211 case AVRCC::COND_MI:
212 return get(AVR::BRMIk);
213 case AVRCC::COND_PL:
214 return get(AVR::BRPLk);
215 }
216}
217
218AVRCC::CondCodes AVRInstrInfo::getCondFromBranchOpc(unsigned Opc) const {
219 switch (Opc) {
220 default:
221 return AVRCC::COND_INVALID;
222 case AVR::BREQk:
223 return AVRCC::COND_EQ;
224 case AVR::BRNEk:
225 return AVRCC::COND_NE;
226 case AVR::BRSHk:
227 return AVRCC::COND_SH;
228 case AVR::BRLOk:
229 return AVRCC::COND_LO;
230 case AVR::BRMIk:
231 return AVRCC::COND_MI;
232 case AVR::BRPLk:
233 return AVRCC::COND_PL;
234 case AVR::BRGEk:
235 return AVRCC::COND_GE;
236 case AVR::BRLTk:
237 return AVRCC::COND_LT;
238 }
239}
240
241AVRCC::CondCodes AVRInstrInfo::getOppositeCondition(AVRCC::CondCodes CC) const {
242 switch (CC) {
243 default:
244 llvm_unreachable("Invalid condition!");
245 case AVRCC::COND_EQ:
246 return AVRCC::COND_NE;
247 case AVRCC::COND_NE:
248 return AVRCC::COND_EQ;
249 case AVRCC::COND_SH:
250 return AVRCC::COND_LO;
251 case AVRCC::COND_LO:
252 return AVRCC::COND_SH;
253 case AVRCC::COND_GE:
254 return AVRCC::COND_LT;
255 case AVRCC::COND_LT:
256 return AVRCC::COND_GE;
257 case AVRCC::COND_MI:
258 return AVRCC::COND_PL;
259 case AVRCC::COND_PL:
260 return AVRCC::COND_MI;
261 }
262}
263
Jacques Pienaar71c30a12016-07-15 14:41:04 +0000264bool AVRInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
Dylan McKay6d8078f2016-05-06 10:12:31 +0000265 MachineBasicBlock *&TBB,
266 MachineBasicBlock *&FBB,
267 SmallVectorImpl<MachineOperand> &Cond,
268 bool AllowModify) const {
269 // Start from the bottom of the block and work up, examining the
270 // terminator instructions.
271 MachineBasicBlock::iterator I = MBB.end();
272 MachineBasicBlock::iterator UnCondBrIter = MBB.end();
273
274 while (I != MBB.begin()) {
275 --I;
Shiva Chen801bf7e2018-05-09 02:42:00 +0000276 if (I->isDebugInstr()) {
Dylan McKay6d8078f2016-05-06 10:12:31 +0000277 continue;
278 }
279
280 // Working from the bottom, when we see a non-terminator
281 // instruction, we're done.
282 if (!isUnpredicatedTerminator(*I)) {
283 break;
284 }
285
286 // A terminator that isn't a branch can't easily be handled
287 // by this analysis.
288 if (!I->getDesc().isBranch()) {
289 return true;
290 }
291
292 // Handle unconditional branches.
293 //:TODO: add here jmp
294 if (I->getOpcode() == AVR::RJMPk) {
295 UnCondBrIter = I;
296
297 if (!AllowModify) {
298 TBB = I->getOperand(0).getMBB();
299 continue;
300 }
301
302 // If the block has any instructions after a JMP, delete them.
303 while (std::next(I) != MBB.end()) {
304 std::next(I)->eraseFromParent();
305 }
306
307 Cond.clear();
308 FBB = 0;
309
310 // Delete the JMP if it's equivalent to a fall-through.
311 if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
312 TBB = 0;
313 I->eraseFromParent();
314 I = MBB.end();
315 UnCondBrIter = MBB.end();
316 continue;
317 }
318
319 // TBB is used to indicate the unconditinal destination.
320 TBB = I->getOperand(0).getMBB();
321 continue;
322 }
323
324 // Handle conditional branches.
325 AVRCC::CondCodes BranchCode = getCondFromBranchOpc(I->getOpcode());
326 if (BranchCode == AVRCC::COND_INVALID) {
327 return true; // Can't handle indirect branch.
328 }
329
330 // Working from the bottom, handle the first conditional branch.
331 if (Cond.empty()) {
332 MachineBasicBlock *TargetBB = I->getOperand(0).getMBB();
333 if (AllowModify && UnCondBrIter != MBB.end() &&
334 MBB.isLayoutSuccessor(TargetBB)) {
335 // If we can modify the code and it ends in something like:
336 //
337 // jCC L1
338 // jmp L2
339 // L1:
340 // ...
341 // L2:
342 //
343 // Then we can change this to:
344 //
345 // jnCC L2
346 // L1:
347 // ...
348 // L2:
349 //
350 // Which is a bit more efficient.
351 // We conditionally jump to the fall-through block.
352 BranchCode = getOppositeCondition(BranchCode);
353 unsigned JNCC = getBrCond(BranchCode).getOpcode();
354 MachineBasicBlock::iterator OldInst = I;
355
356 BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(JNCC))
357 .addMBB(UnCondBrIter->getOperand(0).getMBB());
358 BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(AVR::RJMPk))
359 .addMBB(TargetBB);
360
361 OldInst->eraseFromParent();
362 UnCondBrIter->eraseFromParent();
363
364 // Restart the analysis.
365 UnCondBrIter = MBB.end();
366 I = MBB.end();
367 continue;
368 }
369
370 FBB = TBB;
371 TBB = I->getOperand(0).getMBB();
372 Cond.push_back(MachineOperand::CreateImm(BranchCode));
373 continue;
374 }
375
376 // Handle subsequent conditional branches. Only handle the case where all
377 // conditional branches branch to the same destination.
378 assert(Cond.size() == 1);
379 assert(TBB);
380
381 // Only handle the case where all conditional branches branch to
382 // the same destination.
383 if (TBB != I->getOperand(0).getMBB()) {
384 return true;
385 }
386
387 AVRCC::CondCodes OldBranchCode = (AVRCC::CondCodes)Cond[0].getImm();
388 // If the conditions are the same, we can leave them alone.
389 if (OldBranchCode == BranchCode) {
390 continue;
391 }
392
393 return true;
394 }
395
396 return false;
397}
398
Matt Arsenaulte8e0f5c2016-09-14 17:24:15 +0000399unsigned AVRInstrInfo::insertBranch(MachineBasicBlock &MBB,
Dylan McKay6d8078f2016-05-06 10:12:31 +0000400 MachineBasicBlock *TBB,
401 MachineBasicBlock *FBB,
402 ArrayRef<MachineOperand> Cond,
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000403 const DebugLoc &DL,
404 int *BytesAdded) const {
Dylan McKay9cf1dc12017-07-11 04:17:13 +0000405 if (BytesAdded) *BytesAdded = 0;
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000406
Dylan McKay6d8078f2016-05-06 10:12:31 +0000407 // Shouldn't be a fall through.
Matt Arsenaulte8e0f5c2016-09-14 17:24:15 +0000408 assert(TBB && "insertBranch must not be told to insert a fallthrough");
Dylan McKay6d8078f2016-05-06 10:12:31 +0000409 assert((Cond.size() == 1 || Cond.size() == 0) &&
410 "AVR branch conditions have one component!");
411
412 if (Cond.empty()) {
413 assert(!FBB && "Unconditional branch with multiple successors!");
Dylan McKay9cf1dc12017-07-11 04:17:13 +0000414 auto &MI = *BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(TBB);
415 if (BytesAdded)
416 *BytesAdded += getInstSizeInBytes(MI);
Dylan McKay6d8078f2016-05-06 10:12:31 +0000417 return 1;
418 }
419
420 // Conditional branch.
421 unsigned Count = 0;
422 AVRCC::CondCodes CC = (AVRCC::CondCodes)Cond[0].getImm();
Dylan McKay9cf1dc12017-07-11 04:17:13 +0000423 auto &CondMI = *BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);
424
425 if (BytesAdded) *BytesAdded += getInstSizeInBytes(CondMI);
Dylan McKay6d8078f2016-05-06 10:12:31 +0000426 ++Count;
427
428 if (FBB) {
429 // Two-way Conditional branch. Insert the second branch.
Dylan McKay9cf1dc12017-07-11 04:17:13 +0000430 auto &MI = *BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(FBB);
431 if (BytesAdded) *BytesAdded += getInstSizeInBytes(MI);
Dylan McKay6d8078f2016-05-06 10:12:31 +0000432 ++Count;
433 }
434
435 return Count;
436}
437
Matt Arsenault1b9fc8e2016-09-14 20:43:16 +0000438unsigned AVRInstrInfo::removeBranch(MachineBasicBlock &MBB,
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000439 int *BytesRemoved) const {
Dylan McKay9cf1dc12017-07-11 04:17:13 +0000440 if (BytesRemoved) *BytesRemoved = 0;
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000441
Dylan McKay6d8078f2016-05-06 10:12:31 +0000442 MachineBasicBlock::iterator I = MBB.end();
443 unsigned Count = 0;
444
445 while (I != MBB.begin()) {
446 --I;
Shiva Chen801bf7e2018-05-09 02:42:00 +0000447 if (I->isDebugInstr()) {
Dylan McKay6d8078f2016-05-06 10:12:31 +0000448 continue;
449 }
450 //:TODO: add here the missing jmp instructions once they are implemented
451 // like jmp, {e}ijmp, and other cond branches, ...
452 if (I->getOpcode() != AVR::RJMPk &&
453 getCondFromBranchOpc(I->getOpcode()) == AVRCC::COND_INVALID) {
454 break;
455 }
456
457 // Remove the branch.
Dylan McKay9cf1dc12017-07-11 04:17:13 +0000458 if (BytesRemoved) *BytesRemoved += getInstSizeInBytes(*I);
Dylan McKay6d8078f2016-05-06 10:12:31 +0000459 I->eraseFromParent();
460 I = MBB.end();
461 ++Count;
462 }
463
464 return Count;
465}
466
Matt Arsenault1b9fc8e2016-09-14 20:43:16 +0000467bool AVRInstrInfo::reverseBranchCondition(
Dylan McKay6d8078f2016-05-06 10:12:31 +0000468 SmallVectorImpl<MachineOperand> &Cond) const {
469 assert(Cond.size() == 1 && "Invalid AVR branch condition!");
470
471 AVRCC::CondCodes CC = static_cast<AVRCC::CondCodes>(Cond[0].getImm());
472 Cond[0].setImm(getOppositeCondition(CC));
473
474 return false;
475}
476
Job Noorman6cd8c9a2016-08-16 08:41:35 +0000477unsigned AVRInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
478 unsigned Opcode = MI.getOpcode();
Dylan McKay6d8078f2016-05-06 10:12:31 +0000479
480 switch (Opcode) {
481 // A regular instruction
482 default: {
483 const MCInstrDesc &Desc = get(Opcode);
484 return Desc.getSize();
485 }
486 case TargetOpcode::EH_LABEL:
487 case TargetOpcode::IMPLICIT_DEF:
488 case TargetOpcode::KILL:
489 case TargetOpcode::DBG_VALUE:
490 return 0;
491 case TargetOpcode::INLINEASM: {
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