avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-libc-dev] Request: gcrt1.S with empty section .init9


From: Georg-Johann Lay
Subject: Re: [avr-libc-dev] Request: gcrt1.S with empty section .init9
Date: Fri, 06 Jan 2017 19:31:26 +0100
User-agent: Thunderbird 2.0.0.24 (Windows/20100228)

Marko Mäkelä schrieb:
I am trying to move from assembler to C programming on the AVR while avoiding unnecessary overhead. I see that crt1/gcrt1.S contains the following code:

    .section .init9,"ax",@progbits
#ifdef __AVR_ASM_ONLY__
    XJMP    main
#else    /* !__AVR_ASM_ONLY__ */
    XCALL    main
    XJMP    exit
#endif    /* __AVR_ASM_ONLY__ */

When you need optimizations at a lever where 2 instructions matter,
then it's very likely you need a project specific start-up code and
linker description anyway.  For example, you might truncate the
vector table after the last vector used by the application.

For an easy fix, you can

1) Set up own start-up code omitting .init9

2) Provide own linker description file without input section .init9

3) Or, as a quick fix: 3a) Link with -Wl,--unique=.init9 so that
   .init9 becomes an output section, and then 3b) drop it by means
   of avr-objcopy --remove-section=.init9 foo.elf

All of these approaches require main in .init8 or earlier.

The above references to main() and exit() are needed for complying with the C standard. However, I would tend to believe that normally programs written for bare metal (such as the AVR) never terminate. Such programs do not need an exit() function or even a call or jump to main().

One approach is to handle it similar to bits of the start-up code which
are only dragged if needed.  For example, if avr-gcc sees some stuff
being put into .bss or COMMON, it emits ".global __do_clear_bss" where
the latter is implemented in libgcc, cf. http://gcc.gnu.org/PR18145

Using a similar approach for, say, call_main will lead to the unpleasant
effect that you'll get the same code twice except you are using a libc
version which removed .init9 from gcrt1.S :-) and you still need to set
a command option to /not/ drag the call to main by having the compiler
/not/ emit the ".global __init9_call_main".

gcrt1.S would need yet another #if __GNUC__ >= 7 or so, and because
toolchain distributors are usually not aware of such subtleties, you
will observe complaints of "brain dead misoptimization" à la

  CALL main
  JMP exit
  CALL main
  JMP exit

throughout avr forums all over the net if someone bundles avr-gcc
with the new feature together with avr-libc without conditional removal.

Johann

One last note: As you are coming straight from asm programming, you will
have a hard time reading the compiler generated code.  Maybe your are
shocked enough to jump into contributing to GCC :-)

Would it be possible to introduce a (necessarily non-standard) option that allows the .init9 section of the runtime libary to be omitted? Then, the user could declare their infinite main loop something like this:

__attribute__((naked)) __attribute__((section(".init9")))
static
void
mainloop (void)
{
    for (;;) do_my_stuff ();
}

This would save 3 instructions and some RAM (call main/ret, jump exit).

I am aware of the linker options -nostartfiles -nostdlib, but I do want the interrupt table and the sections .init0 through .init8.

Perhaps .linkonce or some clever use of .weak could help here? Or perhaps an alternative crt.o file could be provided for a minimal startup?

I would have tried to patch gcrt1.S myself, but I am having trouble setting up the build environment.

Best regards,

    Marko



reply via email to

[Prev in Thread] Current Thread [Next in Thread]