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

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

[avr-gcc-list] Function pointers on > 128 KiB devices, how to?


From: Joerg Wunsch
Subject: [avr-gcc-list] Function pointers on > 128 KiB devices, how to?
Date: Wed, 20 Jan 2010 14:53:55 +0100
User-agent: Mutt/1.5.20 (2009-06-14)

When porting a larger application to a 256 KiB device, we stumbled
across our function pointers and jump tables.  Consider the
following code:

#include <stdint.h>
#include <avr/pgmspace.h>

void foo(void);
void bar(void);
void mumble(void);

typedef void (*fptr) (void);

fptr jumptable[] __attribute__((progmem)) = {
        foo,
        bar,
        mumble,
};

volatile uint32_t i, j, k;

void
foo(void)
{
        for (uint8_t x = 0; x < 200; x++) {
                i = j * 5 + k * 7;
                j = i + 32412341243;
                k = i & 0x12345678ull;
        }
        for (uint8_t x = 0; x < 200; x++) {
                i = j * 5 + k * 7;
                j = i + 32412341243;
                k = i & 0x12345678ull;
        }
}

void
mumble(void)
{
        for (uint8_t x = 0; x < 200; x++) {
                i = j * 5 + k * 7;
                j = i + 32412341243;
                k = i & 0x12345678ull;
        }
        for (uint8_t x = 0; x < 200; x++) {
                i = j * 5 + k * 7;
                j = i + 32412341243;
                k = i & 0x12345678ull;
        }
}

void
bar(void)
{
        for (uint8_t x = 0; x < 200; x++) {
                i = j * 5 + k * 7;
                j = i + 32412341243;
                k = i & 0x12345678ull;
        }
}

int
main(int argc, char **argv)
{
        fptr f;

        if (argc < sizeof jumptable / sizeof jumptable[0]) {
                f = (fptr)pgm_read_word(jumptable[argc]);
                f();
        }

        return 0;
}

...compiled with (thoroughly pessimized to generate large amounts of
code):

avr-gcc -O3 -funroll-loops --param max-peeled-insns=1000000 \
--param max-completely-peel-times=1000000 \
--param max-unrolled-insns=1000000 \
--param=max-completely-peeled-insns=1000000 \
--param max-average-unrolled-insns=1000000 \
-mmcu=atmega2560 -std=c99 -g -o foo.elf foo.c

This yields:

/tmp/cc1QZqci.o: In function `foo':
/tmp/foo.c:20: warning: internal error: out of range error

Trying to replace the pgm_read_word() by a pgm_read_dword_far() just
adds more warnings about casting pointers/integers of different size,
but doesn't help for the initial "out of range" error anyway.

Is there any option at all to use function pointers for a device which
supports code sizes > 128 KiB?  I (incorrectly) assumed these were
replaced by trampoline pointers, but apparently, they aren't.

Any ideas welcome, possibly including quick&dirty inline asm hacks to
generate the indirect call.

-- 
cheers, J"org               .-.-.   --... ...--   -.. .  DL8DTL

http://www.sax.de/~joerg/                        NIC: JW11-RIPE
Never trust an operating system you don't have sources for. ;-)




reply via email to

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