Re: [avr-gcc-list] How to get low byte off a function address?
Erik Christiansen schreef: On Sat, Jan 19, 2008 at 04:15:35PM +0100, Wouter van Gulik wrote: How do I do such a thing? Using the lower 8 bits is possible when loading a register so why not in a table? In the past, we've encountered other relocations that aren't handled by the avr port of binutils. It does look like this is another case that avr-ld hasn't been tweaked to handle. It sounds like you've tried one work-around, i.e. loading a register, then writing to the table, now necessarily in RAM. That's workable, code space allowing. Ehm no not exactly. I am wondering why something like this works: ldi r31, lo8(gs(foo)) and this not: .byte lo8(gs(foo)) Why does as or ld (?) in the latter state it's not constant and the second is no problem? After some more testing I found out that constructions like: .byte lo8(1024) are not allowed. Is this a bug? The learning curve for binutils internals being a bit too steep for a quick toolchain tweak, I'd alternatively be tempted to invoke a few lines of awk (from the makefile) to snaffle the absolute addresses from the map file, insert them in the table, reassemble that file, and link again. (Pre-existing dummy .byte lines would ensure addresses don't move in flash.) That's perhaps worthwhile if you're chasing this either because a RAM-resident table, or the copy loop, is intolerable in the tiny bootloader. Granted, this comes close to winning an ugly contest, but it pretty much has to work(tm). If the file with the function pointer table is linked last, then the others can be incrementally linked, and the table file linked after being awked. I am not afraid of winning the contest. As long as it save flash I am in for it :D That would be an other option yes. An afterthought: You could alternatively put the foo() functions into a separate output section, allowing the linker script to place the block of them at a fixed address. (Each could in fact be placed in an individual section.) The table could in the latter case be filled with constants. (It's not real pretty either, is it?) Well, the whole idea was to have it constant. I wanted to reduce the big cpi/brne tree and so I came up with this reduced-size jump table idea. The table in the real application should also contain an opcode. So the idea was to check against opc and the ijmp/icall to the correct function. After I wrote the assembler it turned out to be 2 bytes shorter then my cpi/brne... But I thought it reads better and it is easier to extend the table. So I kept on trying, but no success yet. Hope you can help Hope some of the above does, at least a little. :-) Thanks anyway! Wouter ___ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org http://lists.nongnu.org/mailman/listinfo/avr-gcc-list
Re: [avr-gcc-list] How to get low byte off a function address?
On Sat, Jan 19, 2008 at 04:15:35PM +0100, Wouter van Gulik wrote: How do I do such a thing? Using the lower 8 bits is possible when loading a register so why not in a table? In the past, we've encountered other relocations that aren't handled by the avr port of binutils. It does look like this is another case that avr-ld hasn't been tweaked to handle. It sounds like you've tried one work-around, i.e. loading a register, then writing to the table, now necessarily in RAM. That's workable, code space allowing. The learning curve for binutils internals being a bit too steep for a quick toolchain tweak, I'd alternatively be tempted to invoke a few lines of awk (from the makefile) to snaffle the absolute addresses from the map file, insert them in the table, reassemble that file, and link again. (Pre-existing dummy .byte lines would ensure addresses don't move in flash.) That's perhaps worthwhile if you're chasing this either because a RAM-resident table, or the copy loop, is intolerable in the tiny bootloader. Granted, this comes close to winning an ugly contest, but it pretty much has to work(tm). If the file with the function pointer table is linked last, then the others can be incrementally linked, and the table file linked after being awked. An afterthought: You could alternatively put the foo() functions into a separate output section, allowing the linker script to place the block of them at a fixed address. (Each could in fact be placed in an individual section.) The table could in the latter case be filled with constants. (It's not real pretty either, is it?) Hope you can help Hope some of the above does, at least a little. :-) Erik ___ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org http://lists.nongnu.org/mailman/listinfo/avr-gcc-list
[avr-gcc-list] How to get low byte off a function address?
Dear list, How do I do this: main.c = void foo(void) { } char table[2] = { (foo), (foo), }; int main(int argc, char* argv[]) { int adr = table[argc]+0x3F00; ((void (*) (void))adr)(); return 0; }= It gives: main.c:5: warning: initialization makes integer from pointer without a cast main.c:5: error: initializer element is not computable at load time main.c:5: error: (near initialization for 'table[0]') main.c:6: warning: initialization makes integer from pointer without a cast main.c:6: error: initializer element is not computable at load time main.c:6: error: (near initialization for 'table[1]') Why is it not computable? Why is it when I make it 16 bits? I first wanted to implement this in assembler. But I got all sorts off error, mainly gas refusing to see I only want 8 bits, not 16. So I figured I go and try this in C, but I can't get it done. You might wonder why on earth would I want to such a strange thing? Well I have a very small bootloader so I know all my functions are within the 512byte/256 word boundary. And I there for I have no need to store the full 16-bit address (in order to keep my bootloader small). I just need the low byte of the address. How do I do such a thing? Using the lower 8 bits is possible when loading a register so why not in a table? In assembler I tried this: .byte lo8(foo) .byte pm_lo8(foo) .byte lo8(pm(foo)) But all are with the same result: Error: illegal relocation size: 1 Error: junk at end of line, first unrecognized character is `(' Hope you can help Wouter ___ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org http://lists.nongnu.org/mailman/listinfo/avr-gcc-list
RE: [avr-gcc-list] How to get low byte off a function address?
-Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] org] On Behalf Of Wouter van Gulik Sent: Saturday, January 19, 2008 8:16 AM To: avr-gcc-list@nongnu.org Subject: [avr-gcc-list] How to get low byte off a function address? Dear list, How do I do this: main.c = void foo(void) { } char table[2] = { (foo), (foo), }; int main(int argc, char* argv[]) { int adr = table[argc]+0x3F00; FYI, there is a known bug in AVR GCC 4.x about adding an offset to a function pointer and doing and indirect call: GCC bug #27192 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27192 Dr. John Regehr (CCed) is the one that found the bug. IIRC, 3.4.x did not have this problem. Eric Weddington ___ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org http://lists.nongnu.org/mailman/listinfo/avr-gcc-list