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

Question on bitfield assignments

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



Joined: 12 Dec 2008
Posts: 4

View user's profile Send private message

Question on bitfield assignments
PostPosted: Fri Dec 12, 2008 5:39 pm     Reply with quote

I recently updated to version 4.083 PCB/PCM. While evaluating the SW that was built with the new compiler I found one particular feature that no longer worked. I narrowed it down to a single line of code, where a bitwise structure member was being assigned. The code is shown below, with my added comments for context...
Code:
// When executed, smbus_data == 0x05
// poweroff_pend_flag is the least signicant bit of the flag2 structure
flag2.poweroff_pend_flag = smbus_data & 0x04;
00E5    0873     MOVF 0x73, W   // smbus_data variable location
00E6    3904     ANDLW 0x4
00E7    00F8     MOVWF 0x78     // SCRATCH area, ends up with a value of 0x04
00E8    1046     BCF 0x46, 0      // clear poweroff_pend_flag member of flag2 data structure
00E9    1878     BTFSC 0x78, 0   // Tests bit 0, should be testing bit 2!!!
00EA    1446     BSF 0x46, 0


As noted above, the offending line of assembly code is that at 00e9 where it is testing the wrong bit.

I fixed this problem by changing the code to...
Code:
if (smbus_data & 0x05)
{
    flag2.poweroff_pend_flag = 1;
}

One interesting thing about this fix, the resulting assembly code is now reduced to...
Code:
BTFSC 0x73, 0x2
BSF 0x46, 0

So is this a compiler bug or am I abusing the C standard on how bitwise structure members can be assigned?

Dave Schmidt
Tektronix, Inc.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Dec 12, 2008 5:53 pm     Reply with quote

Post your PIC.
davesch2008



Joined: 12 Dec 2008
Posts: 4

View user's profile Send private message

PostPosted: Fri Dec 12, 2008 5:56 pm     Reply with quote

Sorry, the target is a PIC16F76.

Dave Schmidt
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Dec 12, 2008 6:01 pm     Reply with quote

Can you post a little test program with the structure declaration, etc.,
so I can duplicate this ?
davesch2008



Joined: 12 Dec 2008
Posts: 4

View user's profile Send private message

PostPosted: Fri Dec 12, 2008 6:10 pm     Reply with quote

I will, but not until the first of next week.

Dave Schmidt
Ttelmah
Guest







PostPosted: Sat Dec 13, 2008 4:35 am     Reply with quote

What you don't say, is how old the previous version compiler was?.

There was a change some time ago, in the way a logic test, would assign to a bitfield. Historically, the compiler assigned the test as 'non zero, assigns to true'. More recently (last year!), it switched to 'bit 0 == 1 assigns to true'.

This was supposedly done to make the compiler closer to ansi specification....

This would explain your older test failing, since the bitwise and, will always result in bit0 == 0, so in a 'false' return.

The new test, as shown in C, does not quite give the same functionality as the old. You would get the bitfield set to 1, if the incoming number == 1, 4, or 5. However the assembler you post, would be for:
Code:

if (smbus_data & 0x04)
{
    flag2.poweroff_pend_flag = 1;
}

Mispost?.

There is a big difference in the new' code, in that it won't ever _clear_ the bit, while the old, would.

The correct replacement, would be:
Code:

flag2.poweroff_pend_flag = ((smbus_data & 0x04)!=0);


Best Wishes
davesch2008



Joined: 12 Dec 2008
Posts: 4

View user's profile Send private message

PostPosted: Sat Dec 13, 2008 12:40 pm     Reply with quote

I don't know the exact version (its not installed anymore) but it was at least three years old. So thanks for the explanation on why the behavior is now different with the new compiler.

The posted workaround code is correct. The flag can only be set there, it is cleared in another portion of the code (i.e., it could be set multiple times prior to being cleared later).

Thanks for the help,
Dave Schmidt
Tektronix, Inc.
Guest








PostPosted: Sat Dec 13, 2008 1:37 pm     Reply with quote

Will this be the same?

Bit evaluation
Code:
flag2.poweroff_pend_flag = ((smbus_data & 0x04)!=0);


Logical evaluation
Code:
flag2.poweroff_pend_flag = (smbus_data && 0x04);
Ttelmah
Guest







PostPosted: Sat Dec 13, 2008 4:18 pm     Reply with quote

Given you don't have to clear the bit, the test and direct assignment, will always be much more efficient. Sometimes it is easy to forget that a simple assignment like this, wil be copying both the '1' result, and the '0' result, while a single test and assign, only has to deal with half this work.

Best Wishes
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