Bit Variable

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Bit Variable

4,282 Views
RubenCG
Contributor III
Hi All,

I'm working with mc9s12xdp512, Codewarrior hcs12 IDE with its C Compiler.
I'm searching the way to define a "one bit" variable. Is it possible to create it without bitfields? I have to manipulate up to 256 variables (all one bit wide).

Thanks in advance
Labels (1)
0 Kudos
16 Replies

1,016 Views
colinh
Contributor I
Hi
Sorry I missed most of this thread - that's the problem with time zones and being in Australia...

Anyway I tried out two variants of the inline function.  First with an array of unsigned chars:

Code:
   24:         bitVar = getbit(array, 23);
  0004 ce0000       LDX   #array
  0007 6e81         STX   1,SP
  0009 c617         LDAB  #23
  000b 6b80         STAB  0,SP
  000d e602         LDAB  2,X
  000f c480         ANDB  #128
  0011 2702         BEQ   *+4 ;abs = 0015
  0013 c601         LDAB  #1
  0015 7b0000       STAB  bitVar


 And then an array of unsigned ints:

Code:
   24:         bitVar = getbit(array, 23);
  0004 ce0000       LDX   #array
  0007 6e81         STX   1,SP
  0009 c617         LDAB  #23
  000b 6b80         STAB  0,SP
  000d ec02         LDD   2,X
  000f c480         ANDB  #128
  0011 87           CLRA 
  0012 046402       TBNE  D,*+5 ;abs = 0017
  0015 c7           CLRB 
  0016 8f           SKIP2
  0017 c601         LDAB  #1
  0019 7b0000       STAB  bitVar

 
So you can see the array of unsigned chars is slightly more efficient.  To be honest a couple of the operations look a little unnecessary (eg saving X and B at locations relative to SP but then not doing anything with these saved values) but I haven't looked into the optimisation issues..


0 Kudos

1,016 Views
Lundin
Senior Contributor IV
I get more or less the same code. Most important notice after disassembling the function itself, is that the CW optimizer is smart enough to replace / and % operators with shift and local AND. So you don't need to worry about doing this optimization yourself and can therefore keep the C code clean and readable.
0 Kudos

1,016 Views
RubenCG
Contributor III
Hi Colinh,

It's really amazing you from Australia and me in Spain can discuss these problems.
Thanks for your examples, now we can say SOLUTION in capital letters.
When I'll finish my functions I hope we can discuss and try to improve them.

Working like this it's a pleasure!


0 Kudos

1,016 Views
colinh
Contributor I
I stand to be corrected, but Codewarrior does not support C99 bool.

Are your 256 bits completely independent and you want to access them by reference, or do you want to be able to access a bit via an index (eg set/clear etc bit number X)  If the latter then the best way I can think of is to have a 32 byte array and write either functions or macros to access the appropriate byte/bit

Hope this helps
Colin
0 Kudos

1,016 Views
RubenCG
Contributor III
Hi Colin,

I need to set and clear the variables in a independent way, so perphaps the best solution is the 32byte array and the collection of macros to make the bit operations.
I was reading some information and the bitfields are not completly recommended because the NON-Portability, what do you think about it?

Thanks fot your help!
0 Kudos

1,016 Views
Lundin
Senior Contributor IV
Bitfields == problems.

Bitfields are poorly defined in the standard. Alignment, overlapping, behavior of bitfields for other types than int, signed/unsigned behavior, little/big endian, struct padding etc etc.

They are a pain to work with, avoid them like the plauge is my advise. They are also completely redundant, since good compilers (such as Codewarrior) optimize all usage of ISO C bit-wise operators to bit-level assembler instructions.

For your particular example, something like this could be used:

unsigned char data[32];
unsigned char index = something_between_0_and_255;
unsigned char mask;
unsigned char result;

mask = (unsigned char)0x01 << (index % 8);
result = data[index / 8] & mask;

if(result > 1)
{
/* bit flag is 1 */
}
else
{
/* bit flag is 0 */
}


Or if you are keen on optimization, you could rewrite the above as

