Hi Joerg >@2010.01.20_15:53:55_+0200
This will create an explicit trampoline. The rest of your code would remain the same. I've used this technique in a slightly different way previously. Caution: Compiled and inspected but not tested/simulated! #define JMP_TABLE_ENTRY(x) __asm__ __volatile__ ("jmp "#x) void jumptable_fn(void) __attribute__ ((naked)); void jumptable_fn(void) { JMP_TABLE_ENTRY(foo); JMP_TABLE_ENTRY(bar); JMP_TABLE_ENTRY(mumble); } fptr jumptable[] __attribute__((progmem)) = { jumptable_fn+0, // foo jumptable_fn+4, // bar, jumptable_fn+8, // mumble, }; An advanced use for this is to allow creation of a 'jump table' that can call functions that are not all of type fptr, ie. void fn(void). > 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. ;-) > > > _______________________________________________ > AVR-GCC-list mailing list > AVR-GCC-list@nongnu.org > http://lists.nongnu.org/mailman/listinfo/avr-gcc-list > -- Regards Dale _______________________________________________ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org http://lists.nongnu.org/mailman/listinfo/avr-gcc-list