Am 06.12.24 um 15:50 schrieb Oleg Endo:
On Fri, 2024-12-06 at 06:32 -0700, Jeff Law wrote:

On 12/6/24 5:23 AM, Sam James wrote:
Georg-Johann Lay <a...@gjlay.de> writes:

This patch disables CRC lookup tables which consume quite some RAM.

Given that -foptimize-crc is new, it may be useful to CC the pass
authors in case they have input.
I think this is trivially OK for the AVR.  The bigger question is should
we do something more general for -Os.

CRC generation through table lookups is going to take more data space.
You need a 256 byte table for each unique CRC (sizes & polynomial), and
the code to compute the index into the table can be (from a code size
standpoint) relatively expensive as well, particularly on the
micro-controllers if the crc is to be computed in a mode wider than a
word on the target.

So I would actually even support a more general "don't optimize CRCs by
default for -Os".

I've been putting CRC tables for many years into .text / .rodata on various
MCU projects.  Never considered putting them into .data, since flash is
usually a lot larger than RAM.  What's the reasoning behind putting the
tables in .data?

Best regards,
Oleg Endo

The CRC tables ARE put into .rodata, not into .data.

The correct question is: Why is avr putting .rodata into RAM?

Suppose the following C code:

char read_c (const char *p)
{
    return p[1];
}

Where p may point to .rodata, .data, .bss etc.
Now suppose .rodata is located in flash and .data and .bss
are located in RAM.  Then you'd need the following code to
access c[1]:

if (ADDR_SPACE (p) == GENERIC)
   Use LD, LDD with address R, R++, --R or R+const
   where R is one of the address registers X, Y or Z.
   Also may use direct addressing.
else if (ADDR_SPACE (p) == __flash)
   Use LPM with Z or Z++ addressing mode.  No other
   addressing mode or address reg or instruction is
   allowed.

This would imply that there is some means to tell apart
different address spaces by looking at p.  This is *not* the
case.  In particular, flash address 0x4 looks exactly the same
like RAM address 0x4.  Both are 16-bit address 0x0004, and there
is no way to tell them apart.  It would have been possible to
reserve one bit of the address for the address space and let
the linker set that bit depending on the address space where
a symbol is placed.  This means you'd have to tell apart the
addresses at run-time.

This is not the approach taken by the avr tools.
(This was the design decision back then, and it was a good
decision, even in retrospect IMO.)

Instead, they put .rodata in RAM, and when the user wants a
table in flash, she has to put it in section .progmem.data
by hand and use inline assembly to access them.

https://avrdudes.github.io/avr-libc/avr-libc-user-manual/group__avr__pgmspace.html

As an alternative, a named address space can be used when
available, but all such objects have to be put in that
address space by hand, and all objects have to be accessed
through pointers qualified as __flash.

There are more 16-bit address spaces like __flash1, __flash2
__flash3, __flash4, __flash5 for larger devices.  And there
is a 24-bit address space that can host references to any
address space, including generic.  But using them comes
with quite some overhead because the decision which AS to use
has to be taken at run-time.  This also means the addressing
mode is limited to the ones supported by /all/ address spaces,
since you don't know at compile time where the address points to.

Johann.

Reply via email to