Why not use an inline assembly statement to do what you want?

See the inline assembler cookbook

A simple (readable) multiline example from there (a very short delay) which can go right into your AVR-GCC program:

asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t" ::);

Since you seem to know your assembly, you should be good ready to rock with inline assembly as well.

Answer from Windell Oskay on Stack Exchange
🌐
Nongnu
nongnu.org › avr-libc › user-manual › group__avr__cpufunc.html
avr-libc: <avr/cpufunc.h>: Special AVR CPU functions
For debugging purposes, a NOP can be useful to have an instruction that is guaranteed to be not optimized away by the compiler, so it can always become a breakpoint in the debugger. Write __value to Configuration Change Protected (CCP) IO register at __ioaddr. Generated on Sat Jan 29 2022 00:24:04 for avr...
🌐
GNU
gcc.gnu.org › onlinedocs › gcc › AVR-Built-in-Functions.html
AVR Built-in Functions (Using the GNU Compiler Collection (GCC))
For each built-in function for AVR, there is an equally named, uppercase built-in macro defined. That way users can easily query if or if not a specific built-in is implemented or not. For example, if __builtin_avr_nop is available the macro __BUILTIN_AVR_NOP is defined to 1 and undefined otherwise.
Top answer
1 of 3
2

Why not use an inline assembly statement to do what you want?

See the inline assembler cookbook

A simple (readable) multiline example from there (a very short delay) which can go right into your AVR-GCC program:

asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t" ::);

Since you seem to know your assembly, you should be good ready to rock with inline assembly as well.

2 of 3
2

I think that GCC's naked attribute does what you want. It skips generating any function header or footer, so you need to do your own reti.

void INT0_vect(void) __attribute__ ((signal, naked)); 

void INT0_vect(void) 
{
    TCCR1B = 0x09;
    asm volatile("reti"); 
} 

FreeRTOS uses this scheme for context switching on AVR, they explicitly store all registers. You may only want a subset:

    #define portSAVE_CONTEXT()      \
    asm volatile (  "push   r0                                              \n\t"   \
                                    "in             r0, __SREG__                    \n\t"   \
                                    "cli                                                    \n\t"   \
                                    "push   r0                                              \n\t"   \
                                    "push   r1                                              \n\t"   \
                                    "clr    r1                                              \n\t"   \
                                    "push   r2                                              \n\t"   \
                                    "push   r3                                              \n\t"   \
                                    "push   r4                                              \n\t"   \
                                    "push   r5                                              \n\t"   \
                                    "push   r6                                              \n\t"   \
                                    "push   r7                                              \n\t"   \
                                    "push   r8                                              \n\t"   \
                                    "push   r9                                              \n\t"   \
                                    "push   r10                                             \n\t"   \
                                    "push   r11                                             \n\t"   \
                                    "push   r12                                             \n\t"   \
                                    "push   r13                                             \n\t"   \
                                    "push   r14                                             \n\t"   \
                                    "push   r15                                             \n\t"   \
                                    "push   r16                                             \n\t"   \
                                    "push   r17                                             \n\t"   \
                                    "push   r18                                             \n\t"   \
                                    "push   r19                                             \n\t"   \
                                    "push   r20                                             \n\t"   \
                                    "push   r21                                             \n\t"   \
                                    "push   r22                                             \n\t"   \
                                    "push   r23                                             \n\t"   \
                                    "push   r24                                             \n\t"   \
                                    "push   r25                                             \n\t"   \
                                    "push   r26                                             \n\t"   \
                                    "push   r27                                             \n\t"   \
                                    "push   r28                                             \n\t"   \
                                    "push   r29                                             \n\t"   \
                                    "push   r30                                             \n\t"   \
                                    "push   r31                                             \n\t"   \
                                    "lds    r26, pxCurrentTCB               \n\t"   \
                                    "lds    r27, pxCurrentTCB + 1   \n\t"   \
                                    "in             r0, 0x3d                                \n\t"   \
                                    "st             x+, r0                                  \n\t"   \
                                    "in             r0, 0x3e                                \n\t"   \
                                    "st             x+, r0                                  \n\t"   \
                            );

