@@ -2531,27 +2531,47 @@ 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)
2535- .addReg (STI.getTmpRegister (), RegState::Define)
2536- .addImm (STI.getIORegSREG ())
2537- .setMIFlags (Flags);
2538-
2539- buildMI (MBB, MBBI, AVR::BCLRs).addImm (0x07 ).setMIFlags (Flags);
2540-
2541- buildMI (MBB, MBBI, AVR::OUTARr)
2542- .addImm (0x3e )
2543- .addReg (SrcHiReg, getKillRegState (SrcIsKill))
2544- .setMIFlags (Flags);
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+
2540+ buildMI (MBB, MBBI, AVR::OUTARr)
2541+ .addImm (STI.getIORegSPL ())
2542+ .addReg (SrcLoReg, getKillRegState (SrcIsKill))
2543+ .setMIFlags (Flags);
2544+
2545+ buildMI (MBB, MBBI, AVR::OUTARr)
2546+ .addImm (STI.getIORegSPH ())
2547+ .addReg (SrcHiReg, getKillRegState (SrcIsKill))
2548+ .setMIFlags (Flags);
2549+
2550+ } else { // Disable interrupts for older devices (3 extra instructions)
2551+
2552+ buildMI (MBB, MBBI, AVR::INRdA)
2553+ .addReg (STI.getTmpRegister (), RegState::Define)
2554+ .addImm (STI.getIORegSREG ())
2555+ .setMIFlags (Flags);
2556+
2557+ buildMI (MBB, MBBI, AVR::BCLRs).addImm (0x07 ).setMIFlags (Flags);
2558+
2559+ if (STI.getIORegSPH () != -1 )
2560+ buildMI (MBB, MBBI, AVR::OUTARr)
2561+ .addImm (STI.getIORegSPH ())
2562+ .addReg (SrcHiReg, getKillRegState (SrcIsKill))
2563+ .setMIFlags (Flags);
25452564
2546- buildMI (MBB, MBBI, AVR::OUTARr)
2547- .addImm (STI.getIORegSREG ())
2548- .addReg (STI.getTmpRegister (), RegState::Kill)
2549- .setMIFlags (Flags);
2565+ buildMI (MBB, MBBI, AVR::OUTARr)
2566+ .addImm (STI.getIORegSREG ())
2567+ .addReg (STI.getTmpRegister (), RegState::Kill)
2568+ .setMIFlags (Flags);
25502569
2551- buildMI (MBB, MBBI, AVR::OUTARr)
2552- .addImm (0x3d )
2553- .addReg (SrcLoReg, getKillRegState (SrcIsKill))
2554- .setMIFlags (Flags);
2570+ buildMI (MBB, MBBI, AVR::OUTARr)
2571+ .addImm (STI.getIORegSPL ())
2572+ .addReg (SrcLoReg, getKillRegState (SrcIsKill))
2573+ .setMIFlags (Flags);
2574+ }
25552575
25562576 MI.eraseFromParent ();
25572577 return true ;
0 commit comments