[llvm] [AVR] No cli for SPWRITE on XMEGA (PR #147210)

Tom Vijlbrief via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 6 12:56:22 PDT 2025


https://github.com/tomtor updated https://github.com/llvm/llvm-project/pull/147210

>From a0088b4bd3ccd93c0eeae9cbfdf355dea825d22c Mon Sep 17 00:00:00 2001
From: Tom Vijlbrief <tvijlbrief at gmail.com>
Date: Sun, 6 Jul 2025 21:34:20 +0200
Subject: [PATCH 1/2] [AVR] No cli for SPWRITE on XMEGA

---
 llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp | 25 ++++++++++++++++----
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
index 440d852fa4bc8..1c00010c76ff8 100644
--- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
@@ -2531,27 +2531,42 @@ bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
   unsigned Flags = MI.getFlags();
   TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
 
-  buildMI(MBB, MBBI, AVR::INRdA)
+  // From the XMEGA series manual:
+  // To prevent corruption when updating the stack pointer from software,
+  // a write to SPL will automatically disable interrupts
+  // for up to four instructions or until the next I/O memory write.
+  if (STI.getELFArch() >= 102) { // An XMEGA device
+    buildMI(MBB, MBBI, AVR::OUTARr)
+      .addImm(0x3d)
+      .addReg(SrcLoReg, getKillRegState(SrcIsKill))
+      .setMIFlags(Flags);
+    buildMI(MBB, MBBI, AVR::OUTARr)
+      .addImm(0x3e)
+      .addReg(SrcHiReg, getKillRegState(SrcIsKill))
+      .setMIFlags(Flags);
+  } else { // Disable interrupts for older devices (3 extra instructions)
+    buildMI(MBB, MBBI, AVR::INRdA)
       .addReg(STI.getTmpRegister(), RegState::Define)
       .addImm(STI.getIORegSREG())
       .setMIFlags(Flags);
 
-  buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
+    buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
 
-  buildMI(MBB, MBBI, AVR::OUTARr)
+    buildMI(MBB, MBBI, AVR::OUTARr)
       .addImm(0x3e)
       .addReg(SrcHiReg, getKillRegState(SrcIsKill))
       .setMIFlags(Flags);
 
-  buildMI(MBB, MBBI, AVR::OUTARr)
+    buildMI(MBB, MBBI, AVR::OUTARr)
       .addImm(STI.getIORegSREG())
       .addReg(STI.getTmpRegister(), RegState::Kill)
       .setMIFlags(Flags);
 
-  buildMI(MBB, MBBI, AVR::OUTARr)
+    buildMI(MBB, MBBI, AVR::OUTARr)
       .addImm(0x3d)
       .addReg(SrcLoReg, getKillRegState(SrcIsKill))
       .setMIFlags(Flags);
+  }
 
   MI.eraseFromParent();
   return true;

>From 065e8a3ff79776939f2af815bb1b2ca111312455 Mon Sep 17 00:00:00 2001
From: Tom Vijlbrief <tvijlbrief at gmail.com>
Date: Sun, 6 Jul 2025 21:56:08 +0200
Subject: [PATCH 2/2] formatting

---
 llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp | 40 +++++++++++---------
 1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
index 1c00010c76ff8..23a50945bed88 100644
--- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
@@ -2536,36 +2536,40 @@ bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
   // a write to SPL will automatically disable interrupts
   // for up to four instructions or until the next I/O memory write.
   if (STI.getELFArch() >= 102) { // An XMEGA device
+
     buildMI(MBB, MBBI, AVR::OUTARr)
-      .addImm(0x3d)
-      .addReg(SrcLoReg, getKillRegState(SrcIsKill))
-      .setMIFlags(Flags);
+        .addImm(0x3d)
+        .addReg(SrcLoReg, getKillRegState(SrcIsKill))
+        .setMIFlags(Flags);
+
     buildMI(MBB, MBBI, AVR::OUTARr)
-      .addImm(0x3e)
-      .addReg(SrcHiReg, getKillRegState(SrcIsKill))
-      .setMIFlags(Flags);
+        .addImm(0x3e)
+        .addReg(SrcHiReg, getKillRegState(SrcIsKill))
+        .setMIFlags(Flags);
+
   } else { // Disable interrupts for older devices (3 extra instructions)
+
     buildMI(MBB, MBBI, AVR::INRdA)
-      .addReg(STI.getTmpRegister(), RegState::Define)
-      .addImm(STI.getIORegSREG())
-      .setMIFlags(Flags);
+        .addReg(STI.getTmpRegister(), RegState::Define)
+        .addImm(STI.getIORegSREG())
+        .setMIFlags(Flags);
 
     buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
 
     buildMI(MBB, MBBI, AVR::OUTARr)
-      .addImm(0x3e)
-      .addReg(SrcHiReg, getKillRegState(SrcIsKill))
-      .setMIFlags(Flags);
+        .addImm(0x3e)
+        .addReg(SrcHiReg, getKillRegState(SrcIsKill))
+        .setMIFlags(Flags);
 
     buildMI(MBB, MBBI, AVR::OUTARr)
-      .addImm(STI.getIORegSREG())
-      .addReg(STI.getTmpRegister(), RegState::Kill)
-      .setMIFlags(Flags);
+        .addImm(STI.getIORegSREG())
+        .addReg(STI.getTmpRegister(), RegState::Kill)
+        .setMIFlags(Flags);
 
     buildMI(MBB, MBBI, AVR::OUTARr)
-      .addImm(0x3d)
-      .addReg(SrcLoReg, getKillRegState(SrcIsKill))
-      .setMIFlags(Flags);
+        .addImm(0x3d)
+        .addReg(SrcLoReg, getKillRegState(SrcIsKill))
+        .setMIFlags(Flags);
   }
 
   MI.eraseFromParent();



More information about the llvm-commits mailing list