CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Switch() code generation

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
future



Joined: 14 May 2004
Posts: 330

View user's profile Send private message

Switch() code generation
PostPosted: Tue Dec 28, 2004 9:56 pm     Reply with quote

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







PostPosted: Wed Dec 29, 2004 3:21 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Dec 29, 2004 1:45 pm     Reply with quote

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







PostPosted: Wed Dec 29, 2004 3:52 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Dec 29, 2004 4:48 pm     Reply with quote

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







PostPosted: Fri Dec 31, 2004 10:21 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Dec 31, 2004 8:38 pm     Reply with quote

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







PostPosted: Sat Jan 01, 2005 7:00 am     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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