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 CCS Technical Support

problem comparing #bit values

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



Joined: 07 Aug 2008
Posts: 17

View user's profile Send private message

problem comparing #bit values
PostPosted: Tue Sep 23, 2008 11:00 am     Reply with quote

I was trying to compress my code a little by replacing int8 flags TRUE/FALSE with #BIT fields. Seems this code change messed up my logic badly.

I did some digging and it seems that the compiler is not producing the correct ASM code.

For me the following code outputs "HI" yet my logic is clear.

Is this a bug or just my misunderstanding on how #bit can be used.

Re
Sean M


Code:

//test.c
// PCM compiler version 4.070;3/11/2008 on linux.
// using a DLP-245PG-G board.

#include <16F877A.h>            // Select the development device
#device *=16F877A

#fuses HS,WDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP,NOCPD,NOWRT      // Effectively just suggested programmer settings
#use delay(clock=20M)

#define PIN_WR    PIN_B2
#define PIN_RD    PIN_B1
#define PIN_TXE   PIN_E2
#define PIN_RXF   PIN_E1


#separate
char m_getc();
#separate
void m_putc(char);
#separate
BOOLEAN m_kbhit();



void main(void) {
    char testbits=0;
    #bit testbit0 = testbits.0
    #bit testbit1 = testbits.1
    testbit0=1;
    testbit1=1;
    if(testbit1 != testbit0) {
       printf(m_putc,"HI\r\n");
    }
}





char m_getc() {

       char c;
        while(input(PIN_RXF)==1);//wait for USB data to arrive
   set_tris_d( 0xff );//all input
   output_low(PIN_RD);//pull RD low
   delay_us(20);
       c = input_d();//read data
   output_high(PIN_RD);//take RD back high
   
   // send back a byte
   return c;
   
}


void m_putc(char c) {
   //send the byte back through the USB interface
   set_tris_d( 0x0 );//all output

   while(input(PIN_TXE)==1);//when TXE is high do not write

   output_d(c);
   delay_us(50);
       output_low(PIN_WR);//PIN_B2=0
   delay_us(20);
       output_high(PIN_WR);//PIN_B2=1
}

BOOLEAN m_kbhit() {

  return (input(PIN_RXF)!=1) ? TRUE: FALSE;
}
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Tue Sep 23, 2008 11:38 am     Reply with quote

I'm also stumbling over this CCS special from time to time.

In most places, CCS is treating the bit values correctly as binary value. But in some places, the compiler seems to find a way to misunderstand them, e. g. in the above comparison
Code:
(testbit1 != testbit0)

To be treated right, unconditionally, the expression must look like
Code:
((testbit1!=0) != (testbit0 !=0))

As an additional remark, the same thing happens with int1 variables, that are residing in different bit positions and logical valued expressions as
Code:
(testbit & 1 != testbit & 2)


As far as I see, this behaviour is specicific to CCS, it also existed in V3. I regard it as non-compliant to the C standard. If you're using a lot of different processors and C-compilers, it's difficult to remember always the
eccentricities of each one.

Regards,
Frank
mathewss



Joined: 07 Aug 2008
Posts: 17

View user's profile Send private message

PostPosted: Tue Sep 23, 2008 8:35 pm     Reply with quote

Thanks Frank very much what that is what I figured.

Reading the ASM code my test case used it sure didnt seem right.

The ASM output from your method looks right. Now can it be improved?

Anyone think a method exists with fewer instructions? 10 instructions to do this seems a bit much. If i find a better way I will build a macro or something to do the job in ASM.


Code:

....................     if((testbit1!=0) != (testbit0 !=0)) {
003D:  MOVLW  00
003E:  BTFSC  21.1
003F:  MOVLW  01
0040:  MOVWF  23
0041:  MOVLW  00
0042:  BTFSC  21.0
0043:  MOVLW  01
0044:  SUBWF  23,W
0045:  BTFSC  03.2
0046:  GOTO   052


Re
Sean M
Ttelmah
Guest







PostPosted: Wed Sep 24, 2008 7:33 am     Reply with quote

I'd suggest a different approach.
I think the problem comes about because of the change in the way that 'one bit' values are propagated to eight bit values in the latter CCS forms, rather than CCS2. The #bit directive, is treated as a single bit _of_ an eight bit value, rather than an genuine 'one bit' value.
When dealing with 8bit values, the latter compilers test for true/false, by only testing the LSb of the values. This was actually done to be compliant with ANSI recommendations, but is then being misapplied to the #bit values...
Short values, don't have this problem. So (for the current compilers that support arrays of bits), use:
Code:

union bits {
   char c;
   short b[8];
};

//Then in the main:

   union bits testbits;
   testbits.b[0]=1;
   testbits.b[1]=1;
   if (testbits.b[0] != testbits.b[1]) {


This gives:
Code:

00068:  BSF    11.0
....................    testbits.b[1]=1;
0006A:  BSF    11.1
....................    if (testbits.b[0] != testbits.b[1]) {
0006C:  CLRF   00
0006E:  BTFSC  11.1
00070:  BSF    00.0
00072:  MOVF   11,W
00074:  XORWF  00,W
00076:  ANDLW  01


Which is basically as efficient as possible. :-)

Best Wishes
mathewss



Joined: 07 Aug 2008
Posts: 17

View user's profile Send private message

PostPosted: Wed Sep 24, 2008 9:41 am     Reply with quote

Sweeet....

thats a huge improvement thanks.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Wed Sep 24, 2008 10:58 am     Reply with quote

Interesting. The example shows, that the compiler basically is able to treat bit variables correct and efficient, if it recognizes them, as expectable.
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