[Top][All Lists]
[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?
- [avr-gcc-list] Tiny88 C++ code optimized out of existence?,
Bob Paddock <=