public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
From: Henri Cloetens <henri.cloetens@blueice.be>
To: gcc-help@gcc.gnu.org
Subject: Re: RFC: AVR interrupt handling issue
Date: Sat, 18 Dec 2021 17:31:18 +0100	[thread overview]
Message-ID: <58038025-f6b3-4f41-00bb-31e28467420e@blueice.be> (raw)
In-Reply-To: <f07660af-5827-e893-4f67-c0ebaef29238@mnementh.co.uk>

Dear Sir,

To customize the stack/unstacking, you need to modify the code of your 
backend port.
I mean, the emitting of the stack/unstacking for the normal case (no 
interrupt, but function call),
is in the backend part, NOT in the 'main' files, that are not intended 
to be modified.
I would recommend you look there, and also in other backends, to find 
out how to do this.

Best Regards,

Henri.


On 12/18/21 5:00 PM, Ian Molton wrote:
> Hi all,
>
> I posted about this yesterday on the binutils list, but in the light of
> day, I find myself re-thinking it;
>
> Right now, gcc will emit ISR prologues and epilogues such as this:
>
> __vector_35:
>          push r1          ;
>          push r0          ;
>          in r0,__SREG__   ; ,
>          push r0          ;
>          clr __zero_reg__                 ;
>          in r0,__RAMPZ__  ; ,
>          push r0          ;
>          push r18                 ;
> 	push r19
> 	push r20                 ;
>          push r21                 ;
>          push r22                 ;
>          push r23                 ;
>          push r24                 ;
>          push r25                 ;
>          push r26                 ;
>          push r27                 ;
>          push r30                 ;
>          push r31                 ;
>          push r28                 ;
>          push r29                 ;
>
>          // External func call to provoke pro/epilogue
> 	// generation for this example...
> 	call foo_func();
> 	...
>
> 	pop r29          ;
>          pop r28          ;
>          pop r31          ;
>          pop r30          ;
>          pop r27          ;
>          pop r26          ;
>          pop r25          ;
>          pop r24          ;
>          pop r23          ;
>          pop r22          ;
>          pop r21          ;
>          pop r20          ;
>          pop r19          ;
>          pop r18          ;
>          pop r0           ;
>          out __RAMPZ__,r0         ; ,
>          pop r0           ;
>          out __SREG__,r0  ; ,
>          pop r0           ;
>          pop r1           ;
>          reti
>
>
> The problem I have is that I want to switch to a separate irq stack when
> I get an interrupt, which I cannot do in C, since all the prologue is
> executed before the function body.
>
> I *can* do it if I use an assembler stub that then calls my ISR, which
> switches stacks, and pushes the address of a custom epilogue onto the
> stack, before executing the ISR, but this obviously wastes a lot of
> cycles pushing the epilogue address, and by necessity, some of the
> registers that the existing ISR prologue will redundantly push again.
>
> likewise, being able to insert my own epilogue sequence would allow me
> to avoid an additional branch in the return path from the ISR.
>
> I can see two solutions to this problem:
>
> 1) Allow the compiler to omit certain registers from being saved in the
> ISR prologue
>
> 2) Allow the user to specify custom pro/epilogue functions.
> (-finstrument functions is similar, but not close enough)
>
>
> 1) would work, but would require careful futzing about with the linker
> to arrange the code in such a way that my prologue and epilogue are
> located immediately around the ISR code. implementation could look like
> -mno-save-isr-prologue="r0,r1,SREG,r26,r27" (or whatever regs the custom
> prologue might save prior to the ISR prologue)
>
> 2) would be ideal. The compiler would know which registers the custom
> prologue functions use, and would therefore be able to omit saving them
> from the ISR prologue (and conversely from the epilogue).
>
>
> Something like
>
> __attribute__ ((naked))
> void my_isr_prologue (void)
> {
> 	asm volatile("... whatever" : : : <clobbered regs>);
> }
>
> __attribute__ ((naked))
> void my_isr_epilogue (void)
> {
> 	asm volatile("... un-whatever" : : : <clobbered regs>);
> 	asm volatile("reti");
> }
>
> __attribute__ ((__isr_prologue__(my_isr_prologue, my_isr_epilogue)))
> __attribute__ ((signal))
> __vector_35(void)
> {
>
> ... do interrupt-y things ...
>
> }
>
> Thoguhts? I can see that I could implement option 1) thus:
>
> I specify -mno-gas-isr-prologues to force gcc to emit full
> pro/epi-logues in the assembler output.
>
> I can modify gcc/config/avr/avr.c at this point:
>
> (~line 1893)
>
>    avr_regs_to_save (&set);
>
>    if (no-save-isr-prologue)
>    {
>      // FIXME Remove registers my custom prologue saves from the set
>      ...
>    }
>
>    if (cfun->machine->is_interrupt || cfun->machine->is_signal)
>      {
>      ...
>
> which just leaves me with a (trivial) script to write that can stuff my
> prologue / epilogue into the assembler, and re-assemble it into an object.
>
> The downside is that very simple ISRs which don't need many registers
> will be less efficient. But we're calling C here, and I would write such
> simple ISRs in assembler anyway.
>
>
> Option 2) would require more knowledge of gcc than I currently have.
>
>
> Other (doomed? cursed?) options:
>
> 3)
>
> It almost seems like this could be solved if a function with
> __attribute__ ((signal)) could (inline-) call another function with the
> same attribute. The first function would not need to save any call-used
> registers other than the ones it uses itself, and the called function
> would be able to avoid saving any call-used registers that were saved by
> its calling function.
>
> I suspect, however that that approach is probably doomed to failure, as
> inlining the second function (to avoid the overhead of calling it) would
> presumably also relocate its register save instructions right back to
> the first functions prologue, where it isn't wanted, as described above.
>
> 4)
>
> Use a naked function for the ISR and a script to process the assembler
> in order to generate the prologue and epilogue
>
> The GCC docs state that one should not write C code in a naked function.
> Presumably, as long as you add enough prologue to provide a C
> environment, this isn't a problem, but its explicitly disallowed, and
> would require me writing a script to parse the assembler output to
> generate the entire prologue/epilogue sequences. In a sense, this is the
> "purest" option, but I suspect properly determining the registers used
> in this way would be a challenge.
>
> Presumably this is why the __gcc_isr method of generating pro/epilogues
> is a task split between GCC and binutils?
>
> I am at a bit of a loss as to what information binutils is supposed to
> have in this case, that gcc does not - why *is* it done that way?
>
> I've poked at inline asm with gcc, and find that I can use clobbers to
> force a save of RAMPZ (etc.) from inline assembler within an ISR, so I
> don't really "get" what the __gcc_isr approach is buying... the ability
> to write inline asm without being explicit about clobbers? What for?
>
> Thoughts?



  reply	other threads:[~2021-12-18 16:31 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-18 16:00 Ian Molton
2021-12-18 16:31 ` Henri Cloetens [this message]
2021-12-18 17:47   ` Ian Molton
2021-12-18 18:07     ` Ian Molton
2021-12-20 21:06   ` gcc not generating dwarf prologue_end and epilogue_begin .loc directives (was: Re: RFC: AVR interrupt handling issue) Ian Molton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=58038025-f6b3-4f41-00bb-31e28467420e@blueice.be \
    --to=henri.cloetens@blueice.be \
    --cc=gcc-help@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).