[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[avr-gcc-list] [bug] cbi optimization error for 8-bit AVRs
From: |
Szikra István |
Subject: |
[avr-gcc-list] [bug] cbi optimization error for 8-bit AVRs |
Date: |
Sat, 08 Nov 2014 01:32:52 +0100 |
User-agent: |
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.2.0 |
Hi everyone!
My problem in sort: I’m getting
in r24, 0x18
ldi r25, 0x00
andi r24, 0xEF
out 0x18, r24
instead of
cbi 0x18, 4
.
I’m trying to write efficient modern C/C++ code for multiple platforms
including AVR 8 bit controllers.
Unfortunately GCC support for AVR (among other things) is not always
flawless. And it changes from versions to version (and not always for
the better).
Since I’m a long time AVR developer I have a lot of compiler versions
installed (WinAVR 2006-2010, and Atmel Studio 6.2 with GCC 4.8.1), but I
could test my code with only one (the latest).
I run into some trouble with clearing port bits not translating from C
into cbi in assembler. It is caused by my bits template, but I do not
know why. It seems to me like a bug in GCC. Maybe someone here can shed
some light on the reason, or suggest a fix.
Here is the code:
#include <avr/io.h>
//#include <bits.hpp>
template<typename T>
constexpr unsigned int bits(T idx1)
{
return (1<<idx1);
}
template <typename T, typename... Rest>
constexpr unsigned int bits(T idx1, Rest... r)
{
return (1<<idx1) | bits(r...);
}
int main(void)
{
DDRB = 0x0f;
for(;;) {
PORTB |= bits(4);
PORTB &=~bits(4);
PORTB |= (1<<4);
PORTB &=~(1<<4);
}
}
It’s compiled with avr-gcc (AVR_8_bit_GNU_Toolchain_3.4.4_1229) 4.8.1
(Atmel Studio 6.2):
avr-gcc -c -mmcu=attiny13 -I. -x c++ -gdwarf-2 -DF_CPU=9600000UL -Os
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
-fno-exceptions -Wall -Wundef -fno-strict-aliasing -Winline
-fno-inline-small-functions -fno-default-inline -save-temps
-Wa,-adhlns=./test.lst -ID:/Lib/ -std=gnu++11 -MMD -MP -MF .dep/test.o.d
test.cpp -o test.o
My older compiler versions do not support -std=gnu++11. By the way,
does anyone know when Atmel is coming out with GCC 4.8.3 version for AVR?
----
Here is the preproc output:
template<typename T>
constexpr unsigned int bits(T idx1)
{
return (1<<idx1);
}
template <typename T, typename... Rest>
constexpr unsigned int bits(T idx1, Rest... r)
{
return (1<<idx1) | bits(r...);
}
int main(void)
{
(*(volatile uint8_t *)((0x17) + 0x20)) = 0x0f;
for(;;) {
(*(volatile uint8_t *)((0x18) + 0x20)) |= bits(4);
(*(volatile uint8_t *)((0x18) + 0x20)) &=~bits(4);
(*(volatile uint8_t *)((0x18) + 0x20)) |= (1<<4);
(*(volatile uint8_t *)((0x18) + 0x20)) &=~(1<<4);
}
}
----
Assembly list file (relevant part only):
19:test.cpp **** for(;;) {
20:test.cpp **** PORTB |= bits(4);
26 .loc 1 20 0 discriminator 1
27 0004 C49A sbi 0x18,4
28 .LVL1:
21:test.cpp **** PORTB &=~bits(4);
29 .loc 1 21 0 discriminator 1
30 0006 88B3 in r24,0x18
31 0008 90E0 ldi r25,0
32 000a 8F7E andi r24,239
33 000c 88BB out 0x18,r24
22:test.cpp ****
23:test.cpp **** PORTB |= (1<<4);
34 .loc 1 23 0 discriminator 1
35 000e C49A sbi 0x18,4
24:test.cpp **** PORTB &=~(1<<4);
36 .loc 1 24 0 discriminator 1
37 0010 C498 cbi 0x18,4
and the objdump (in case someone likes it better, like me)
for(;;) {
PORTB |= bits(4);
26: c4 9a sbi 0x18, 4 ; 24
PORTB &=~bits(4);
28: 88 b3 in r24, 0x18 ; 24
2a: 90 e0 ldi r25, 0x00 ; 0 <---WTF?
2c: 8f 7e andi r24, 0xEF ; 239
2e: 88 bb out 0x18, r24 ; 24
PORTB |= (1<<4);
30: c4 9a sbi 0x18, 4 ; 24
PORTB &=~(1<<4);
32: c4 98 cbi 0x18, 4 ; 24
34: f8 cf rjmp .-16 ; 0x26 <main+0x4>
Regards,
Steven
- [avr-gcc-list] [bug] cbi optimization error for 8-bit AVRs,
Szikra István <=