avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-libc-dev] RFC: avr/bits.h


From: E. Weddington
Subject: Re: [avr-libc-dev] RFC: avr/bits.h
Date: Tue, 01 Mar 2005 10:00:13 -0700
User-agent: Mozilla Thunderbird 0.7.3 (Windows/20040803)

Bob Paddock wrote:

On Tue, 01 Mar 2005 01:15:47 -0800, Erik Walthinsen <address@hidden> wrote:

As per E. Weddinton's suggestion a month ago, I'd like to start the
process of getting avr/bits.h included in avr-libc.  A first pass at the
file and its documentation are attached.



I wanted to do a test case for using bit_XXX on longs to see if it does the right thing, and wrote the following test case. However the results to me
are puzzling, they look down right broken.  What is going on here?:

Yes, they are broken.

I left out something in the RFC, mainly because it would have been obvious to Jörg but not perhaps to others.

The file requires 2 different bit name to bit mask convertor macros. This is because numeric constants are automatically typed as int which is 16 bits. So that means that this:
#define bit(x)   (1 << (x))
will be an int because the 1 is automatically typed as int.

This obviously fails on 32 bit values. So, a second macro needs to be created. I don't care what name it's called, but I'll use this for the discussion:
#include <stdint.h>
#define bit_32(x)  ((uint32_t)1 << (x))

Yes, I'm aware that one can use 1UL, but with the -mint8 switch, the size of a long changes. Use of the stdint.h header with the uint32_t will guarantee that this produces a 32-bit value.

Now the real question is whether we can just get away with having one version of this and typecasts will fix everything up. For example, what if we had this:
==================================================
#include <stdint.h>

#define bit(x)  ((uint32_t)1 << (x))

#define bit_set_8(v, m)      ((uint8_t)(v) |= (uint8_t)(m))
#define bit_clear_8(v, m)   ((uint8_t)(v) &= (uint8_t)~(m))
#define bit_toggle_8(v, m)  ((uint8_t)(v) ^= (uint8_t)(m))
#define bit_read_8(v, m)        ((uint8_t)(v) & (uint8_t)(m))

//.....

#include <avr/io.h>
void foo(void)
{
   bit_set_8(PORTD, bit(3));
   return;
}
==================================================

Would the generated assembly for function foo be the most efficient? Would the compiler do the Right Thing and size all of the operands correctly?

If yes, then make sure that it works for all bit_*_<size> macros such as:
bit_set_8(v,m)
bit_set_16(v,m)
bit_set_32(v,m)

If that all works, then perhaps we only need one implementation of the bit() macro.

Eric





reply via email to

[Prev in Thread] Current Thread [Next in Thread]