Re: [avr-gcc-list] How to get low byte off a function address?

2008-01-21 Thread Wouter van Gulik

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?

2008-01-20 Thread Erik Christiansen
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?

2008-01-19 Thread Wouter van Gulik
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?

2008-01-19 Thread Weddington, Eric
 

 -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