https://gcc.gnu.org/g:dfa35668605788918c7a1b28faa8699afb6b5fe1

commit r14-12140-gdfa35668605788918c7a1b28faa8699afb6b5fe1
Author: Georg-Johann Lay <[email protected]>
Date:   Thu Nov 6 19:59:48 2025 +0100

    AVR: AVR-SD: Put a valid opcode prior to gs() table in .subsection 1.
    
    On functional safety devices (AVR-SD), each executed instruction must
    be followed by a valid opcode.  This is because instruction fetch and
    decode for the next instruction runs while the 2-stage pipeline is
    executing the current instruction.
    
    There is only one case where avr-gcc generates code interspersed with
    data, which is when a switch/case table is generated for a function
    with a "section" attribute and AVR_HAVE_JMP_CALL.  In that case, the
    table with the gs() code label addresses is put in .subsection 1 so
    that it belongs to the section as specified by the "section" attribute.
    
    gcc/
            * config/avr/avr.cc (avr_output_addr_vec): Output
            a valid opcode prior to the first gs() label provided:
            - The code is compiled for an arch that has AVR-SD mcus, and
            - the function has a "section" attribute, and
            - the function has a gs() label addresses switch/case table.
    
    (cherry picked from commit d79d12d3faea6c4472ede35e4b66a68cf1f85f77)

Diff:
---
 gcc/config/avr/avr.cc | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 03ba51ea6199..43dac0198a35 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -14328,6 +14328,16 @@ avr_output_addr_vec (rtx_insn *labl, rtx table)
 
   app_disable();
 
+  // AVR-SD: On functional safety devices, each executed instruction must
+  // be followed by a valid opcode.  This is because instruction validation
+  // runs at fetch and decode for the next instruction and while the 2-stage
+  // pipeline is executing the current one.  There is no multilib option for
+  // these devices, so take all multilib variants that contain AVR-SD.
+  const bool maybe_sd = (AVR_HAVE_JMP_CALL
+                        && (avr_arch_index == ARCH_AVRXMEGA2
+                            || avr_arch_index == ARCH_AVRXMEGA3));
+  bool uses_subsection = false;
+
   // Switch to appropriate (sub)section.
 
   if (DECL_SECTION_NAME (current_function_decl)
@@ -14339,6 +14349,7 @@ avr_output_addr_vec (rtx_insn *labl, rtx table)
 
       switch_to_section (current_function_section ());
       fprintf (stream, "\t.subsection\t1\n");
+      uses_subsection = true;
     }
   else
     {
@@ -14361,9 +14372,21 @@ avr_output_addr_vec (rtx_insn *labl, rtx table)
               AVR_HAVE_JMP_CALL ? "a" : "ax");
     }
 
-  // Output the label that preceeds the table.
-
   ASM_OUTPUT_ALIGN (stream, 1);
+
+  if (maybe_sd && uses_subsection)
+    {
+      // Insert a valid opcode prior to the first gs() label.
+      // Any valid opcode will do.  Use CLH since it disassembles
+      // more nicely than NOP = 0x0000.  This is all GCC can do.
+      // Other cases, like inserting CLH after the vector table and
+      // after the last instruction, are handled by other parts of
+      // the toolchain.
+      fprintf (stream, "\tclh\n");
+    }
+
+  // Output the label that precedes the table.
+
   targetm.asm_out.internal_label (stream, "L", CODE_LABEL_NUMBER (labl));
 
   // Output the table's content.

Reply via email to