|
|
View previous topic :: View next topic |
Author |
Message |
future
Joined: 14 May 2004 Posts: 330
|
Switch() code generation |
Posted: Tue Dec 28, 2004 9:56 pm |
|
|
I want to know if its the correct code for these statements, if this big size is normal.
All irrelevant code was removed.
Thank you.
Code: | #define AD_SEL_CHANNEL0 0
#define AD_WAIT_DELAY0 1
#define AD_READ_SAMPLE0 2
#define AD_SEL_CHANNEL1 3
#define AD_WAIT_DELAY1 4
#define AD_READ_SAMPLE1 5
...Until AD_SEL_CHANNEL7... AD_READ_SAMPLE7
switch(state_ad)
{
10E2: MOVF state_ad,W
10E4: XORLW 00
10E6: BZ 116E
10E8: XORLW 01
10EA: BZ 117E
10EC: XORLW 03
10EE: BZ 118E
10F0: XORLW 01
10F2: BZ 11A8
10F4: XORLW 07
10F6: BTFSC STATUS.2
10F8: BRA 11C0
10FA: XORLW 01
10FC: BTFSC STATUS.2
10FE: BRA 11D2
1100: XORLW 03
1102: BTFSC STATUS.2
1104: BRA 11EC
1106: XORLW 01
1108: BTFSC STATUS.2
110A: BRA 11FC
110C: XORLW 0F
110E: BTFSC STATUS.2
1110: BRA 120E
1112: XORLW 01
1114: BTFSC STATUS.2
1116: BRA 1228
1118: XORLW 03
111A: BTFSC STATUS.2
111C: BRA 1238
111E: XORLW 01
1120: BTFSC STATUS.2
1122: BRA 124A
1124: XORLW 07
1126: BTFSC STATUS.2
1128: BRA 125A
112A: XORLW 01
112C: BTFSC STATUS.2
112E: BRA 1272
1130: XORLW 03
1132: BTFSC STATUS.2
1134: BRA 1284
1136: XORLW 01
1138: BTFSC STATUS.2
113A: BRA 12B2
113C: XORLW 1F
113E: BTFSC STATUS.2
1140: BRA 12C2
1142: XORLW 01
1144: BTFSC STATUS.2
1146: BRA 12D4
1148: XORLW 03
114A: BTFSC STATUS.2
114C: BRA 12E4
114E: XORLW 01
1150: BTFSC STATUS.2
1152: BRA 12F4
1154: XORLW 07
1156: BTFSC STATUS.2
1158: BRA 1306
115A: XORLW 01
115C: BTFSC STATUS.2
115E: BRA 1316
1160: XORLW 03
1162: BTFSC STATUS.2
1164: BRA 1326
1166: XORLW 01
1168: BTFSC STATUS.2
116A: BRA 1338
116C: BRA 1346
case AD_SEL_CHANNEL0:
state_ad=AD_WAIT_DELAY0;
case AD_WAIT_DELAY0:
state_ad=AD_READ_SAMPLE0;
case AD_READ_SAMPLE0:
state_ad=AD_SEL_CHANNEL1;
case AD_SEL_CHANNEL1:
... Until channel 7 |
|
|
|
Ttelmah Guest
|
|
Posted: Wed Dec 29, 2004 3:21 am |
|
|
First comment.
Where are your 'break' statements?. As shown in the small bit of code at the end of the assembler, each branch, will 'run through' into the next....
There are two 'distinct' code versions generated for switches. If you do a switch statement, that is smaller than about 5 cases (this has varied with different compiler versions), or contains a 'default' statement, the compiler will effectively perform 'if' branches for every case. This produced code like you are showing. If however you code without a default statement, and with more cases (and with a break at the end of each case...), the compiler will then generate a 'table jump' instead. This is bulkier for a small number of cases, but results in smaller code, and makes the branch times the same for each case, for larger routines.
Generally, it may be a good idea, to have a default 'equivalent', so you can code with something like:
Code: |
if (test_val>7) {
//'default' handler here
}
else switch(test_val) {
case 0:
//first handler
break;
case 1:
//second hander
break;
.....
case 7:
//eighth handler
break;
}
|
This results in a 'table based' switch, with the code generated as:
1DBA: NOP(FFFF)
1DBC: MOVFF FF2,0E
1DC0: BCF FF2.7
1DC2: ADDWF FE8,W
1DC4: ADDLW E5
1DC6: MOVWF FF6
1DC8: MOVLW 1D
1DCA: MOVWF FF7
1DCC: BTFSC FD8.0
1DCE: INCF FF7,F
1DD0: TBLRD*-
1DD2: NOP(FFFF)
1DD4: MOVF FF5,W
1DD6: MOVWF FFA
1DD8: TBLRD*
1DDA: NOP(FFFF)
1DDC: MOVF FF5,W
1DDE: BTFSC 0E.7
1DE0: BSF FF2.7
1DE2: MOVWF FF9
1DE4: DATA EE,14
1DE6: DATA 44,15
1DE8: DATA 9A,15
1DEA: DATA AE,15
1DEC: DATA C2,15
1DEE: DATA 26,1D
1DF0: DATA FC,15
1DF2: DATA 16,16
The values in the 'data' statements, are the addresses of each routine.
Best Wishes |
|
|
future
Joined: 14 May 2004 Posts: 330
|
|
Posted: Wed Dec 29, 2004 1:45 pm |
|
|
The breaks were removed in the post... there are 24 cases and no default one.
Compiler is 3.212.
I was hoping to see a table jump instead of the long test sequence. |
|
|
Ttelmah Guest
|
|
Posted: Wed Dec 29, 2004 3:52 pm |
|
|
future wrote: | The breaks were removed in the post... there are 24 cases and no default one.
Compiler is 3.212.
I was hoping to see a table jump instead of the long test sequence. |
Post the source code, and the definitions for the values use in the switch. There is something 'odd' in the code as posted, since it seems to be duplicating cases in places, suggesting that the values are not all unique. If this is the case, a branch form will result.
Best Wishes |
|
|
future
Joined: 14 May 2004 Posts: 330
|
|
Posted: Wed Dec 29, 2004 4:48 pm |
|
|
Delays are respected, just the code for switch(); is the problem.
Code: | #define AD_SEL_CHANNEL_0 0
#define AD_WAIT_DELAY_0 1
#define AD_READ_SAMPLE_0 2
#define AD_SEL_CHANNEL_1 3
#define AD_WAIT_DELAY_1 4
#define AD_READ_SAMPLE_1 5
#define AD_SEL_CHANNEL_2 6
#define AD_WAIT_DELAY_2 7
#define AD_READ_SAMPLE_2 8
#define AD_SEL_CHANNEL_3 9
#define AD_WAIT_DELAY_3 10
#define AD_READ_SAMPLE_3 11
#define AD_SEL_CHANNEL_4 12
#define AD_WAIT_DELAY_4 13
#define AD_READ_SAMPLE_4 14
#define AD_SEL_CHANNEL_5 15
#define AD_WAIT_DELAY_5 16
#define AD_READ_SAMPLE_5 17
#define AD_SEL_CHANNEL_6 18
#define AD_WAIT_DELAY_6 19
#define AD_READ_SAMPLE_6 20
#define AD_SEL_CHANNEL_7 21
#define AD_WAIT_DELAY_7 22
#define AD_READ_SAMPLE_7 23
void sense_world(void)
{
switch(state_ad)
{
case AD_SEL_CHANNEL_0:
ADCON0=ADCHANNEL_0;
state_ad=AD_WAIT_DELAY_0;
break;
case AD_WAIT_DELAY_0:
read_adc(ADC_START_ONLY);
state_ad=AD_READ_SAMPLE_0;
break;
case AD_READ_SAMPLE_0:
ad0raw=ADRESH;
state_ad=AD_SEL_CHANNEL_1;
break;
case AD_SEL_CHANNEL_1:
ADCON0=ADCHANNEL_1;
state_ad=AD_WAIT_DELAY_1;
break;
case AD_WAIT_DELAY_1:
read_adc(ADC_START_ONLY);
state_ad=AD_READ_SAMPLE_1;
break;
case AD_READ_SAMPLE_1:
ad1raw=ADRESH;
state_ad=AD_SEL_CHANNEL_2;
break;
case AD_SEL_CHANNEL_2:
ADCON0=ADCHANNEL_2;
state_ad=AD_WAIT_DELAY_2;
break;
case AD_WAIT_DELAY_2:
read_adc(ADC_START_ONLY);
state_ad=AD_READ_SAMPLE_2;
break;
case AD_READ_SAMPLE_2:
ad2raw=ADRESH;
state_ad=AD_SEL_CHANNEL_3;
break;
case AD_SEL_CHANNEL_3
ADCON0=ADCHANNEL_3;
state_ad=AD_WAIT_DELAY_3;
break;
case AD_WAIT_DELAY_3:
read_adc(ADC_START_ONLY);
state_ad=AD_READ_SAMPLE_3;
break;
case AD_READ_SAMPLE_3:
ad3raw=ADRESH;
state_ad=AD_SEL_CHANNEL_4;
break;
case AD_SEL_CHANNEL_4:
ADCON0=ADCHANNEL_4;
state_ad=AD_WAIT_DELAY_4;
break;
case AD_WAIT_DELAY_4:
read_adc(ADC_START_ONLY);
state_ad=AD_READ_SAMPLE_4;
break;
case AD_READ_SAMPLE_4:
ad4raw=ADRESH;
state_ad=AD_SEL_CHANNEL_5;
break;
case AD_SEL_CHANNEL_5:
ADCON0=ADCHANNEL_5;
state_ad=AD_WAIT_DELAY_5;
break;
case AD_WAIT_DELAY_5:
read_adc(ADC_START_ONLY);
state_ad=AD_READ_SAMPLE_5;
break;
case AD_READ_SAMPLE_5:
ad5raw=ADRESH;
state_ad=AD_SEL_CHANNEL_6;
break;
case AD_SEL_CHANNEL_6:
ADCON0=ADCHANNEL_6;
state_ad=AD_WAIT_DELAY_6;
break;
case AD_WAIT_DELAY_6:
read_adc(ADC_START_ONLY);
state_ad=AD_READ_SAMPLE_6;
break;
case AD_READ_SAMPLE_6
ad6raw=ADRESH;
state_ad=AD_SEL_CHANNEL_7;
break;
case AD_SEL_CHANNEL_7:
ADCON0=ADCHANNEL_7;
state_ad=AD_WAIT_DELAY_7;
break;
case AD_WAIT_DELAY_7:
read_adc(ADC_START_ONLY);
state_ad=AD_READ_SAMPLE_7;
break;
case AD_READ_SAMPLE_7:
ad7raw=ADRESH;
state_ad=AD_SEL_CHANNEL_0;
break;
}
} |
|
|
|
Ttelmah Guest
|
|
Posted: Fri Dec 31, 2004 10:21 am |
|
|
What is the chip?.
The code you have posted, gives a table based jump for me, but this does (of course), require a chip that supports the TBLRD instruction. I was assuming this was a chip, with these functions, because of the presence of the BZ, and BRA instructions, but maybe this is not the case?.
Have you tried altering the optimisation level of the compiler?. A few versions ago, there were some problems that needed this turning 'down', and I never checked whether doing this might cause the table version to disappear...
Try with 3.191. I must admit, I hit so many oddities with the latter releases, that I have been 'shying' away from these, till they are more stable.
Best Wishes |
|
|
future
Joined: 14 May 2004 Posts: 330
|
|
Posted: Fri Dec 31, 2004 8:38 pm |
|
|
PIC 18F458 and compiler 3.212 optimization 10.
Its bad because I am using a lot of switches and state machines.
I will try older versions, lets see what happens.
Happy new year!
SOLVED: The Switch can not be in a #INLINE function!! Almost 100bytes less now. |
|
|
Ttelmah Guest
|
|
Posted: Sat Jan 01, 2005 7:00 am |
|
|
future wrote: | PIC 18F458 and compiler 3.212 optimization 10.
Its bad because I am using a lot of switches and state machines.
I will try older versions, lets see what happens.
Happy new year!
SOLVED: The Switch can not be in a #INLINE function!! Almost 100bytes less now. |
An interesting discovery.
Explains why the example worked for me (no #inline in the post).
A very happy new year to everybody, with 'thoughts' for anyone in the areas in Asia, or who has friends/family in these areas. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|