avr-gcc-list
[Top][All Lists]
Advanced

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

[avr-gcc-list] RFC: ATmega256x and 16-bit function pointers


From: Marek Michalkiewicz
Subject: [avr-gcc-list] RFC: ATmega256x and 16-bit function pointers
Date: Fri, 18 Mar 2005 00:20:56 +0100
User-agent: Mutt/1.5.6+20040907i

Hi,

I think I've just come up with a potential solution for the ATmega256x
problem with function pointers (16 bits not enough), at the cost of
reasonable overhead (no shift by 6 with 128-byte function alignment).

The idea: output each function in two parts, in different sections:
 - JMP instruction, pointing to the function body
 - function body

Now, the first section must be in the lowest 128K of program memory
(so you can take the 16-bit program memory address of the jump),
but it's just 4 bytes for each function in the program (unlikely to
run out of space).  JMP can reach anywhere in the 8 MB address space,
so there are no restrictions where function body can be located.

This means small runtime overhead (JMP) for each function call, but
we can still have 16-bit function pointers (larger pointers would
result in much more overhead, and are a lot of work to implement).

One possible speed optimization would be to only go through the jump
for indirect calls (in CALL, use the function body address directly)
if we figure out how to do this (probably some deep linker magic:
detecting a CALL to a JMP and changing it to point to JMP target).

And, one possible size optimization would be to remove unnecessary
JMP instructions (for functions whose address is never taken), but
this hack is only for >128K devices anyway so it's low priority.

I'm not sure what to do with -ffunction-sections - both the jump
and the function body should be in their own unique sections?
(The linker script must recognize section names so that the jumps
go into the "below 128K" section in this case, too.)

And, the same problem we have with -mcall-prologues in C++ exists
here, too (worse, because -mcall-prologues is just an option):
the function body must have a label with a name constructed from
mangled function name, but I haven't yet figured out the mangled
equivalent of current_function_name() in GCC.

I'm not yet sure about section naming convention to use: put the jumps
in a special "low" section and function body in .text as usual, or the
jumps in .text and function body in a special "high" section.

Interrupt/signal functions are often time critical, so there should
be some way to avoid jumping to another jump.  Taking the address of
an interrupt handler (if supported at all) probably should give us
the vector address (2, 4, 6, ...) directly.

There are some caveats with indirect function calls in bootloaders:
EIND must be initialized to point to the last 128K, and EICALL must
be used instead of ICALL.  As long as we are not switching between
different 128K pages (like indirect calls to bootloader functions
from the application), EIND doesn't need to be changed.

Right now, this looks like the easiest way toward supporting ATmega256x
and possibly larger devices (without a major redesign, likely necessary
to make pointers larger).  Comments?

Thanks,
Marek





reply via email to

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