Best way to pass 1 bit parameters

15 posts / 0 new
Author
Message

I am wondering whats the best way to pass 1 bit parameters?

I am currently using bool included from stdbool.h, but i feel like there is extra overhead using it because I am checking for if(bool)

I want to do something like

```void functionX(bit onOrOff)
{
char data = 0x80;
data |= onOrOff << 2;
}
```

Have you checked the generated ASM of each option? It is rather difficult to optimize without some knowledge in that direction.

You could certainly make the "bit" value any 8-bit data type ( though uint8_t would be preferable ), and always assign either zero ( 0x00 ) or one ( 0x01 ) to it, then your data update would work... but I'm not really convinced that it will improve your code. Because there is no barrel shifter on the AVR, your "optimized" code will actually have to do two shift operations. Thus, it may not be any more compact than the comparison version anyway.

Only one way to know.

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

As Martin suggested, look at the generated code if you are that worried.

If your example is actually what you want to do, sit down and think.

```input:    0       1
output:   0x80    0x84

data = 0x80;
if (onoroff) data = 0x84;```

Note that your quoted example function does nothing anyway. It is void !

David.

It is interesting to see that the function using a (onoroff << 2) uses less assembly instructions than the If(onoroff) function.

The code was initially compiled with optimization -Os.

When I tried the same code with optimization -O3 functionX compiled identically as before. functionY(), on the other hand, was reduced by only one assembly instruction in principal, but used two paths and thus more assembly instructions overall.

```#include
#include

bool OnOff;

typedef bool bit;

volatile char data1;

int functionX(bit onoroff)
{
char data = ((0x80 | (onoroff << 2)));
return data;
}

int functionY(bit onoroff)
{
char data = 0x80;
if (onoroff) data = 0x84;
return data;
}

int main(void)
{

OnOff = 0;
data1 = functionX(OnOff);
OnOff = 1;
data1 = functionY(OnOff);

while(1);
}
```
```00000090 :
typedef bool bit;

volatile char data1;

int functionX(bit onoroff)
{
90:	88 0f       	add	r24, r24
92:	88 0f       	add	r24, r24
char data = ((0x80 | (onoroff << 2)));
return data;
}
94:	80 68       	ori	r24, 0x80	; 128
96:	90 e0       	ldi	r25, 0x00	; 0
98:	08 95       	ret

0000009a :

int functionY(bit onoroff)
{
char data = 0x80;
if (onoroff) data = 0x84;
9a:	88 23       	and	r24, r24
9c:	11 f0       	breq	.+4      	; 0xa2
9e:	84 e8       	ldi	r24, 0x84	; 132
a0:	01 c0       	rjmp	.+2      	; 0xa4
a2:	80 e8       	ldi	r24, 0x80	; 128
return data;
}
a4:	90 e0       	ldi	r25, 0x00	; 0
a6:	08 95       	ret

000000a8 :

int main(void)
{

OnOff = 0;
data1 = functionX(OnOff);
a8:	80 e8       	ldi	r24, 0x80	; 128
aa:	80 93 01 01 	sts	0x0101, r24
OnOff = 1;
ae:	81 e0       	ldi	r24, 0x01	; 1
b0:	80 93 00 01 	sts	0x0100, r24
data1 = functionY(OnOff);
b4:	84 e8       	ldi	r24, 0x84	; 132
b6:	80 93 01 01 	sts	0x0101, r24
ba:	ff cf       	rjmp	.-2      	; 0xba

000000bc <_exit>:
bc:	f8 94       	cli

000000be <__stop_program>:
be:	ff cf       	rjmp	.-2      	; 0xbe <__stop_program>
```
```0000009a :

int functionY(bit onoroff)
{
char data = 0x80;
if (onoroff) data = 0x84;
9a:	88 23       	and	r24, r24
9c:	21 f0       	breq	.+8      	; 0xa6
9e:	24 e8       	ldi	r18, 0x84	; 132
a0:	30 e0       	ldi	r19, 0x00	; 0
return data;
}
a2:	c9 01       	movw	r24, r18
a4:	08 95       	ret
}

int functionY(bit onoroff)
{
char data = 0x80;
if (onoroff) data = 0x84;
a6:	20 e8       	ldi	r18, 0x80	; 128
a8:	30 e0       	ldi	r19, 0x00	; 0
return data;
}
aa:	c9 01       	movw	r24, r18
ac:	08 95       	ret
```

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Larry,

I am always amazed at some of avr-gcc's intelligence. The if (xpr) sequence often compiles better on most other compilers.

Note that avr-gcc has 'inlined' the result of functionY() in the main() function. i.e. it never bothered to do a call functionY.

