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

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

[avr-gcc-list] Tiny88 C++ code optimized out of existence?


From: Bob Paddock
Subject: [avr-gcc-list] Tiny88 C++ code optimized out of existence?
Date: Wed, 14 Jan 2009 12:06:01 -0500

I'm trying to bring up a new board that uses a Tiny88.
I'm compiling the code as C++ code, using WinAVR 20081205/4.3.2,
using -Os.  Makefile was produced by MFile.

This is the test program, main.cpp:

=============
#if defined(__cplusplus) && __cplusplus
 extern "C" {
#endif

#include <avr/io.h>
#include <inttypes.h>

#if defined(__cplusplus) && __cplusplus
 }
#endif

#define BUTTON_BIT               (2)
#define BUTTON                   _BV(BUTTON_BIT)

#define LED0H_BIT                (6)
#define LED0H                     _BV(LED0H_BIT)

#define LED2H_BIT                (5)
#define LED2H                    _BV(LED2H_BIT)

#define VpumpH_BIT               (2)
#define VpumpH                   _BV(VpumpH_BIT)

#define VpumpL_BIT                 (1)
#define VpumpL                   _BV(VpumpL_BIT)

/* 
***************************************************************************************
*/
int main( void )
{
  SMCR = 0;             /* Sleep mode disabled */

  GPIOR2 = MCUSR;       /* Save the cause of reset in General Purpose
Register Two */
  MCUSR = 0;            /* Clear the flags for the next pass */

  WDTCSR = (_BV(WDCE)|_BV(WDE)); /* Disable Watchdog, which can only
be done if WDRF is clear in MCUSR */
  WDTCSR = 0;                    /* Must be done within four
instructions of above WDTCSR */

  PORTB = VpumpH;       /* Deassert all outputs */
  DDRB  = 0xFF;

  PORTA = 0x00;
  DDRA  = 0xFF;

  PORTC = 0x00;
  DDRC  = 0xFF;

  PORTD = BUTTON;       /* Pull Up on BUTTON, all others output low */
  DDRD  = (uint8_t) ~BUTTON;

  for(;;)
    {
      uint8_t byte_u8 = LED2H; // Start LED

      // Charge pump off:
      byte_u8 |= VpumpH;
      byte_u8 &= (uint8_t) ~VpumpL;

      PORTB = byte_u8;

      byte_u8 <<= 1;  // Key to failing seems to be this line
                      // without this the produced code would be
                      // what the compiler is really generating

      //  When All LEDs have been lit, start over:
      if( 0 == (byte_u8 & (uint8_t) ~VpumpH))
        {
          byte_u8 = (uint8_t) LED0H;
        }
    }
}
=============

which generates this very broken code:

=============
/* 
***************************************************************************************
*/
int main( void )
{
  SMCR = 0;              /* Sleep mode disabled */
  60:   13 be           out     0x33, r1        ; 51

  GPIOR2 = MCUSR;       /* Save the cause of reset in General Purpose
Register Two */
  62:   84 b7           in      r24, 0x34       ; 52
  64:   8b bd           out     0x2b, r24       ; 43
  MCUSR = 0;            /* Clear the flags for the next pass */
  66:   14 be           out     0x34, r1        ; 52

  WDTCSR = (_BV(WDCE)|_BV(WDE)); /* Disable Watchdog, which can only
be done if WDRF is clear in MCUSR */
  68:   88 e1           ldi     r24, 0x18       ; 24
  6a:   80 93 60 00     sts     0x0060, r24
  WDTCSR = 0;                    /* Must be done within four
instructions of above WDTCSR */
  6e:   10 92 60 00     sts     0x0060, r1

  PORTB = VpumpH;       /* Deassert all outputs */
  72:   94 e0           ldi     r25, 0x04       ; 4
  74:   95 b9           out     0x05, r25       ; 5
  DDRB  = 0xFF;
  76:   8f ef           ldi     r24, 0xFF       ; 255
  78:   84 b9           out     0x04, r24       ; 4

  PORTA = 0x00;
  7a:   1e b8           out     0x0e, r1        ; 14
  DDRA  = 0xFF;
  7c:   8d b9           out     0x0d, r24       ; 13

  PORTC = 0x00;
  7e:   18 b8           out     0x08, r1        ; 8
  DDRC  = 0xFF;
  80:   87 b9           out     0x07, r24       ; 7

  PORTD = BUTTON;       /* Pull Up on BUTTON, all others output low */
  82:   9b b9           out     0x0b, r25       ; 11
  DDRD  = (uint8_t) ~BUTTON;
  84:   8b ef           ldi     r24, 0xFB       ; 251
  86:   8a b9           out     0x0a, r24       ; 10
      uint8_t byte_u8 = LED2H;

      byte_u8 |= VpumpH;
      byte_u8 &= (uint8_t) ~VpumpL;

      PORTB = byte_u8;
  88:   84 e2           ldi     r24, 0x24       ; 36
  8a:   85 b9           out     0x05, r24       ; 5
  8c:   fe cf           rjmp    .-4             ; 0x8a <main+0x2a>

0000008e <_exit>:
  8e:   f8 94           cli

00000090 <__stop_program>:
  90:   ff cf           rjmp    .-2             ; 0x90 <__stop_program>
=============

It appears everything involving modifying/testing byte_u8 in the for(;;)
has been optimized out of existence.  Why?  This is not an interrupt,
so the usual FAQ issue of volatile doesn't seem like it applies here.

If you change this:

  for(;;)
    {
      uint8_t byte_u8 = LED2H;
      ...

to this:

  uint8_t byte_u8 = LED2H;
  for(;;)
    {
     ...

the compiler at least tells you that byte_u8 is assigned but not used.

Something here is failing the "least surprise" test.  What is it
I'm not understanding?




reply via email to

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