Signed overflow is actually undefined behaviour in C/C++, and the compiler is 
free to do whatever it wants in that case. For gcc, there's a flag to make 
signed integer arithmetic wrap around, though: 

        -fwrapv
        This option instructs the compiler to assume that signed arithmetic 
overflow of
        addition, subtraction and multiplication wraps around using 
twos-complement
        representation. This flag enables some optimizations and disables 
others.

It's one of the "safety switches" I've enabled for our embedded code, because 
it's something many people (including myself until recently) don't know about. 
Especially if you're coming from Java, where signed overflow *is* defined to 
wrap.

John Regehr has a large amount of interesting, if scary, information about 
undefined behaviour in C on his blog, for example 
http://blog.regehr.org/archives/759 and http://blog.regehr.org/archives/761.

HTH,
Michiel

> -----Original Message-----
> From: Rick Kimball [mailto:rick.kimb...@gmail.com]
> Sent: Friday, February 15, 2013 03:19
> To: mspgcc-users@lists.sourceforge.net
> Subject: [Mspgcc-users] msp430-gcc 4.6.3 optimizer killing my code
> 
> I've been working on some C++ template based classes and ran into a
> snag. At first I thought it was related to the C++ templates however
> it turns out when I reduced the code down to a straight 'C'
> implementation I still have the same problem.
> 
> The code below has issues with the int8_t data type. In "test 2" i8
> starts at 126 and incrementing it should make it roll over to a
> negative number but it doesn't. This problem appears when i use -Os (
> which is my normal mode of operation ) and does go away if I back off
> and use -O1. If nothing else it would interesting if others try this
> with their version of the compiler. I'm using the linux version that
> ships with Energia:
> gcc version 4.6.3 20120301 (mspgcc LTS 20120406 unpatched) (MSPGCC
> 20120406 (With patches: sf3540953 sf3559978)) Adding volatile to just
> the int8_t declaration will get rid of the problem.
> 
> If you use msp430-gcc you might try this code and post your results.
> 
> Secondary question, red-hat has been churning away with the msp430-gcc
> code for a while. Is there an ETA for when we might see a new version
> from them?
> 
> Thanks,
> 
> -rick
> 
> code on github: https://gist.github.com/RickKimball/4957969
> 
> /**
>  * signedtest.c - this fails to output int8_t values properly when
> optimized with -Os
>  *
>  * Compiled like this:
>  *
>  * $ msp430-gcc -mmcu=msp430g2553 -DF_CPU=16000000 -Os -Wall \
>  *   -Wno-main -g -mdisable-watchdog -fdata-sections -ffunction-
> sections \
>  *   -Wl,--gc-sections signedtest.c
>  *
>  * $ mspdebug rf2500 "prog a.out"
>  *
>  * compiling with -O1 produces proper output, as does changing the
>  * int8_t to volatile int8_t
>  *
>  */
> 
> #include <msp430.h>
> #include <stdint.h>
> #include <stdlib.h>
> 
> /**
>  * serial output routines
>  */
> void printc(const char c) {
>     while(!(IFG2 & UCA0TXIFG));
>     IFG2 &= ~UCA0TXIFG;
>     UCA0TXBUF = c;
> }
> 
> void prints(const char *s) {
>     while(*s)
>       printc(*s++);
> }
> 
> void printi(int8_t i) {
>   char buff[8];
> 
> #if 1
>   if ( i < 0 ) {
>     printc('-');
>     i=-i;
>   }
>   utoa((i & 0xff),buff,10);
> #else
>   itoa((int8_t)i,buff,10); /* also tried this, also failed */
> #endif
> 
>   prints(buff);
> }
> 
> void printu(uint8_t i) {
>   char buff[8];
> 
>   utoa((i & 0xff),buff,10);
>   prints(buff);
> }
> 
> void println() {
>   printc('\n');
> }
> 
> static const uint32_t brd = (F_CPU + (9600 >> 1)) / 9600; // Bit rate
> divisor
> 
> int main(void) {
>   uint16_t indx;
> 
> #define BAD
> 
> #if defined(GOOD)
>   volatile int8_t i8; // test2 produces valid results
> #elif defined(BAD)
>   int8_t i8; // broken for test2 unless marked volatile or you use -O1
> #endif
>   uint8_t u8;
> 
>   WDTCTL = WDTPW + WDTHOLD;                       // No watchdog reset
>                                                   //
>   DCOCTL = 0;                                     // Run at 16 MHz
>   BCSCTL1 = CALBC1_16MHZ;                         //
>   DCOCTL  = CALDCO_16MHZ;                         //
> 
>   //P1DIR |= BIT0 | BIT4; P1SEL |= BIT4;
> 
>   // GPIO Configuration  ;                        // Set alternate
> function I/O for UART & SPI
>   P1SEL  |= BIT2;                                 // UART P1.2(tx)
>   P1SEL2 |= BIT2;
> 
>   // Serial Config
>   UCA0CTL1 = UCSWRST;                             // Hold USCI in
> reset to allow configuration
>   UCA0CTL0 = 0;                                   // No parity, LSB
> first, 8 bits, one stop bit, UART (async)
>   UCA0BR1 = (brd >> 12) & 0xFF;                   // High byte of whole
> divisor
>   UCA0BR0 = (brd >> 4) & 0xFF;                    // Low byte of whole
> divisor
>   UCA0MCTL = ((brd << 4) & 0xF0) | UCOS16;        // Fractional
> divisor, oversampling mode
>   UCA0CTL1 = UCSSEL_2;                            // Use SMCLK for bit
> rate generator, release reset
> 
> 
>   prints("-test 1- int8_t=125, uint8_t=125 - signed/unsigned boundary
> rollover\n RESULTS: always succeeds\n");
>   i8=125; u8=125;
>   for(indx=0; indx < 5; indx++, i8++, u8++) {
>     printi(i8);
>     prints(", ");
>     printu(u8);
>     println();
>   }
> 
>   prints("-test 2- int8_t=126, uint8_t=126 - signed/unsigned boundary
> rollover\n RESULTS: fails unless volatile\n");
>   i8=126; u8=126;
>   for(indx=0; indx < 4; indx++, i8++, u8++) {
>     printi(i8);
>     prints(", ");
>     printu(u8);
>     println();
>   }
> 
>   prints("-test 3- int8_t=127, uint8_t=127 - signed/unsigned boundary
> rollover\n RESULTS: always ok\n");
>   i8=127; u8=127;
>   for(indx=0; indx < 3; indx++, i8++, u8++) {
>     printi(i8);
>     prints(", ");
>     printu(u8);
>     println();
>   }
> 
>   while(1);
> }
> 
> #if 0
> >>> Bad results when int8_t not volatile
> 
>    -test 1- int8_t=125, uint8_t=125 - signed/unsigned boundary rollover
>     RESULTS: always succeeds
>    125, 125
>    126, 126
>    127, 127
>    -128, 128
>    -127, 129
>    -test 2- int8_t=126, uint8_t=126 - signed/unsigned boundary rollover
>     RESULTS: fails unless volatile
>    126, 126
>    127, 127
>    127, 128 << fail this is the wrong result
>    127, 129 << fail this is the wrong result
>    -test 3- int8_t=127, uint8_t=127 - signed/unsigned boundary rollover
>     RESULTS: always ok
>    127, 127
>    -128, 128
>    -127, 129
> 
> 
> >>> Good results when using volatile int8_t
> 
>   -test 1- int8_t=125, uint8_t=125 - signed/unsigned boundary rollover
>    RESULTS: always succeeds
>   125, 125
>   126, 126
>   127, 127
>   -128, 128
>   -127, 129
>   -test 2- int8_t=126, uint8_t=126 - signed/unsigned boundary rollover
>    RESULTS: fails unless volatile
>   126, 126
>   127, 127
>   -128, 128
>   -127, 129
>   -test 3- int8_t=127, uint8_t=127 - signed/unsigned boundary rollover
>    RESULTS: always ok
>   127, 127
>   -128, 128
>   -127, 129
> 
> 
> #endif
> 
> -----------------------------------------------------------------------
> -------
> Free Next-Gen Firewall Hardware Offer
> Buy your Sophos next-gen firewall before the end March 2013
> and get the hardware for free! Learn more.
> http://p.sf.net/sfu/sophos-d2d-feb
> _______________________________________________
> Mspgcc-users mailing list
> Mspgcc-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/mspgcc-users

------------------------------------------------------------------------------
Free Next-Gen Firewall Hardware Offer
Buy your Sophos next-gen firewall before the end March 2013 
and get the hardware for free! Learn more.
http://p.sf.net/sfu/sophos-d2d-feb
_______________________________________________
Mspgcc-users mailing list
Mspgcc-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mspgcc-users

Reply via email to