blob: ea4a179c00a968b9c251326c10da2c6ad105ee77 [file] [log] [blame]
Dylan McKaya789f402016-11-16 21:58:04 +00001//===-- AVRExpandPseudoInsts.cpp - Expand pseudo instructions -------------===//
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 a pass that expands pseudo instructions into target
11// instructions. This pass should be run after register allocation but before
12// the post-regalloc scheduling pass.
13//
14//===----------------------------------------------------------------------===//
15
16#include "AVR.h"
17#include "AVRInstrInfo.h"
18#include "AVRTargetMachine.h"
19#include "MCTargetDesc/AVRMCTargetDesc.h"
20
21#include "llvm/CodeGen/MachineFunctionPass.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/MachineRegisterInfo.h"
24#include "llvm/Target/TargetRegisterInfo.h"
25
26using namespace llvm;
27
Dylan McKay8cec7eb2016-12-07 11:08:56 +000028#define AVR_EXPAND_PSEUDO_NAME "AVR pseudo instruction expansion pass"
29
Dylan McKaya789f402016-11-16 21:58:04 +000030namespace {
31
32/// Expands "placeholder" instructions marked as pseudo into
33/// actual AVR instructions.
34class AVRExpandPseudo : public MachineFunctionPass {
35public:
36 static char ID;
37
Dylan McKay8cec7eb2016-12-07 11:08:56 +000038 AVRExpandPseudo() : MachineFunctionPass(ID) {
39 initializeAVRExpandPseudoPass(*PassRegistry::getPassRegistry());
40 }
Dylan McKaya789f402016-11-16 21:58:04 +000041
42 bool runOnMachineFunction(MachineFunction &MF) override;
43
Dylan McKay8cec7eb2016-12-07 11:08:56 +000044 StringRef getPassName() const override { return AVR_EXPAND_PSEUDO_NAME; }
Dylan McKaya789f402016-11-16 21:58:04 +000045
46private:
47 typedef MachineBasicBlock Block;
48 typedef Block::iterator BlockIt;
49
50 const AVRRegisterInfo *TRI;
51 const TargetInstrInfo *TII;
52
53 /// The register to be used for temporary storage.
54 const unsigned SCRATCH_REGISTER = AVR::R0;
55 /// The IO address of the status register.
56 const unsigned SREG_ADDR = 0x3f;
57
58 bool expandMBB(Block &MBB);
59 bool expandMI(Block &MBB, BlockIt MBBI);
60 template <unsigned OP> bool expand(Block &MBB, BlockIt MBBI);
61
62 MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode) {
63 return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode));
64 }
65
66 MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode,
67 unsigned DstReg) {
68 return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode), DstReg);
69 }
70
71 MachineRegisterInfo &getRegInfo(Block &MBB) { return MBB.getParent()->getRegInfo(); }
72
73 bool expandArith(unsigned OpLo, unsigned OpHi, Block &MBB, BlockIt MBBI);
74 bool expandLogic(unsigned Op, Block &MBB, BlockIt MBBI);
75 bool expandLogicImm(unsigned Op, Block &MBB, BlockIt MBBI);
76
77 template<typename Func>
78 bool expandAtomic(Block &MBB, BlockIt MBBI, Func f);
79
80 template<typename Func>
81 bool expandAtomicBinaryOp(unsigned Opcode, Block &MBB, BlockIt MBBI, Func f);
82
83 bool expandAtomicBinaryOp(unsigned Opcode, Block &MBB, BlockIt MBBI);
84
85 bool expandAtomicArithmeticOp(unsigned MemOpcode,
86 unsigned ArithOpcode,
87 Block &MBB,
88 BlockIt MBBI);
89};
90
91char AVRExpandPseudo::ID = 0;
92
Dylan McKaya789f402016-11-16 21:58:04 +000093bool AVRExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
94 bool Modified = false;
95
96 BlockIt MBBI = MBB.begin(), E = MBB.end();
97 while (MBBI != E) {
98 BlockIt NMBBI = std::next(MBBI);
99 Modified |= expandMI(MBB, MBBI);
100 MBBI = NMBBI;
101 }
102
103 return Modified;
104}
105
106bool AVRExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
107 bool Modified = false;
108
109 const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
110 TRI = STI.getRegisterInfo();
111 TII = STI.getInstrInfo();
112
113 for (Block &MBB : MF) {
114 bool ContinueExpanding = true;
115 unsigned ExpandCount = 0;
116
117 // Continue expanding the block until all pseudos are expanded.
118 do {
119 assert(ExpandCount < 10 && "pseudo expand limit reached");
120
121 bool BlockModified = expandMBB(MBB);
122 Modified |= BlockModified;
123 ExpandCount++;
124
125 ContinueExpanding = BlockModified;
126 } while (ContinueExpanding);
127 }
128
129 return Modified;
130}
131
132bool AVRExpandPseudo::
133expandArith(unsigned OpLo, unsigned OpHi, Block &MBB, BlockIt MBBI) {
134 MachineInstr &MI = *MBBI;
135 unsigned SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
136 unsigned DstReg = MI.getOperand(0).getReg();
137 unsigned SrcReg = MI.getOperand(2).getReg();
138 bool DstIsDead = MI.getOperand(0).isDead();
139 bool DstIsKill = MI.getOperand(1).isKill();
140 bool SrcIsKill = MI.getOperand(2).isKill();
141 bool ImpIsDead = MI.getOperand(3).isDead();
142 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
143 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
144
145 buildMI(MBB, MBBI, OpLo)
146 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
147 .addReg(DstLoReg, getKillRegState(DstIsKill))
148 .addReg(SrcLoReg, getKillRegState(SrcIsKill));
149
150 auto MIBHI = buildMI(MBB, MBBI, OpHi)
151 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
152 .addReg(DstHiReg, getKillRegState(DstIsKill))
153 .addReg(SrcHiReg, getKillRegState(SrcIsKill));
154
155 if (ImpIsDead)
156 MIBHI->getOperand(3).setIsDead();
157
158 // SREG is always implicitly killed
159 MIBHI->getOperand(4).setIsKill();
160
161 MI.eraseFromParent();
162 return true;
163}
164
165bool AVRExpandPseudo::
166expandLogic(unsigned Op, Block &MBB, BlockIt MBBI) {
167 MachineInstr &MI = *MBBI;
168 unsigned SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
169 unsigned DstReg = MI.getOperand(0).getReg();
170 unsigned SrcReg = MI.getOperand(2).getReg();
171 bool DstIsDead = MI.getOperand(0).isDead();
172 bool DstIsKill = MI.getOperand(1).isKill();
173 bool SrcIsKill = MI.getOperand(2).isKill();
174 bool ImpIsDead = MI.getOperand(3).isDead();
175 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
176 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
177
178 auto MIBLO = buildMI(MBB, MBBI, Op)
179 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
180 .addReg(DstLoReg, getKillRegState(DstIsKill))
181 .addReg(SrcLoReg, getKillRegState(SrcIsKill));
182
183 // SREG is always implicitly dead
184 MIBLO->getOperand(3).setIsDead();
185
186 auto MIBHI = buildMI(MBB, MBBI, Op)
187 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
188 .addReg(DstHiReg, getKillRegState(DstIsKill))
189 .addReg(SrcHiReg, getKillRegState(SrcIsKill));
190
191 if (ImpIsDead)
192 MIBHI->getOperand(3).setIsDead();
193
194 MI.eraseFromParent();
195 return true;
196}
197
198bool AVRExpandPseudo::
199expandLogicImm(unsigned Op, Block &MBB, BlockIt MBBI) {
200 MachineInstr &MI = *MBBI;
201 unsigned DstLoReg, DstHiReg;
202 unsigned DstReg = MI.getOperand(0).getReg();
203 bool DstIsDead = MI.getOperand(0).isDead();
204 bool SrcIsKill = MI.getOperand(1).isKill();
205 bool ImpIsDead = MI.getOperand(3).isDead();
206 unsigned Imm = MI.getOperand(2).getImm();
207 unsigned Lo8 = Imm & 0xff;
208 unsigned Hi8 = (Imm >> 8) & 0xff;
209 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
210
211 auto MIBLO = buildMI(MBB, MBBI, Op)
212 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
213 .addReg(DstLoReg, getKillRegState(SrcIsKill))
214 .addImm(Lo8);
215
216 // SREG is always implicitly dead
217 MIBLO->getOperand(3).setIsDead();
218
219 auto MIBHI = buildMI(MBB, MBBI, Op)
220 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
221 .addReg(DstHiReg, getKillRegState(SrcIsKill))
222 .addImm(Hi8);
223
224 if (ImpIsDead)
225 MIBHI->getOperand(3).setIsDead();
226
227 MI.eraseFromParent();
228 return true;
229}
230
231template <>
232bool AVRExpandPseudo::expand<AVR::ADDWRdRr>(Block &MBB, BlockIt MBBI) {
233 return expandArith(AVR::ADDRdRr, AVR::ADCRdRr, MBB, MBBI);
234}
235
236template <>
237bool AVRExpandPseudo::expand<AVR::ADCWRdRr>(Block &MBB, BlockIt MBBI) {
238 return expandArith(AVR::ADCRdRr, AVR::ADCRdRr, MBB, MBBI);
239}
240
241template <>
242bool AVRExpandPseudo::expand<AVR::SUBWRdRr>(Block &MBB, BlockIt MBBI) {
243 return expandArith(AVR::SUBRdRr, AVR::SBCRdRr, MBB, MBBI);
244}
245
246template <>
247bool AVRExpandPseudo::expand<AVR::SUBIWRdK>(Block &MBB, BlockIt MBBI) {
248 MachineInstr &MI = *MBBI;
249 unsigned DstLoReg, DstHiReg;
250 unsigned DstReg = MI.getOperand(0).getReg();
251 bool DstIsDead = MI.getOperand(0).isDead();
252 bool SrcIsKill = MI.getOperand(1).isKill();
253 bool ImpIsDead = MI.getOperand(3).isDead();
254 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
255
256 auto MIBLO = buildMI(MBB, MBBI, AVR::SUBIRdK)
257 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
258 .addReg(DstLoReg, getKillRegState(SrcIsKill));
259
260 auto MIBHI = buildMI(MBB, MBBI, AVR::SBCIRdK)
261 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
262 .addReg(DstHiReg, getKillRegState(SrcIsKill));
263
264 switch (MI.getOperand(2).getType()) {
265 case MachineOperand::MO_GlobalAddress: {
266 const GlobalValue *GV = MI.getOperand(2).getGlobal();
267 int64_t Offs = MI.getOperand(2).getOffset();
268 unsigned TF = MI.getOperand(2).getTargetFlags();
269 MIBLO.addGlobalAddress(GV, Offs, TF | AVRII::MO_NEG | AVRII::MO_LO);
270 MIBHI.addGlobalAddress(GV, Offs, TF | AVRII::MO_NEG | AVRII::MO_HI);
271 break;
272 }
273 case MachineOperand::MO_Immediate: {
274 unsigned Imm = MI.getOperand(2).getImm();
275 MIBLO.addImm(Imm & 0xff);
276 MIBHI.addImm((Imm >> 8) & 0xff);
277 break;
278 }
279 default:
280 llvm_unreachable("Unknown operand type!");
281 }
282
283 if (ImpIsDead)
284 MIBHI->getOperand(3).setIsDead();
285
286 // SREG is always implicitly killed
287 MIBHI->getOperand(4).setIsKill();
288
289 MI.eraseFromParent();
290 return true;
291}
292
293template <>
294bool AVRExpandPseudo::expand<AVR::SBCWRdRr>(Block &MBB, BlockIt MBBI) {
295 return expandArith(AVR::SBCRdRr, AVR::SBCRdRr, MBB, MBBI);
296}
297
298template <>
299bool AVRExpandPseudo::expand<AVR::SBCIWRdK>(Block &MBB, BlockIt MBBI) {
300 MachineInstr &MI = *MBBI;
301 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
302 unsigned DstReg = MI.getOperand(0).getReg();
303 bool DstIsDead = MI.getOperand(0).isDead();
304 bool SrcIsKill = MI.getOperand(1).isKill();
305 bool ImpIsDead = MI.getOperand(3).isDead();
306 unsigned Imm = MI.getOperand(2).getImm();
307 unsigned Lo8 = Imm & 0xff;
308 unsigned Hi8 = (Imm >> 8) & 0xff;
309 OpLo = AVR::SBCIRdK;
310 OpHi = AVR::SBCIRdK;
311 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
312
313 auto MIBLO = buildMI(MBB, MBBI, OpLo)
314 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
315 .addReg(DstLoReg, getKillRegState(SrcIsKill))
316 .addImm(Lo8);
317
318 // SREG is always implicitly killed
319 MIBLO->getOperand(4).setIsKill();
320
321 auto MIBHI = buildMI(MBB, MBBI, OpHi)
322 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
323 .addReg(DstHiReg, getKillRegState(SrcIsKill))
324 .addImm(Hi8);
325
326 if (ImpIsDead)
327 MIBHI->getOperand(3).setIsDead();
328
329 // SREG is always implicitly killed
330 MIBHI->getOperand(4).setIsKill();
331
332 MI.eraseFromParent();
333 return true;
334}
335
336template <>
337bool AVRExpandPseudo::expand<AVR::ANDWRdRr>(Block &MBB, BlockIt MBBI) {
338 return expandLogic(AVR::ANDRdRr, MBB, MBBI);
339}
340
341template <>
342bool AVRExpandPseudo::expand<AVR::ANDIWRdK>(Block &MBB, BlockIt MBBI) {
343 return expandLogicImm(AVR::ANDIRdK, MBB, MBBI);
344}
345
346template <>
347bool AVRExpandPseudo::expand<AVR::ORWRdRr>(Block &MBB, BlockIt MBBI) {
348 return expandLogic(AVR::ORRdRr, MBB, MBBI);
349}
350
351template <>
352bool AVRExpandPseudo::expand<AVR::ORIWRdK>(Block &MBB, BlockIt MBBI) {
353 return expandLogicImm(AVR::ORIRdK, MBB, MBBI);
354}
355
356template <>
357bool AVRExpandPseudo::expand<AVR::EORWRdRr>(Block &MBB, BlockIt MBBI) {
358 return expandLogic(AVR::EORRdRr, MBB, MBBI);
359}
360
361template <>
362bool AVRExpandPseudo::expand<AVR::COMWRd>(Block &MBB, BlockIt MBBI) {
363 MachineInstr &MI = *MBBI;
364 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
365 unsigned DstReg = MI.getOperand(0).getReg();
366 bool DstIsDead = MI.getOperand(0).isDead();
367 bool DstIsKill = MI.getOperand(1).isKill();
368 bool ImpIsDead = MI.getOperand(2).isDead();
369 OpLo = AVR::COMRd;
370 OpHi = AVR::COMRd;
371 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
372
373 auto MIBLO = buildMI(MBB, MBBI, OpLo)
374 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
375 .addReg(DstLoReg, getKillRegState(DstIsKill));
376
377 // SREG is always implicitly dead
378 MIBLO->getOperand(2).setIsDead();
379
380 auto MIBHI = buildMI(MBB, MBBI, OpHi)
381 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
382 .addReg(DstHiReg, getKillRegState(DstIsKill));
383
384 if (ImpIsDead)
385 MIBHI->getOperand(2).setIsDead();
386
387 MI.eraseFromParent();
388 return true;
389}
390
391template <>
392bool AVRExpandPseudo::expand<AVR::CPWRdRr>(Block &MBB, BlockIt MBBI) {
393 MachineInstr &MI = *MBBI;
394 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
395 unsigned DstReg = MI.getOperand(0).getReg();
396 unsigned SrcReg = MI.getOperand(1).getReg();
397 bool DstIsKill = MI.getOperand(0).isKill();
398 bool SrcIsKill = MI.getOperand(1).isKill();
399 bool ImpIsDead = MI.getOperand(2).isDead();
400 OpLo = AVR::CPRdRr;
401 OpHi = AVR::CPCRdRr;
402 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
403 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
404
405 // Low part
406 buildMI(MBB, MBBI, OpLo)
407 .addReg(DstLoReg, getKillRegState(DstIsKill))
408 .addReg(SrcLoReg, getKillRegState(SrcIsKill));
409
410 auto MIBHI = buildMI(MBB, MBBI, OpHi)
411 .addReg(DstHiReg, getKillRegState(DstIsKill))
412 .addReg(SrcHiReg, getKillRegState(SrcIsKill));
413
414 if (ImpIsDead)
415 MIBHI->getOperand(2).setIsDead();
416
417 // SREG is always implicitly killed
418 MIBHI->getOperand(3).setIsKill();
419
420 MI.eraseFromParent();
421 return true;
422}
423
424template <>
425bool AVRExpandPseudo::expand<AVR::CPCWRdRr>(Block &MBB, BlockIt MBBI) {
426 MachineInstr &MI = *MBBI;
427 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
428 unsigned DstReg = MI.getOperand(0).getReg();
429 unsigned SrcReg = MI.getOperand(1).getReg();
430 bool DstIsKill = MI.getOperand(0).isKill();
431 bool SrcIsKill = MI.getOperand(1).isKill();
432 bool ImpIsDead = MI.getOperand(2).isDead();
433 OpLo = AVR::CPCRdRr;
434 OpHi = AVR::CPCRdRr;
435 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
436 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
437
438 auto MIBLO = buildMI(MBB, MBBI, OpLo)
439 .addReg(DstLoReg, getKillRegState(DstIsKill))
440 .addReg(SrcLoReg, getKillRegState(SrcIsKill));
441
442 // SREG is always implicitly killed
443 MIBLO->getOperand(3).setIsKill();
444
445 auto MIBHI = buildMI(MBB, MBBI, OpHi)
446 .addReg(DstHiReg, getKillRegState(DstIsKill))
447 .addReg(SrcHiReg, getKillRegState(SrcIsKill));
448
449 if (ImpIsDead)
450 MIBHI->getOperand(2).setIsDead();
451
452 // SREG is always implicitly killed
453 MIBHI->getOperand(3).setIsKill();
454
455 MI.eraseFromParent();
456 return true;
457}
458
459template <>
460bool AVRExpandPseudo::expand<AVR::LDIWRdK>(Block &MBB, BlockIt MBBI) {
461 MachineInstr &MI = *MBBI;
462 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
463 unsigned DstReg = MI.getOperand(0).getReg();
464 bool DstIsDead = MI.getOperand(0).isDead();
465 OpLo = AVR::LDIRdK;
466 OpHi = AVR::LDIRdK;
467 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
468
469 auto MIBLO = buildMI(MBB, MBBI, OpLo)
470 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead));
471
472 auto MIBHI = buildMI(MBB, MBBI, OpHi)
473 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead));
474
475 switch (MI.getOperand(1).getType()) {
476 case MachineOperand::MO_GlobalAddress: {
477 const GlobalValue *GV = MI.getOperand(1).getGlobal();
478 int64_t Offs = MI.getOperand(1).getOffset();
479 unsigned TF = MI.getOperand(1).getTargetFlags();
480
481 MIBLO.addGlobalAddress(GV, Offs, TF | AVRII::MO_LO);
482 MIBHI.addGlobalAddress(GV, Offs, TF | AVRII::MO_HI);
483 break;
484 }
485 case MachineOperand::MO_BlockAddress: {
486 const BlockAddress *BA = MI.getOperand(1).getBlockAddress();
487 unsigned TF = MI.getOperand(1).getTargetFlags();
488
489 MIBLO.addOperand(MachineOperand::CreateBA(BA, TF | AVRII::MO_LO));
490 MIBHI.addOperand(MachineOperand::CreateBA(BA, TF | AVRII::MO_HI));
491 break;
492 }
493 case MachineOperand::MO_Immediate: {
494 unsigned Imm = MI.getOperand(1).getImm();
495
496 MIBLO.addImm(Imm & 0xff);
497 MIBHI.addImm((Imm >> 8) & 0xff);
498 break;
499 }
500 default:
501 llvm_unreachable("Unknown operand type!");
502 }
503
504 MI.eraseFromParent();
505 return true;
506}
507
508template <>
509bool AVRExpandPseudo::expand<AVR::LDSWRdK>(Block &MBB, BlockIt MBBI) {
510 MachineInstr &MI = *MBBI;
511 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
512 unsigned DstReg = MI.getOperand(0).getReg();
513 bool DstIsDead = MI.getOperand(0).isDead();
514 OpLo = AVR::LDSRdK;
515 OpHi = AVR::LDSRdK;
516 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
517
518 auto MIBLO = buildMI(MBB, MBBI, OpLo)
519 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead));
520
521 auto MIBHI = buildMI(MBB, MBBI, OpHi)
522 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead));
523
524 switch (MI.getOperand(1).getType()) {
525 case MachineOperand::MO_GlobalAddress: {
526 const GlobalValue *GV = MI.getOperand(1).getGlobal();
527 int64_t Offs = MI.getOperand(1).getOffset();
528 unsigned TF = MI.getOperand(1).getTargetFlags();
529
530 MIBLO.addGlobalAddress(GV, Offs, TF);
531 MIBHI.addGlobalAddress(GV, Offs + 1, TF);
532 break;
533 }
534 case MachineOperand::MO_Immediate: {
535 unsigned Imm = MI.getOperand(1).getImm();
536
537 MIBLO.addImm(Imm);
538 MIBHI.addImm(Imm + 1);
539 break;
540 }
541 default:
542 llvm_unreachable("Unknown operand type!");
543 }
544
545 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
546 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
547
548 MI.eraseFromParent();
549 return true;
550}
551
552template <>
553bool AVRExpandPseudo::expand<AVR::LDWRdPtr>(Block &MBB, BlockIt MBBI) {
554 MachineInstr &MI = *MBBI;
555 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
556 unsigned DstReg = MI.getOperand(0).getReg();
557 unsigned SrcReg = MI.getOperand(1).getReg();
558 bool DstIsDead = MI.getOperand(0).isDead();
559 bool SrcIsKill = MI.getOperand(1).isKill();
560 OpLo = AVR::LDRdPtr;
561 OpHi = AVR::LDDRdPtrQ;
562 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
563
564 assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
565
566 auto MIBLO = buildMI(MBB, MBBI, OpLo)
567 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
568 .addReg(SrcReg);
569
570 auto MIBHI = buildMI(MBB, MBBI, OpHi)
571 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
572 .addReg(SrcReg, getKillRegState(SrcIsKill))
573 .addImm(1);
574
575 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
576 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
577
578 MI.eraseFromParent();
579 return true;
580}
581
582template <>
583bool AVRExpandPseudo::expand<AVR::LDWRdPtrPi>(Block &MBB, BlockIt MBBI) {
584 MachineInstr &MI = *MBBI;
585 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
586 unsigned DstReg = MI.getOperand(0).getReg();
587 unsigned SrcReg = MI.getOperand(1).getReg();
588 bool DstIsDead = MI.getOperand(0).isDead();
589 bool SrcIsDead = MI.getOperand(1).isKill();
590 OpLo = AVR::LDRdPtrPi;
591 OpHi = AVR::LDRdPtrPi;
592 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
593
594 assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
595
596 auto MIBLO = buildMI(MBB, MBBI, OpLo)
597 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
598 .addReg(SrcReg, RegState::Define)
599 .addReg(SrcReg, RegState::Kill);
600
601 auto MIBHI = buildMI(MBB, MBBI, OpHi)
602 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
603 .addReg(SrcReg, RegState::Define | getDeadRegState(SrcIsDead))
604 .addReg(SrcReg, RegState::Kill);
605
606 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
607 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
608
609 MI.eraseFromParent();
610 return true;
611}
612
613template <>
614bool AVRExpandPseudo::expand<AVR::LDWRdPtrPd>(Block &MBB, BlockIt MBBI) {
615 MachineInstr &MI = *MBBI;
616 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
617 unsigned DstReg = MI.getOperand(0).getReg();
618 unsigned SrcReg = MI.getOperand(1).getReg();
619 bool DstIsDead = MI.getOperand(0).isDead();
620 bool SrcIsDead = MI.getOperand(1).isKill();
621 OpLo = AVR::LDRdPtrPd;
622 OpHi = AVR::LDRdPtrPd;
623 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
624
625 assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
626
627 auto MIBHI = buildMI(MBB, MBBI, OpHi)
628 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
629 .addReg(SrcReg, RegState::Define)
630 .addReg(SrcReg, RegState::Kill);
631
632 auto MIBLO = buildMI(MBB, MBBI, OpLo)
633 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
634 .addReg(SrcReg, RegState::Define | getDeadRegState(SrcIsDead))
635 .addReg(SrcReg, RegState::Kill);
636
637 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
638 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
639
640 MI.eraseFromParent();
641 return true;
642}
643
644template <>
645bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
646 MachineInstr &MI = *MBBI;
647 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
648 unsigned DstReg = MI.getOperand(0).getReg();
649 unsigned SrcReg = MI.getOperand(1).getReg();
650 unsigned Imm = MI.getOperand(2).getImm();
651 bool DstIsDead = MI.getOperand(0).isDead();
652 bool SrcIsKill = MI.getOperand(1).isKill();
653 OpLo = AVR::LDDRdPtrQ;
654 OpHi = AVR::LDDRdPtrQ;
655 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
656
657 assert(Imm < 63 && "Offset is out of range");
Dylan McKay8cec7eb2016-12-07 11:08:56 +0000658
659 unsigned TmpLoReg = DstLoReg;
660 unsigned TmpHiReg = DstHiReg;
661
662 // HACK: We shouldn't have instances of this instruction
663 // where src==dest because the instruction itself is
664 // marked earlyclobber. We do however get this instruction when
665 // loading from stack slots where the earlyclobber isn't useful.
666 //
667 // In this case, just use a temporary register.
668 if (DstReg == SrcReg) {
669 TmpLoReg = SCRATCH_REGISTER;
670 TmpHiReg = SCRATCH_REGISTER;
671 }
Dylan McKaya789f402016-11-16 21:58:04 +0000672
673 auto MIBLO = buildMI(MBB, MBBI, OpLo)
Dylan McKay8cec7eb2016-12-07 11:08:56 +0000674 .addReg(TmpLoReg, RegState::Define | getDeadRegState(DstIsDead))
Dylan McKaya789f402016-11-16 21:58:04 +0000675 .addReg(SrcReg)
676 .addImm(Imm);
677
Dylan McKay8cec7eb2016-12-07 11:08:56 +0000678 // Push the low part of the temporary register to the stack.
679 if (TmpLoReg != DstLoReg)
680 buildMI(MBB, MBBI, AVR::PUSHRr)
681 .addReg(AVR::R0);
682
Dylan McKaya789f402016-11-16 21:58:04 +0000683 auto MIBHI = buildMI(MBB, MBBI, OpHi)
Dylan McKay8cec7eb2016-12-07 11:08:56 +0000684 .addReg(TmpHiReg, RegState::Define | getDeadRegState(DstIsDead))
Dylan McKaya789f402016-11-16 21:58:04 +0000685 .addReg(SrcReg, getKillRegState(SrcIsKill))
686 .addImm(Imm + 1);
687
Dylan McKay8cec7eb2016-12-07 11:08:56 +0000688 // If we need to use a temporary register.
689 if (TmpHiReg != DstHiReg) {
690 // Move the hi result from the tmp register to the destination.
691 buildMI(MBB, MBBI, AVR::MOVRdRr)
692 .addReg(DstHiReg).addReg(SCRATCH_REGISTER);
693
694 // Pop the lo result calculated previously and put it into
695 // the lo destination.
696 buildMI(MBB, MBBI, AVR::POPRd).addReg(DstLoReg);
697 }
698
Dylan McKaya789f402016-11-16 21:58:04 +0000699 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
700 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
701
702 MI.eraseFromParent();
703 return true;
704}
705
Dylan McKaya5d49df2016-12-09 07:49:04 +0000706template <>
707bool AVRExpandPseudo::expand<AVR::LPMWRdZ>(Block &MBB, BlockIt MBBI) {
708 llvm_unreachable("wide LPM is unimplemented");
709}
710
711template <>
712bool AVRExpandPseudo::expand<AVR::LPMWRdZPi>(Block &MBB, BlockIt MBBI) {
713 llvm_unreachable("wide LPMPi is unimplemented");
714}
715
Dylan McKaya789f402016-11-16 21:58:04 +0000716template<typename Func>
717bool AVRExpandPseudo::expandAtomic(Block &MBB, BlockIt MBBI, Func f) {
718 // Remove the pseudo instruction.
719 MachineInstr &MI = *MBBI;
720
721 // Store the SREG.
722 buildMI(MBB, MBBI, AVR::INRdA)
723 .addReg(SCRATCH_REGISTER, RegState::Define)
724 .addImm(SREG_ADDR);
725
726 // Disable exceptions.
727 buildMI(MBB, MBBI, AVR::BCLRs).addImm(7); // CLI
728
729 f(MI);
730
731 // Restore the status reg.
732 buildMI(MBB, MBBI, AVR::OUTARr)
733 .addImm(SREG_ADDR)
734 .addReg(SCRATCH_REGISTER);
735
736 MI.eraseFromParent();
737 return true;
738}
739
740template<typename Func>
741bool AVRExpandPseudo::expandAtomicBinaryOp(unsigned Opcode,
742 Block &MBB,
743 BlockIt MBBI,
744 Func f) {
745 return expandAtomic(MBB, MBBI, [&](MachineInstr &MI) {
746 auto Op1 = MI.getOperand(0);
747 auto Op2 = MI.getOperand(1);
748
749 MachineInstr &NewInst = *buildMI(MBB, MBBI, Opcode)
750 .addOperand(Op1).addOperand(Op2)
751 .getInstr();
752 f(NewInst);
753 });
754}
755
756bool AVRExpandPseudo::expandAtomicBinaryOp(unsigned Opcode,
757 Block &MBB,
758 BlockIt MBBI) {
759 return expandAtomicBinaryOp(Opcode, MBB, MBBI, [](MachineInstr &MI) {});
760}
761
762bool AVRExpandPseudo::expandAtomicArithmeticOp(unsigned Width,
763 unsigned ArithOpcode,
764 Block &MBB,
765 BlockIt MBBI) {
766 return expandAtomic(MBB, MBBI, [&](MachineInstr &MI) {
767 auto Op1 = MI.getOperand(0);
768 auto Op2 = MI.getOperand(1);
769
770 unsigned LoadOpcode = (Width == 8) ? AVR::LDRdPtr : AVR::LDWRdPtr;
771 unsigned StoreOpcode = (Width == 8) ? AVR::STPtrRr : AVR::STWPtrRr;
772
773 // Create the load
774 buildMI(MBB, MBBI, LoadOpcode).addOperand(Op1).addOperand(Op2);
775
776 // Create the arithmetic op
777 buildMI(MBB, MBBI, ArithOpcode)
778 .addOperand(Op1).addOperand(Op1)
779 .addOperand(Op2);
780
781 // Create the store
782 buildMI(MBB, MBBI, StoreOpcode).addOperand(Op2).addOperand(Op1);
783 });
784}
785
786template<>
787bool AVRExpandPseudo::expand<AVR::AtomicLoad8>(Block &MBB, BlockIt MBBI) {
788 return expandAtomicBinaryOp(AVR::LDRdPtr, MBB, MBBI);
789}
790
791template<>
792bool AVRExpandPseudo::expand<AVR::AtomicLoad16>(Block &MBB, BlockIt MBBI) {
793 return expandAtomicBinaryOp(AVR::LDWRdPtr, MBB, MBBI);
794}
795
796template<>
797bool AVRExpandPseudo::expand<AVR::AtomicStore8>(Block &MBB, BlockIt MBBI) {
798 return expandAtomicBinaryOp(AVR::STPtrRr, MBB, MBBI);
799}
800
801template<>
802bool AVRExpandPseudo::expand<AVR::AtomicStore16>(Block &MBB, BlockIt MBBI) {
803 return expandAtomicBinaryOp(AVR::STWPtrRr, MBB, MBBI);
804}
805
806template<>
807bool AVRExpandPseudo::expand<AVR::AtomicLoadAdd8>(Block &MBB, BlockIt MBBI) {
808 return expandAtomicArithmeticOp(8, AVR::ADDRdRr, MBB, MBBI);
809}
810
811template<>
812bool AVRExpandPseudo::expand<AVR::AtomicLoadAdd16>(Block &MBB, BlockIt MBBI) {
813 return expandAtomicArithmeticOp(16, AVR::ADDWRdRr, MBB, MBBI);
814}
815
816template<>
817bool AVRExpandPseudo::expand<AVR::AtomicLoadSub8>(Block &MBB, BlockIt MBBI) {
818 return expandAtomicArithmeticOp(8, AVR::SUBRdRr, MBB, MBBI);
819}
820
821template<>
822bool AVRExpandPseudo::expand<AVR::AtomicLoadSub16>(Block &MBB, BlockIt MBBI) {
823 return expandAtomicArithmeticOp(16, AVR::SUBWRdRr, MBB, MBBI);
824}
825
826template<>
827bool AVRExpandPseudo::expand<AVR::AtomicLoadAnd8>(Block &MBB, BlockIt MBBI) {
828 return expandAtomicArithmeticOp(8, AVR::ANDRdRr, MBB, MBBI);
829}
830
831template<>
832bool AVRExpandPseudo::expand<AVR::AtomicLoadAnd16>(Block &MBB, BlockIt MBBI) {
833 return expandAtomicArithmeticOp(16, AVR::ANDWRdRr, MBB, MBBI);
834}
835
836template<>
837bool AVRExpandPseudo::expand<AVR::AtomicLoadOr8>(Block &MBB, BlockIt MBBI) {
838 return expandAtomicArithmeticOp(8, AVR::ORRdRr, MBB, MBBI);
839}
840
841template<>
842bool AVRExpandPseudo::expand<AVR::AtomicLoadOr16>(Block &MBB, BlockIt MBBI) {
843 return expandAtomicArithmeticOp(16, AVR::ORWRdRr, MBB, MBBI);
844}
845
846template<>
847bool AVRExpandPseudo::expand<AVR::AtomicLoadXor8>(Block &MBB, BlockIt MBBI) {
848 return expandAtomicArithmeticOp(8, AVR::EORRdRr, MBB, MBBI);
849}
850
851template<>
852bool AVRExpandPseudo::expand<AVR::AtomicLoadXor16>(Block &MBB, BlockIt MBBI) {
853 return expandAtomicArithmeticOp(16, AVR::EORWRdRr, MBB, MBBI);
854}
855
856template<>
857bool AVRExpandPseudo::expand<AVR::AtomicFence>(Block &MBB, BlockIt MBBI) {
858 // On AVR, there is only one core and so atomic fences do nothing.
859 MBBI->eraseFromParent();
860 return true;
861}
862
863template <>
864bool AVRExpandPseudo::expand<AVR::STSWKRr>(Block &MBB, BlockIt MBBI) {
865 MachineInstr &MI = *MBBI;
866 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
867 unsigned SrcReg = MI.getOperand(1).getReg();
868 bool SrcIsKill = MI.getOperand(1).isKill();
869 OpLo = AVR::STSKRr;
870 OpHi = AVR::STSKRr;
871 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
872
873 // Write the high byte first in case this address belongs to a special
874 // I/O address with a special temporary register.
875 auto MIBHI = buildMI(MBB, MBBI, OpHi);
876 auto MIBLO = buildMI(MBB, MBBI, OpLo);
877
878 switch (MI.getOperand(0).getType()) {
879 case MachineOperand::MO_GlobalAddress: {
880 const GlobalValue *GV = MI.getOperand(0).getGlobal();
881 int64_t Offs = MI.getOperand(0).getOffset();
882 unsigned TF = MI.getOperand(0).getTargetFlags();
883
884 MIBLO.addGlobalAddress(GV, Offs, TF);
885 MIBHI.addGlobalAddress(GV, Offs + 1, TF);
886 break;
887 }
888 case MachineOperand::MO_Immediate: {
889 unsigned Imm = MI.getOperand(0).getImm();
890
891 MIBLO.addImm(Imm);
892 MIBHI.addImm(Imm + 1);
893 break;
894 }
895 default:
896 llvm_unreachable("Unknown operand type!");
897 }
898
899 MIBLO.addReg(SrcLoReg, getKillRegState(SrcIsKill));
900 MIBHI.addReg(SrcHiReg, getKillRegState(SrcIsKill));
901
902 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
903 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
904
905 MI.eraseFromParent();
906 return true;
907}
908
909template <>
910bool AVRExpandPseudo::expand<AVR::STWPtrRr>(Block &MBB, BlockIt MBBI) {
911 MachineInstr &MI = *MBBI;
912 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
913 unsigned DstReg = MI.getOperand(0).getReg();
914 unsigned SrcReg = MI.getOperand(1).getReg();
915 bool DstIsKill = MI.getOperand(0).isKill();
916 bool SrcIsKill = MI.getOperand(1).isKill();
917 OpLo = AVR::STPtrRr;
918 OpHi = AVR::STDPtrQRr;
919 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
920
921 //:TODO: need to reverse this order like inw and stsw?
922 auto MIBLO = buildMI(MBB, MBBI, OpLo)
923 .addReg(DstReg)
924 .addReg(SrcLoReg, getKillRegState(SrcIsKill));
925
926 auto MIBHI = buildMI(MBB, MBBI, OpHi)
927 .addReg(DstReg, getKillRegState(DstIsKill))
928 .addImm(1)
929 .addReg(SrcHiReg, getKillRegState(SrcIsKill));
930
931 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
932 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
933
934 MI.eraseFromParent();
935 return true;
936}
937
938template <>
939bool AVRExpandPseudo::expand<AVR::STWPtrPiRr>(Block &MBB, BlockIt MBBI) {
940 MachineInstr &MI = *MBBI;
941 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
942 unsigned DstReg = MI.getOperand(0).getReg();
943 unsigned SrcReg = MI.getOperand(2).getReg();
944 unsigned Imm = MI.getOperand(3).getImm();
945 bool DstIsDead = MI.getOperand(0).isDead();
946 bool SrcIsKill = MI.getOperand(2).isKill();
947 OpLo = AVR::STPtrPiRr;
948 OpHi = AVR::STPtrPiRr;
949 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
950
951 assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
952
953 auto MIBLO = buildMI(MBB, MBBI, OpLo)
954 .addReg(DstReg, RegState::Define)
955 .addReg(DstReg, RegState::Kill)
956 .addReg(SrcLoReg, getKillRegState(SrcIsKill))
957 .addImm(Imm);
958
959 auto MIBHI = buildMI(MBB, MBBI, OpHi)
960 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
961 .addReg(DstReg, RegState::Kill)
962 .addReg(SrcHiReg, getKillRegState(SrcIsKill))
963 .addImm(Imm);
964
965 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
966 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
967
968 MI.eraseFromParent();
969 return true;
970}
971
972template <>
973bool AVRExpandPseudo::expand<AVR::STWPtrPdRr>(Block &MBB, BlockIt MBBI) {
974 MachineInstr &MI = *MBBI;
975 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
976 unsigned DstReg = MI.getOperand(0).getReg();
977 unsigned SrcReg = MI.getOperand(2).getReg();
978 unsigned Imm = MI.getOperand(3).getImm();
979 bool DstIsDead = MI.getOperand(0).isDead();
980 bool SrcIsKill = MI.getOperand(2).isKill();
981 OpLo = AVR::STPtrPdRr;
982 OpHi = AVR::STPtrPdRr;
983 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
984
985 assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
986
987 auto MIBHI = buildMI(MBB, MBBI, OpHi)
988 .addReg(DstReg, RegState::Define)
989 .addReg(DstReg, RegState::Kill)
990 .addReg(SrcHiReg, getKillRegState(SrcIsKill))
991 .addImm(Imm);
992
993 auto MIBLO = buildMI(MBB, MBBI, OpLo)
994 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
995 .addReg(DstReg, RegState::Kill)
996 .addReg(SrcLoReg, getKillRegState(SrcIsKill))
997 .addImm(Imm);
998
999 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1000 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1001
1002 MI.eraseFromParent();
1003 return true;
1004}
1005
1006template <>
1007bool AVRExpandPseudo::expand<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {
1008 MachineInstr &MI = *MBBI;
1009 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
1010 unsigned DstReg = MI.getOperand(0).getReg();
1011 unsigned SrcReg = MI.getOperand(2).getReg();
1012 unsigned Imm = MI.getOperand(1).getImm();
1013 bool DstIsKill = MI.getOperand(0).isKill();
1014 bool SrcIsKill = MI.getOperand(2).isKill();
1015 OpLo = AVR::STDPtrQRr;
1016 OpHi = AVR::STDPtrQRr;
1017 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
1018
1019 assert(Imm < 63 && "Offset is out of range");
1020
1021 auto MIBLO = buildMI(MBB, MBBI, OpLo)
1022 .addReg(DstReg)
1023 .addImm(Imm)
1024 .addReg(SrcLoReg, getKillRegState(SrcIsKill));
1025
1026 auto MIBHI = buildMI(MBB, MBBI, OpHi)
1027 .addReg(DstReg, getKillRegState(DstIsKill))
1028 .addImm(Imm + 1)
1029 .addReg(SrcHiReg, getKillRegState(SrcIsKill));
1030
1031 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1032 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1033
1034 MI.eraseFromParent();
1035 return true;
1036}
1037
1038template <>
1039bool AVRExpandPseudo::expand<AVR::INWRdA>(Block &MBB, BlockIt MBBI) {
1040 MachineInstr &MI = *MBBI;
1041 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
1042 unsigned Imm = MI.getOperand(1).getImm();
1043 unsigned DstReg = MI.getOperand(0).getReg();
1044 bool DstIsDead = MI.getOperand(0).isDead();
1045 OpLo = AVR::INRdA;
1046 OpHi = AVR::INRdA;
1047 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1048
1049 assert(Imm < 63 && "Address is out of range");
1050
1051 auto MIBLO = buildMI(MBB, MBBI, OpLo)
1052 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1053 .addImm(Imm);
1054
1055 auto MIBHI = buildMI(MBB, MBBI, OpHi)
1056 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1057 .addImm(Imm + 1);
1058
1059 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1060 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1061
1062 MI.eraseFromParent();
1063 return true;
1064}
1065
1066template <>
1067bool AVRExpandPseudo::expand<AVR::OUTWARr>(Block &MBB, BlockIt MBBI) {
1068 MachineInstr &MI = *MBBI;
1069 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
1070 unsigned Imm = MI.getOperand(0).getImm();
1071 unsigned SrcReg = MI.getOperand(1).getReg();
1072 bool SrcIsKill = MI.getOperand(1).isKill();
1073 OpLo = AVR::OUTARr;
1074 OpHi = AVR::OUTARr;
1075 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
1076
1077 assert(Imm < 63 && "Address is out of range");
1078
1079 // 16 bit I/O writes need the high byte first
1080 auto MIBHI = buildMI(MBB, MBBI, OpHi)
1081 .addImm(Imm + 1)
1082 .addReg(SrcHiReg, getKillRegState(SrcIsKill));
1083
1084 auto MIBLO = buildMI(MBB, MBBI, OpLo)
1085 .addImm(Imm)
1086 .addReg(SrcLoReg, getKillRegState(SrcIsKill));
1087
1088 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1089 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1090
1091 MI.eraseFromParent();
1092 return true;
1093}
1094
1095template <>
1096bool AVRExpandPseudo::expand<AVR::PUSHWRr>(Block &MBB, BlockIt MBBI) {
1097 MachineInstr &MI = *MBBI;
1098 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
1099 unsigned SrcReg = MI.getOperand(0).getReg();
1100 bool SrcIsKill = MI.getOperand(0).isKill();
1101 unsigned Flags = MI.getFlags();
1102 OpLo = AVR::PUSHRr;
1103 OpHi = AVR::PUSHRr;
1104 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
1105
1106 // Low part
1107 buildMI(MBB, MBBI, OpLo)
1108 .addReg(SrcLoReg, getKillRegState(SrcIsKill))
1109 .setMIFlags(Flags);
1110
1111 // High part
1112 buildMI(MBB, MBBI, OpHi)
1113 .addReg(SrcHiReg, getKillRegState(SrcIsKill))
1114 .setMIFlags(Flags);
1115
1116 MI.eraseFromParent();
1117 return true;
1118}
1119
1120template <>
1121bool AVRExpandPseudo::expand<AVR::POPWRd>(Block &MBB, BlockIt MBBI) {
1122 MachineInstr &MI = *MBBI;
1123 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
1124 unsigned DstReg = MI.getOperand(0).getReg();
1125 unsigned Flags = MI.getFlags();
1126 OpLo = AVR::POPRd;
1127 OpHi = AVR::POPRd;
1128 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1129
1130 buildMI(MBB, MBBI, OpHi, DstHiReg).setMIFlags(Flags); // High
1131 buildMI(MBB, MBBI, OpLo, DstLoReg).setMIFlags(Flags); // Low
1132
1133 MI.eraseFromParent();
1134 return true;
1135}
1136
1137template <>
1138bool AVRExpandPseudo::expand<AVR::LSLWRd>(Block &MBB, BlockIt MBBI) {
1139 MachineInstr &MI = *MBBI;
1140 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
1141 unsigned DstReg = MI.getOperand(0).getReg();
1142 bool DstIsDead = MI.getOperand(0).isDead();
1143 bool DstIsKill = MI.getOperand(1).isKill();
1144 bool ImpIsDead = MI.getOperand(2).isDead();
1145 OpLo = AVR::LSLRd;
1146 OpHi = AVR::ROLRd;
1147 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1148
1149 // Low part
1150 buildMI(MBB, MBBI, OpLo)
1151 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1152 .addReg(DstLoReg, getKillRegState(DstIsKill));
1153
1154 auto MIBHI = buildMI(MBB, MBBI, OpHi)
1155 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1156 .addReg(DstHiReg, getKillRegState(DstIsKill));
1157
1158 if (ImpIsDead)
1159 MIBHI->getOperand(2).setIsDead();
1160
1161 // SREG is always implicitly killed
1162 MIBHI->getOperand(3).setIsKill();
1163
1164 MI.eraseFromParent();
1165 return true;
1166}
1167
1168template <>
1169bool AVRExpandPseudo::expand<AVR::LSRWRd>(Block &MBB, BlockIt MBBI) {
1170 MachineInstr &MI = *MBBI;
1171 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
1172 unsigned DstReg = MI.getOperand(0).getReg();
1173 bool DstIsDead = MI.getOperand(0).isDead();
1174 bool DstIsKill = MI.getOperand(1).isKill();
1175 bool ImpIsDead = MI.getOperand(2).isDead();
1176 OpLo = AVR::RORRd;
1177 OpHi = AVR::LSRRd;
1178 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1179
1180 // High part
1181 buildMI(MBB, MBBI, OpHi)
1182 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1183 .addReg(DstHiReg, getKillRegState(DstIsKill));
1184
1185 auto MIBLO = buildMI(MBB, MBBI, OpLo)
1186 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1187 .addReg(DstLoReg, getKillRegState(DstIsKill));
1188
1189 if (ImpIsDead)
1190 MIBLO->getOperand(2).setIsDead();
1191
1192 // SREG is always implicitly killed
1193 MIBLO->getOperand(3).setIsKill();
1194
1195 MI.eraseFromParent();
1196 return true;
1197}
1198
1199template <>
1200bool AVRExpandPseudo::expand<AVR::RORWRd>(Block &MBB, BlockIt MBBI) {
1201 llvm_unreachable("RORW unimplemented");
1202 return false;
1203}
1204
1205template <>
1206bool AVRExpandPseudo::expand<AVR::ROLWRd>(Block &MBB, BlockIt MBBI) {
1207 llvm_unreachable("ROLW unimplemented");
1208 return false;
1209}
1210
1211template <>
1212bool AVRExpandPseudo::expand<AVR::ASRWRd>(Block &MBB, BlockIt MBBI) {
1213 MachineInstr &MI = *MBBI;
1214 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
1215 unsigned DstReg = MI.getOperand(0).getReg();
1216 bool DstIsDead = MI.getOperand(0).isDead();
1217 bool DstIsKill = MI.getOperand(1).isKill();
1218 bool ImpIsDead = MI.getOperand(2).isDead();
1219 OpLo = AVR::RORRd;
1220 OpHi = AVR::ASRRd;
1221 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1222
1223 // High part
1224 buildMI(MBB, MBBI, OpHi)
1225 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1226 .addReg(DstHiReg, getKillRegState(DstIsKill));
1227
1228 auto MIBLO = buildMI(MBB, MBBI, OpLo)
1229 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1230 .addReg(DstLoReg, getKillRegState(DstIsKill));
1231
1232 if (ImpIsDead)
1233 MIBLO->getOperand(2).setIsDead();
1234
1235 // SREG is always implicitly killed
1236 MIBLO->getOperand(3).setIsKill();
1237
1238 MI.eraseFromParent();
1239 return true;
1240}
1241
1242template <> bool AVRExpandPseudo::expand<AVR::SEXT>(Block &MBB, BlockIt MBBI) {
1243 MachineInstr &MI = *MBBI;
1244 unsigned DstLoReg, DstHiReg;
1245 // sext R17:R16, R17
1246 // mov r16, r17
1247 // lsl r17
1248 // sbc r17, r17
1249 // sext R17:R16, R13
1250 // mov r16, r13
1251 // mov r17, r13
1252 // lsl r17
1253 // sbc r17, r17
1254 // sext R17:R16, R16
1255 // mov r17, r16
1256 // lsl r17
1257 // sbc r17, r17
1258 unsigned DstReg = MI.getOperand(0).getReg();
1259 unsigned SrcReg = MI.getOperand(1).getReg();
1260 bool DstIsDead = MI.getOperand(0).isDead();
1261 bool SrcIsKill = MI.getOperand(1).isKill();
1262 bool ImpIsDead = MI.getOperand(2).isDead();
1263 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1264
1265 if (SrcReg != DstLoReg) {
1266 auto MOV = buildMI(MBB, MBBI, AVR::MOVRdRr)
1267 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1268 .addReg(SrcReg);
1269
1270 if (SrcReg == DstHiReg) {
1271 MOV->getOperand(1).setIsKill();
1272 }
1273 }
1274
1275 if (SrcReg != DstHiReg) {
1276 buildMI(MBB, MBBI, AVR::MOVRdRr)
1277 .addReg(DstHiReg, RegState::Define)
1278 .addReg(SrcReg, getKillRegState(SrcIsKill));
1279 }
1280
1281 buildMI(MBB, MBBI, AVR::LSLRd)
1282 .addReg(DstHiReg, RegState::Define)
1283 .addReg(DstHiReg, RegState::Kill);
1284
1285 auto SBC = buildMI(MBB, MBBI, AVR::SBCRdRr)
1286 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1287 .addReg(DstHiReg, RegState::Kill)
1288 .addReg(DstHiReg, RegState::Kill);
1289
1290 if (ImpIsDead)
1291 SBC->getOperand(3).setIsDead();
1292
1293 // SREG is always implicitly killed
1294 SBC->getOperand(4).setIsKill();
1295
1296 MI.eraseFromParent();
1297 return true;
1298}
1299
1300template <> bool AVRExpandPseudo::expand<AVR::ZEXT>(Block &MBB, BlockIt MBBI) {
1301 MachineInstr &MI = *MBBI;
1302 unsigned DstLoReg, DstHiReg;
1303 // zext R25:R24, R20
1304 // mov R24, R20
1305 // eor R25, R25
1306 // zext R25:R24, R24
1307 // eor R25, R25
1308 // zext R25:R24, R25
1309 // mov R24, R25
1310 // eor R25, R25
1311 unsigned DstReg = MI.getOperand(0).getReg();
1312 unsigned SrcReg = MI.getOperand(1).getReg();
1313 bool DstIsDead = MI.getOperand(0).isDead();
1314 bool SrcIsKill = MI.getOperand(1).isKill();
1315 bool ImpIsDead = MI.getOperand(2).isDead();
1316 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1317
1318 if (SrcReg != DstLoReg) {
1319 buildMI(MBB, MBBI, AVR::MOVRdRr)
1320 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1321 .addReg(SrcReg, getKillRegState(SrcIsKill));
1322 }
1323
1324 auto EOR = buildMI(MBB, MBBI, AVR::EORRdRr)
1325 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1326 .addReg(DstHiReg, RegState::Kill)
1327 .addReg(DstHiReg, RegState::Kill);
1328
1329 if (ImpIsDead)
1330 EOR->getOperand(3).setIsDead();
1331
1332 MI.eraseFromParent();
1333 return true;
1334}
1335
1336template <>
1337bool AVRExpandPseudo::expand<AVR::SPREAD>(Block &MBB, BlockIt MBBI) {
1338 MachineInstr &MI = *MBBI;
1339 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
1340 unsigned DstReg = MI.getOperand(0).getReg();
1341 bool DstIsDead = MI.getOperand(0).isDead();
1342 unsigned Flags = MI.getFlags();
1343 OpLo = AVR::INRdA;
1344 OpHi = AVR::INRdA;
1345 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1346
1347 // Low part
1348 buildMI(MBB, MBBI, OpLo)
1349 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1350 .addImm(0x3d)
1351 .setMIFlags(Flags);
1352
1353 // High part
1354 buildMI(MBB, MBBI, OpHi)
1355 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1356 .addImm(0x3e)
1357 .setMIFlags(Flags);
1358
1359 MI.eraseFromParent();
1360 return true;
1361}
1362
1363template <>
1364bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
1365 MachineInstr &MI = *MBBI;
1366 unsigned SrcLoReg, SrcHiReg;
1367 unsigned SrcReg = MI.getOperand(1).getReg();
1368 bool SrcIsKill = MI.getOperand(1).isKill();
1369 unsigned Flags = MI.getFlags();
1370 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
1371
1372 buildMI(MBB, MBBI, AVR::INRdA)
1373 .addReg(AVR::R0, RegState::Define)
1374 .addImm(SREG_ADDR)
1375 .setMIFlags(Flags);
1376
1377 buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
1378
1379 buildMI(MBB, MBBI, AVR::OUTARr)
1380 .addImm(0x3e)
1381 .addReg(SrcHiReg, getKillRegState(SrcIsKill))
1382 .setMIFlags(Flags);
1383
1384 buildMI(MBB, MBBI, AVR::OUTARr)
1385 .addImm(SREG_ADDR)
1386 .addReg(AVR::R0, RegState::Kill)
1387 .setMIFlags(Flags);
1388
1389 buildMI(MBB, MBBI, AVR::OUTARr)
1390 .addImm(0x3d)
1391 .addReg(SrcLoReg, getKillRegState(SrcIsKill))
1392 .setMIFlags(Flags);
1393
1394 MI.eraseFromParent();
1395 return true;
1396}
1397
1398bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
1399 MachineInstr &MI = *MBBI;
1400 int Opcode = MBBI->getOpcode();
1401
1402#define EXPAND(Op) \
1403 case Op: \
1404 return expand<Op>(MBB, MI)
1405
1406 switch (Opcode) {
1407 EXPAND(AVR::ADDWRdRr);
1408 EXPAND(AVR::ADCWRdRr);
1409 EXPAND(AVR::SUBWRdRr);
1410 EXPAND(AVR::SUBIWRdK);
1411 EXPAND(AVR::SBCWRdRr);
1412 EXPAND(AVR::SBCIWRdK);
1413 EXPAND(AVR::ANDWRdRr);
1414 EXPAND(AVR::ANDIWRdK);
1415 EXPAND(AVR::ORWRdRr);
1416 EXPAND(AVR::ORIWRdK);
1417 EXPAND(AVR::EORWRdRr);
1418 EXPAND(AVR::COMWRd);
1419 EXPAND(AVR::CPWRdRr);
1420 EXPAND(AVR::CPCWRdRr);
1421 EXPAND(AVR::LDIWRdK);
1422 EXPAND(AVR::LDSWRdK);
1423 EXPAND(AVR::LDWRdPtr);
1424 EXPAND(AVR::LDWRdPtrPi);
1425 EXPAND(AVR::LDWRdPtrPd);
1426 case AVR::LDDWRdYQ: //:FIXME: remove this once PR13375 gets fixed
1427 EXPAND(AVR::LDDWRdPtrQ);
Dylan McKaya5d49df2016-12-09 07:49:04 +00001428 EXPAND(AVR::LPMWRdZ);
1429 EXPAND(AVR::LPMWRdZPi);
Dylan McKaya789f402016-11-16 21:58:04 +00001430 EXPAND(AVR::AtomicLoad8);
1431 EXPAND(AVR::AtomicLoad16);
1432 EXPAND(AVR::AtomicStore8);
1433 EXPAND(AVR::AtomicStore16);
1434 EXPAND(AVR::AtomicLoadAdd8);
1435 EXPAND(AVR::AtomicLoadAdd16);
1436 EXPAND(AVR::AtomicLoadSub8);
1437 EXPAND(AVR::AtomicLoadSub16);
1438 EXPAND(AVR::AtomicLoadAnd8);
1439 EXPAND(AVR::AtomicLoadAnd16);
1440 EXPAND(AVR::AtomicLoadOr8);
1441 EXPAND(AVR::AtomicLoadOr16);
1442 EXPAND(AVR::AtomicLoadXor8);
1443 EXPAND(AVR::AtomicLoadXor16);
1444 EXPAND(AVR::AtomicFence);
1445 EXPAND(AVR::STSWKRr);
1446 EXPAND(AVR::STWPtrRr);
1447 EXPAND(AVR::STWPtrPiRr);
1448 EXPAND(AVR::STWPtrPdRr);
1449 EXPAND(AVR::STDWPtrQRr);
1450 EXPAND(AVR::INWRdA);
1451 EXPAND(AVR::OUTWARr);
1452 EXPAND(AVR::PUSHWRr);
1453 EXPAND(AVR::POPWRd);
1454 EXPAND(AVR::LSLWRd);
1455 EXPAND(AVR::LSRWRd);
1456 EXPAND(AVR::RORWRd);
1457 EXPAND(AVR::ROLWRd);
1458 EXPAND(AVR::ASRWRd);
1459 EXPAND(AVR::SEXT);
1460 EXPAND(AVR::ZEXT);
1461 EXPAND(AVR::SPREAD);
1462 EXPAND(AVR::SPWRITE);
1463 }
1464#undef EXPAND
1465 return false;
1466}
1467
Dylan McKay017a55b2016-11-16 23:06:14 +00001468} // end of anonymous namespace
1469
Dylan McKay8cec7eb2016-12-07 11:08:56 +00001470INITIALIZE_PASS(AVRExpandPseudo, "avr-expand-pseudo",
1471 AVR_EXPAND_PSEUDO_NAME, false, false)
Dylan McKaya789f402016-11-16 21:58:04 +00001472namespace llvm {
1473
1474FunctionPass *createAVRExpandPseudoPass() { return new AVRExpandPseudo(); }
1475
1476} // end of namespace llvm