[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] switch/case optimisation in TWI ISR
From: |
Paulo Marques |
Subject: |
Re: [avr-gcc-list] switch/case optimisation in TWI ISR |
Date: |
Fri, 23 Dec 2005 20:05:10 +0000 |
User-agent: |
Mozilla Thunderbird 1.0.6 (X11/20050716) |
James Washer wrote:
In GCC, it's legal to have an array of gotos, so this should work...
and save a lot of space (and execution too, I would think)
void *jumptable[]={ &&label0, &&label1, &&label31};
goto *jumptable[TWSR>>3];
label0:
//code for state 0
return;
label1:
//code for state 1
return;
label31:
//code for state31
return;
This is some manual optimization that the compiler should do for you.
I've just tried this in one of the latest gcc 4.2 and it indeed does
this as expected.
This code fragment:
void test(unsigned char a)
{
switch (a) {
case 0: PORTB = 12; break;
case 1: PORTB = 72; break;
case 2: PORTB = 25; break;
case 3: PORTB = 17; break;
case 4: PORTB = 19; break;
case 5: PORTB = 29; break;
case 6: PORTB = 54; break;
case 7: PORTB = 23; break;
}
}
is translated into:
00000026 <__ctors_end>:
26: 2a c0 rjmp .+84 ; 0x7c <test+0x10>
28: 2b c0 rjmp .+86 ; 0x80 <test+0x14>
2a: 2c c0 rjmp .+88 ; 0x84 <test+0x18>
2c: 2d c0 rjmp .+90 ; 0x88 <test+0x1c>
2e: 2e c0 rjmp .+92 ; 0x8c <test+0x20>
30: 2f c0 rjmp .+94 ; 0x90 <test+0x24>
32: 30 c0 rjmp .+96 ; 0x94 <test+0x28>
34: 32 c0 rjmp .+100 ; 0x9a <test+0x2e>
0000006c <test>:
void test(unsigned char a)
{
switch (a) {
6c: e8 2f mov r30, r24
6e: ff 27 eor r31, r31
70: e8 30 cpi r30, 0x08 ; 8
72: f1 05 cpc r31, r1
74: a0 f4 brcc .+40 ; 0x9e <test+0x32>
76: ed 5e subi r30, 0xED ; 237
78: ff 4f sbci r31, 0xFF ; 255
7a: 09 94 ijmp
case 0: PORTB = 12; break;
7c: 8c e0 ldi r24, 0x0C ; 12
7e: 0b c0 rjmp .+22 ; 0x96 <test+0x2a>
case 1: PORTB = 72; break;
80: 88 e4 ldi r24, 0x48 ; 72
82: 09 c0 rjmp .+18 ; 0x96 <test+0x2a>
case 2: PORTB = 25; break;
84: 89 e1 ldi r24, 0x19 ; 25
86: 07 c0 rjmp .+14 ; 0x96 <test+0x2a>
case 3: PORTB = 17; break;
88: 81 e1 ldi r24, 0x11 ; 17
8a: 05 c0 rjmp .+10 ; 0x96 <test+0x2a>
case 4: PORTB = 19; break;
8c: 83 e1 ldi r24, 0x13 ; 19
8e: 03 c0 rjmp .+6 ; 0x96 <test+0x2a>
case 5: PORTB = 29; break;
90: 8d e1 ldi r24, 0x1D ; 29
92: 01 c0 rjmp .+2 ; 0x96 <test+0x2a>
case 6: PORTB = 54; break;
94: 86 e3 ldi r24, 0x36 ; 54
96: 88 bb out 0x18, r24 ; 24
98: 08 95 ret
case 7: PORTB = 23; break;
9a: 87 e1 ldi r24, 0x17 ; 23
9c: 88 bb out 0x18, r24 ; 24
9e: 08 95 ret
The compiler builds the jump table for you as it should.
If the values are 0,8,16,...,56, then the compiler does a sort of binary
search conditions to go to the value, bute the tests are done using just
8 bits, unlike what you've shown in your original mail.
Maybe you should try doing "switch (state >> 3)" so that the targets are
better aligned. Upgrading the compiler might be a good idea too, though
there are still situations in which gcc4 behaves worse than gcc3... :(
--
Paulo Marques
Software Development Department - Grupo PIE, S.A.
Phone: +351 252 290600, Fax: +351 252 290601
Web: www.grupopie.com
Pointy-Haired Boss: I don't see anything that could stand in our way.
Dilbert: Sanity? Reality? The laws of physics?