optimization of while(!(PINA & 0x40));

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

Perhaps I have an option wrong. Its been quite a while since I've done any AVR stuff, so its entirely possible... but...

while(!(PINA & 0x80));

produces:

sbis	0x19, 7
rjmp	.-4

as it should, but

while(!(PINA & 0x40));

produces:

ldi	r18, 0x01
ldi	r19, 0x00
in	r24, 0x19
eor	r25, r25
ldi	r20, 0x06
lsr	r25
ror	r24
dec	r20
brne	.-8 
eor	r24, r18
eor	r25, r19
sbrc	r24, 0
rjmp	.-22

Some kind of promotion problem?, or perhaps the code just didnt get optimized?

All bits except 7 cause the problem. I have tried several different registers. Im using a clean install of WinAVR 20050214 -Os. For now Im just ignoring the issue, and if necessary I can switch to assembly for the loop.

Anyone know what Im doing wrong?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

C promotes all constants to an int, or somthing like that. Try typcasting:

while(!(PINA & (unsigned char)0x80));

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the response..

note that I said that the value 0x80 optimizes correctly, and the value 0x40 does not.

But just to be on the safe side, I tried your suggestion, and recieved the same results: 0x80 = ok, 0x40 (and any other bit) = poor code...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can compile corectly! What is your context?
Andras

int main( void )
	{
		while(!(PINB & 0x80));
		while(!(PINB & 0x40));
		while(!(PINB & 0x20));
		while(!(PINB & 0x02));
		while(!(PINB & 0x01));


000003d8 
: 3d8: cf ef ldi r28, 0xFF ; 255 3da: d2 e0 ldi r29, 0x02 ; 2 3dc: de bf out 0x3e, r29 ; 62 3de: cd bf out 0x3d, r28 ; 61 3e0: 1f 9b sbis 0x03, 7 ; 3 3e2: fe cf rjmp .-4 ; 0x3e0 3e4: 1e 9b sbis 0x03, 6 ; 3 3e6: fe cf rjmp .-4 ; 0x3e4 3e8: 1d 9b sbis 0x03, 5 ; 3 3ea: fe cf rjmp .-4 ; 0x3e8 3ec: 19 9b sbis 0x03, 1 ; 3 3ee: fe cf rjmp .-4 ; 0x3ec 3f0: 18 9b sbis 0x03, 0 ; 3 3f2: fe cf rjmp .-4 ; 0x3f0
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for the slow response. Just found a key to the puzzle a few seconds ago. It appears to be the c++ compiler only.

Here's how to reproduce it. First make tst.c:

#include 
void tst()
{
  while(!(PINB & 0x80));
  while(!(PINB & 0x40));
}

not much to it.

This line produces the problem:
avr-g++ -c -Os -mmcu=atmega128 -o tst.o tst.c
This line works correctly:
avr-gcc -c -Os -mmcu=atmega128 -o tst.o tst.c

I use this to check if the assembly:
avr-objdump --disassemble tst.o

Its strange that it works correctly for 0x80, but incorrectly otherwise...