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?
next prev parent 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).