I can make GCC use a jumptable using this code:
test.c
===========================================
volatile int x;
volatile int y;
void foo (void) {
x++;
}
void main(void)
{
switch(y)
{
case 0 : foo();
case 1 : foo();
case 2 : foo();
case 3 : foo();
case 4 : foo();
case 5 : foo();
case 6 : foo();
case 7 : foo();
case 8 : foo();
case 9 : foo();
case 10 : foo();
case 11 : foo();
case 12 : foo();
case 13 : foo();
case 14 : foo();
case 15 : foo();
case 16 : foo();
}
}
===========================================
Compiling using:
avr-gcc -g -Os -Wall -mmcu=atmega16 -fno-inline test.c
(Using no inline to keep disassembly small)
gcc version 4.2.2
Gives:
=======================================================================
main:
.LFB3:
.LM3:
/* prologue: frame size=0 */
/* prologue end (size=0) */
.LM4:
lds r30,y
lds r31,(y)+1
cpi r30,17
cpc r31,__zero_reg__
brsh .L23
.LM5:
subi r30,lo8(-(gs(.L22)))
sbci r31,hi8(-(gs(.L22)))
lsl r30
rol r31
lpm __tmp_reg__,Z+
lpm r31,Z
mov r30,__tmp_reg__
ijmp
.data
.section .progmem.gcc_sw_table, "a", @progbits
.p2align 1
.L22:
.data
.section .progmem.gcc_sw_table, "a", @progbits
.p2align 1
.word gs(.L5)
.word gs(.L6)
.word gs(.L7)
.word gs(.L8)
.word gs(.L9)
.word gs(.L10)
.word gs(.L11)
.word gs(.L12)
.word gs(.L13)
.word gs(.L14)
.word gs(.L15)
.word gs(.L16)
.word gs(.L17)
.word gs(.L18)
.word gs(.L19)
.word gs(.L20)
.word gs(.L21)
.text
.L5:
.LM6:
call foo
<snip>
etc...
==========================================================================
Some interesting notes:
It works only from 17 cases and up.
For smaller devices (e.g. atmega8)
It works from already from 3 cases. But then an rjmp table is used.
Why is GCC not using this rjmp scheme for the atmega16? Is it too difficult
to predict it will not pass 4k boundary?
HTH,
Wouter
Hi
Does anyone have some code that creates tablejump in Avr-gcc? This is
where gcc will create table instead of long line of if-then-else tests
I cant seem to create enough switch cases to force one!
I have been looking at compilation patterns and noticed that gcc address
is multiplied by 2 to form address for LPM (table being in ROM). LPM
needs byte address and gcc has word address.
"lsl r30
rol r31
lpm __tmp_reg__,Z+
lpm r31,Z
mov r30,__tmp_reg__
ijmp"
Asm Pattern currently expects value to be in R30. However, it would
appear that this would be better with a symbol rather than value in
register - thus providing a means to multiply that value by 2 at compile
time. (and I cant see any reason it would be called with other than
constant address in ROM)
Obviously, I'd like to test it.
Andy
_______________________________________________
AVR-GCC-list mailing list
address@hidden
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list