avr-gcc-list
[Top][All Lists]
Advanced

[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



reply via email to

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