So in answer to the OP, his function is fine. The function will be available to external object files (via a call) but will probably never be called in the original module. It is just optimised!

If it is a really important function that is massively used by external modules, declaring as an inline function in a header file would give the best of all worlds.

However I doubt that anything would be noticeable in a real world application. e.g. saving cycles or enabling the use of a 'half-size flash' AVR.

Bootloaders are an exception. It is not uncommon to squeeze into 512 or 1024 bytes.

David.

You can use SREG flags for that. And for returning bit values as well (given example).

```Find_f: \pattern_found_N:
ld data,-X ;load data from SRAM
sub data,pattern ;check if that is the one
cpse XL,start ;ret if all the table was searched
brbc SREG_Z,pattern_found_N ;loop if not
; SREG_Z set, if found. If so, X points to the element```

No RSTDISBL, no fun!

As Brutte says, you can use the SREG flags, but that could be dangerous depending on what your compiler does with them ( in C, in ASM of course you are in control ). A safer C alternative would be to use bits in the GPIO register/s ( if your AVR model has them ). Of course, they are often better suited to storing bit values rather than passing them, but, in the end, there is little difference.

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

Quote:

depending on what your compiler does with them ...

I'm surprised that Bob the Topic Cop hasn't asked for this thread to be moved to the GCC forum. Yes, the topic is generic, but the starting code and all the discussion is GCC.

Also, with the superlative "Best way" in the title wouldn't it be counter-productive to say "use XYZ toolchain instead"?

Is the "best way to pass 1 bit parameters" the same as "My algorithm is already the best way but I want the toolchain to produce optimal code sequences"? Is it allowed to say "Don't do it that way"?

[I hate superlatives in discussions like this. What is the best automobile I should buy?]

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

theusch wrote:
I'm surprised that

He is not a newbie. Almost 30 posts!

theusch wrote:
Also, with the superlative

Would you be satisfied having a topic with performance index? Like "Best way to pass 1 bit variable -Os"?

No RSTDISBL, no fun!

Quote:

Would you be satisfied having a topic with performance index? Like "Best way to pass 1 bit variable -Os"?

Well, it is just that in general it rankles me because there is rarely an overall "best" (or other superlative) regardless of the discussion. Take my automobile question--then you'd find out later I need seats for seven children, after the consensus "best" was a Scion tC.

What is "best" in this case? Smallest? Fastest? Least stack use? Most pleasing source code to the eye of a purist?

In other words: What are the objectives? What alternatives were tried? What are the results, and why did you find one or more lacking?

Certainly all that can't be in the title. But e.g. "Better way to ... ?" and then outline the judging criteria.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

david.prentice wrote:
Larry,

I am always amazed at some of avr-gcc's intelligence. The if (xpr) sequence often compiles better on most other compilers.

Note that avr-gcc has 'inlined' the result of functionY() in the main() function. i.e. it never bothered to do a call functionY...

Hi David,

Good morning, at least here. Well it sure helps to get some sleep, wasn't really noticing much, when I was doing that, in the wee hours of the morning.

I was focused on what the compiler was doing with the code in the functions and had never bothered looking at the code in main(). Actually both functionX and functionY were inlined.

Thank you for the wake-up call.

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Quote:

Actually both functionX and functionY were inlined.

...which allows me to again flog the dead "best" horse...

If this function is indeed only called from one place and is modest sized, then inlining may certainly be "best". In the real world, a critical function (I can only assume since the trouble was taken to post that it is indeed critical) will often (usually?) be called often and may not be a prime candidate for inlining.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Lee,

If you leave the "superlatives" issue out of the equation, then, the OP is posing a fair question. e.g.
"I am wondering how to pass 1 bit parameters?"

I do agree with you that the OP should provide more information as you have stated here:

Quote:

In other words: What are the objectives? What alternatives were tried? What are the results, and why did you find one or more lacking?

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

larryvc wrote:
the OP is posing a fair question. e.g.
"I am wondering how to pass 1 bit parameters?"

But OP clearly knows how to pass a binary type to the function.
John5788 wrote:
I am currently using bool included from stdbool.h

IMHO the posed question is purely how to make it "best" way(whatever "best" means).

I am sure the one Op gave is also "best" with some sort of performance index (like readability), but considering:

John5788 wrote:
but i feel like there is extra overhead
his "best" does not satisfy him - OP thirsts for other "best".

The problem is any method is "best" in some way :)

No RSTDISBL, no fun!

Brutte wrote:

... his "best" does not satisfy him - OP thirsts for other "best".

This RP thirsts for "beer". :wink:

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius