@@ -2531,27 +2531,42 @@ bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
25312531 unsigned Flags = MI.getFlags ();
25322532 TRI->splitReg (SrcReg, SrcLoReg, SrcHiReg);
25332533
2534- buildMI (MBB, MBBI, AVR::INRdA)
2534+ // From the XMEGA series manual:
2535+ // To prevent corruption when updating the stack pointer from software,
2536+ // a write to SPL will automatically disable interrupts
2537+ // for up to four instructions or until the next I/O memory write.
2538+ if (STI.getELFArch () >= 102 ) { // An XMEGA device
2539+ buildMI (MBB, MBBI, AVR::OUTARr)
2540+ .addImm (0x3d )
2541+ .addReg (SrcLoReg, getKillRegState (SrcIsKill))
2542+ .setMIFlags (Flags);
2543+ buildMI (MBB, MBBI, AVR::OUTARr)
2544+ .addImm (0x3e )
2545+ .addReg (SrcHiReg, getKillRegState (SrcIsKill))
2546+ .setMIFlags (Flags);
2547+ } else { // Disable interrupts for older devices (3 extra instructions)
2548+ buildMI (MBB, MBBI, AVR::INRdA)
25352549 .addReg (STI.getTmpRegister (), RegState::Define)
25362550 .addImm (STI.getIORegSREG ())
25372551 .setMIFlags (Flags);
25382552
2539- buildMI (MBB, MBBI, AVR::BCLRs).addImm (0x07 ).setMIFlags (Flags);
2553+ buildMI (MBB, MBBI, AVR::BCLRs).addImm (0x07 ).setMIFlags (Flags);
25402554
2541- buildMI (MBB, MBBI, AVR::OUTARr)
2555+ buildMI (MBB, MBBI, AVR::OUTARr)
25422556 .addImm (0x3e )
25432557 .addReg (SrcHiReg, getKillRegState (SrcIsKill))
25442558 .setMIFlags (Flags);
25452559
2546- buildMI (MBB, MBBI, AVR::OUTARr)
2560+ buildMI (MBB, MBBI, AVR::OUTARr)
25472561 .addImm (STI.getIORegSREG ())
25482562 .addReg (STI.getTmpRegister (), RegState::Kill)
25492563 .setMIFlags (Flags);
25502564
2551- buildMI (MBB, MBBI, AVR::OUTARr)
2565+ buildMI (MBB, MBBI, AVR::OUTARr)
25522566 .addImm (0x3d )
25532567 .addReg (SrcLoReg, getKillRegState (SrcIsKill))
25542568 .setMIFlags (Flags);
2569+ }
25552570
25562571 MI.eraseFromParent ();
25572572 return true ;
0 commit comments