#define portRESTORE_CONTEXT()                                                           \
    asm volatile (  "lds    r26, pxCurrentTCB               \n\t"   \
                                    "lds    r27, pxCurrentTCB + 1   \n\t"   \
                                    "ld             r28, x+                                 \n\t"   \
                                    "out    __SP_L__, r28                   \n\t"   \
                                    "ld             r29, x+                                 \n\t"   \
                                    "out    __SP_H__, r29                   \n\t"   \
                                    "pop    r31                                             \n\t"   \
                                    "pop    r30                                             \n\t"   \
                                    "pop    r29                                             \n\t"   \
                                    "pop    r28                                             \n\t"   \
                                    "pop    r27                                             \n\t"   \
                                    "pop    r26                                             \n\t"   \
                                    "pop    r25                                             \n\t"   \
                                    "pop    r24                                             \n\t"   \
                                    "pop    r23                                             \n\t"   \
                                    "pop    r22                                             \n\t"   \
                                    "pop    r21                                             \n\t"   \
                                    "pop    r20                                             \n\t"   \
                                    "pop    r19                                             \n\t"   \
                                    "pop    r18                                             \n\t"   \
                                    "pop    r17                                             \n\t"   \
                                    "pop    r16                                             \n\t"   \
                                    "pop    r15                                             \n\t"   \
                                    "pop    r14                                             \n\t"   \
                                    "pop    r13                                             \n\t"   \
                                    "pop    r12                                             \n\t"   \
                                    "pop    r11                                             \n\t"   \
                                    "pop    r10                                             \n\t"   \
                                    "pop    r9                                              \n\t"   \
                                    "pop    r8                                              \n\t"   \
                                    "pop    r7                                              \n\t"   \
                                    "pop    r6                                              \n\t"   \
                                    "pop    r5                                              \n\t"   \
                                    "pop    r4                                              \n\t"   \
                                    "pop    r3                                              \n\t"   \
                                    "pop    r2                                              \n\t"   \
                                    "pop    r1                                              \n\t"   \
                                    "pop    r0                                              \n\t"   \
                                    "out    __SREG__, r0                    \n\t"   \
                                    "pop    r0                                              \n\t"   \
                            );
🌐
Linux Man Pages
linux.die.net › man › 1 › avr-gcc
avr-gcc(1): GNU project C/C++ compiler - Linux man page
Normally the gcc program will exit with the code of 1 if any phase of the compiler returns a non-success return code. If you specify -pass-exit-codes, the gcc program will instead return with numerically highest error produced by any phase that returned an error indication.
🌐
Mcselec
avrhelp.mcselec.com › nop.htm
NOP - BASCOM-AVR - MCS Electronics
This statement does noting · The NOP statement will create 1 NOP assembly instruction. A NOP takes 1 machine cycle and can be used to create a small delay
Find elsewhere
🌐
Nongnu
nongnu.org › avr-libc › user-manual › using_tools.html
Options for the C compiler avr-gcc
The table matches them against the corresponding avr-gcc architecture name, and shows the preprocessor symbol declared by the -mmcu option.
🌐
Nongnu
nongnu.org › avr-libc › user-manual › cpufunc_8h_source.html
avr-libc: cpufunc.h Source File
51 \ingroup avr_cpufunc · 52 \def _NOP · 53 · 54 Execute a <i>no operation</i> (NOP) CPU instruction. This · 55 should not be used to implement delays, better use the functions · 56 from <util/delay_basic.h> or <util/delay.h> for this. For · 57 debugging purposes, a NOP can be useful ...
🌐
Stack Overflow
stackoverflow.com › questions › 62866116 › how-to-define-a-subroutine-macro-in-sperate-asm-file
c - How to define a subroutine/macro in sperate .asm file? - Stack Overflow
0000000a <here>: a: ff cf rjmp .-2 ; 0xa <here> 0000000c <fun>: c: 00 00 nop e: 00 00 nop 10: 08 95 ret · assembly language is specific to the assembler, not the target, so you need to use the language for the assembler you are using, the above ...
🌐
Nongnu
nongnu.org › avr-libc › user-manual › inline_asm.html
Inline Assembler Cookbook
The assembler instruction, "clr r3", will clear the variable counter. AVR-GCC will not completely reserve the specified register. If the optimizer recognizes that the variable will not be referenced any longer, the register may be re-used. But the compiler is not able to check wether this register ...
🌐
Nongnu
nongnu.org › avr-libc › user-manual › FAQ.html
Frequently Asked Questions
While this waste of space applies to virtually any platform C is implemented on, it's usually not noticeable on larger machines like PCs, while the waste of flash ROM storage can be very painful on a small microcontroller like the AVR. So in general, variables should only be explicitly initialized if the initial value is non-zero. ... Recent versions of GCC are now smart enough to detect this situation, and revert variables that are explicitly initialized to 0 to the .bss section.
🌐
Microchip
ww1.microchip.com › downloads › en › Appnotes › doc32074.pdf pdf
32-bit Microcontrollers Application Note Rev. 32074A-AVR-12/07
The AVR32 architecture has three possible shadowing modes: full, half or none2. Specifying no argument to the attribute defaults to none. Writing an · interrupt handler function for an interrupt with half shadow mode can then be done ... GCC provides two built-in functions for byte- swapping.
🌐
GNU
lists.gnu.org › archive › html › avr-gcc-list › 2009-02 › msg00148.html
[avr-gcc-list] How to force GCC to not to remove "nop" statements ?
February 19, 2009 - So I did that.. and the LCD doesn't work reliably. Suspecting the problem, I went straight to the generated assembly, and horror, my 4 nop statements have disappeared ! I made a few trials. It appears that up to and including 3 nop statements, GCC leaves them alone.