Hi, I've dug about in the sourcecode of gcc and gas, in order to understand how it works.
in particular, in gas avr_patch_gccisr_frag (fragS *fr, int reg) There is behaviour, specific to AVR that allows binutils to analyse the compiler output for interrupt routines, and causes it to generate special prologue/epilogues that preserve the CPU state. My problem is that these appear to have been designed with a particular approach/model for interrupt handling in mind, and are proving to be frustrating now that I wish to write my own kernel for AVR. In particular, I want to call schedule() following an interrupt handler (and prior to returning to a thread) that causes schedule() to be required, which would in turn require saving the entire current thread state, but if I don't call it, then I want to avoid pushing a bunch of un-necessary regs. For example void __attribute__((signal)) __vector_20(void) { char a; a++ return; } As it stands, the code generated by gcc, I assume, looks something like: .foo gccisr 0 add rX ... gccisr 1 gccisr 2 Which would compile into something like: (in its "fuller form") .foo push r1 push r0 in r0, 0x3f ; 63 push r0 eor r1, r1 push rX add rx ... pop rX pop r1 pop r0 It seems that it even checks called functions, so its ideal for writing interrupt handlers. However, I want to use a separate stack for IRQs, and this prevents me doing so, AFAICT. I could have my interrupt call an assembler stub beforehand to switch SP, but to do so, I must save a couple of registers to the stack. I don't want to save them *again* in the prologue, as its wasteful and on a hot path. I could write code to switch stack within foo(), but this won't work, since the gccisr prologue will come before it, which is not right either. I can see no other gcc / binutils option that would allow me to achieve this trick - I had hoped that I could use some sort of function prologue, but I can't see how, and it would suffer the same problems as above. I can see that I can trivially modify binutils so that it *NEVER* emits the code to save SREG, only the registers to push. This gets be half-way there. What I need then, is a way to prepend my ISR "prologue" to foo() In a simplistic way, I could call an assembler shim, eg. .call_foo <my ISR prologue to save SREG> <switch stack> rjmp foo() which would clearly work, but the rjmp could be avoided if I can place the code of .call_foo immediately prior to the code of foo(). I assume the linker can be instructed to do this, but I'm at a bit of a loss as to how right now. It seems like being able to disable the "extra prologue" and only have gas fix up the stack, would be a useful option. Documentation is sparse in this area, and if gcc has a more generic way of doing this or if I'm barking up the wrong tree, please do mention... -Ian