mask = (unsigned char)0x01 << (index & 7);
result = data[index >> 3] & mask;
0 Kudos

1,016 Views
RubenCG
Contributor III
The problem is space vs. code complexity, I mean, why don't I store the variables like chars(8 bits in memory)? The final code and the operations with variables are easier, aren't they?
Ok!, waste of space, but which of our options are faster? Operation with bits or bytes or (why not) 16bits operations (this MCU is 16bits).

I admit I'm a beginner (in this field of science too :smileyhappy: ), but I really have these kind of doubts.
I really thank your interest.

Rbn

0 Kudos

1,016 Views
JimDon
Senior Contributor III
Well the question is, how many bits are you storing?

4 - not worth it.
32 - probably worth it.
256 - worth it.

The only complexity would be debugging. It would not be as easy to spy on the bits in the array.
0 Kudos

1,016 Views
Lundin
Senior Contributor IV
When optimizing for HCS12, you generally want to save RAM before flash. You have an endless amount of flash but not so much RAM.

Execution speed would be a valid argument against my example, as the compiler will likely not be able to optimize it fully. So if the data has to be read/written to very quickly, yes you could motivate the 256 bytes of data, but that is probably a rare case.
0 Kudos

1,016 Views
RubenCG
Contributor III
Hi all,

I think you're right... the best option is an array of 32 chars or an array of 16 ints, codifiying the variables in separated bits whitin the array. In this case there is no waste of space, moreover the most important operations I have to make are logical... Are logical bitwise operations 16bits-operations or 8bits-operations?
In any case, no waste of space and fast execution speed. Don't you agree?

Thanks one more time
Rbn


0 Kudos

1,016 Views
Lundin
Senior Contributor IV
From an ISO C point of view, you never can tell. C will enforce "integer promotion" of the operands, which might cause them to end up as 16-bit variables, temporary.

This is especially problematic when using the bitwise shift operators, as integer promotion might result in a different result than expected on some machines, since high order bytes might suddenly be added to the integers. You will have to keep this in mind if the code must be portable. The solution is to typecast the operands explicitly to the correct type, in this case 8-bit unsigned char.

For the case of HCS12, I think you will always get 8-bit operations as the compiler will translate & to ANDA or ANDB. If the program is properly written (ie everything is unsigned char), you won't end up with any integer promotions either.

Message Edited by Lundin on 2008-01-22 11:19 AM
0 Kudos

1,016 Views
RubenCG
Contributor III
Ok Lundin, I've read the hcs12 assembler operations and it doesn't exist ANDD, only ANDA ANDB.
Solution= Unsigned char.
I think the question is resolved...for the time being.

0 Kudos

1,016 Views
CompilerGuru
NXP Employee
NXP Employee
Use 8 bit operations, an array of unsigned char.
I don't think the actual logical operations would differ much if just a single bit is tested/set/cleared as long as the bit number and value are known. With computed indexes or values I think the 8 bit unsigned char array is more efficient.

Daniel
0 Kudos

1,016 Views
RubenCG
Contributor III
I trust you all!

Unsigned char array[32] is the final solution of my almost phylosophical dilemma. I hope this time we're spending thinking about the best solution will be profitable :smileyhappy:.

Rbn
0 Kudos

1,016 Views
JimDon
Senior Contributor III

Code:
#define GETBIT(v,bn) v[bn/8] & (1 << (bn%8))#define SETBIT(v,bn) v[bn/8] |= (1 << (bn%8))#define CLRBIT(v,bn) v[bn/8] &= ~(1<<(bn%8))

 

0 Kudos

1,016 Views
Lundin
Senior Contributor IV
I'd advise against function-like macros as the only thing they do is to make the code less readable and harder to debug.

This code is completely equivalent in terms of efficiency:


#pragma INLINE
BOOL getbit (const unsigned char* data, unsigned char n)
{
unsigned char result;

result = data[n / 8] & (0x01 << (n % 8));

return (result > 0);
}

Message Edited by Lundin on 2008-01-22 08:30 AM
0 Kudos