Tool/software: TI C/C++ Compiler
/* TI MSP430 compiler bug discovered by Greg Fundyler on August 15, 2018.
*
* Tested primarily with -O2 --opt-for-speed=5
* Speed vs size setting appears not to matter.
* Bug manifests with -O2 and higher.
*
* Each for-loop executes only once, but this structure is required to
* demonstrate the bug.
*
* Tested with ti-cgt-msp430_16.9.1.LTS and ti-cgt-msp430_18.1.3.LTS
*
* Compiler invocation:
* "C:/apps/ti/ccsv7/tools/compiler/ti-cgt-msp430_18.1.3.LTS/bin/cl430" -vmspx -O2 --opt_for_speed=5 --include_path="C:/apps/ti/ccsv7/ccs_base/msp430/include" --include_path="C:/apps/ti/ccsv7/tools/compiler/ti-cgt-msp430_18.1.3.LTS/include" --advice:power="all" --define=__MSP430FR5739__ --define=_MPU_ENABLE -g --printf_support=minimal --diag_warning=225 --diag_wrap=off --display_error_number --abi=eabi --silicon_errata=CPU21 --silicon_errata=CPU22 --silicon_errata=CPU40 -k --asm_listing --cross_reference --output_all_syms --gen_acp_raw --preproc_with_compile --preproc_dependency="main.d" "../main.c"
*
* Linker invocation:
* "C:/apps/ti/ccsv7/tools/compiler/ti-cgt-msp430_18.1.3.LTS/bin/cl430" -vmspx -O2 --opt_for_speed=5 --advice:power="all" --define=__MSP430FR5739__ --define=_MPU_ENABLE -g --printf_support=minimal --diag_warning=225 --diag_wrap=off --display_error_number --abi=eabi --silicon_errata=CPU21 --silicon_errata=CPU22 --silicon_errata=CPU40 -k --asm_listing --cross_reference --output_all_syms --gen_acp_raw -z -m"bug.map" --heap_size=160 --stack_size=160 --cinit_hold_wdt=on -i"C:/apps/ti/ccsv7/ccs_base/msp430/include" -i"C:/apps/ti/ccsv7/ccs_base/msp430/lib/5xx_6xx_FRxx" -i"C:/apps/ti/ccsv7/tools/compiler/ti-cgt-msp430_18.1.3.LTS/lib" -i"C:/apps/ti/ccsv7/tools/compiler/ti-cgt-msp430_18.1.3.LTS/include" --reread_libs --define=_MPU_ENABLE --diag_wrap=off --display_error_number --warn_sections --xml_link_info="linkInfo.xml" --rom_model -o "bug.out" "./main.obj" "C:/apps/ti/ccsv7/ccs_base/msp430/include/lnk_msp430fr5739.cmd" -llibmath.a -llibc.a
*/
#include <msp430fr5739.h>
#include <stdint.h>
uint32_t y;
int32_t signed_y;
int16_t z;
int32_t big_z;
volatile int32_t outa, outb, outc, outd; // optimized out if missing 'volatile' at -O3 and higher
// volatile int16_t outa, outb, outc, outd; // changes behavior slightly
static inline int16_t foo(int32_t x) {
return x >> 16;
}
void test1(void) {
for(y = 33345; y < 34000; y += 1000) {
signed_y = (int16_t)y;
outa = (5368UL * (uint16_t)y) >> 16;
outb = foo(signed_y); // outb = 0 (incorrect: should be -1)
outc = signed_y >> 16; // outc = -1 (correct)
}
}
void test2(void) {
for(y = 33345; y < 34000; y += 1000) {
signed_y = (int16_t)y;
outa = (5368UL * y) >> 16;
outb = foo(signed_y); // outb = 0 (incorrect: should be -1)
outc = signed_y >> 16; // outc = 0 (incorrect: should be -1)
}
}
void test3(void) {
for(y = 33345; y < 34000; y += 1000) {
signed_y = (int16_t)y;
outb = foo(signed_y); // outb = 0 (incorrect: should be -1)
outc = signed_y >> 16; // outc = 0 (incorrect: should be -1)
}
}
void test4(void) {
for(y = 33345; y < 34000; y += 1000) {
signed_y = (int16_t)y;
outb = foo(signed_y); // outb = -1 (correct)
outc = signed_y >> 16; // outc = 65535 (incorrect: should be -1)
outd = signed_y >> 17; // outd = -1 (correct)
}
}
void test5(void) {
for(y = 33345; y < 34000; y += 1000) {
signed_y = (int16_t)y;
outc = signed_y >> 16; // outc = -1 (correct)
outb = foo(signed_y); // outb = -1 (correct)
}
}
void test6(void) {
for(z = -20000; z < -19500; z += 1000) {
big_z = z;
outb = foo(big_z); // outb = -1 (correct)
outc = big_z >> 16; // outc = 65535 @ -O2 optimization, -1 @ all other optimizations
}
}
void test7(void) {
for(z = -20000; z < -19500; z += 1000) {
big_z = z;
outc = big_z >> 16; // outc = -1 (correct)
outb = foo(big_z); // outb = -1 (correct)
}
}
void main(void) {
WDTCTL = WDTPW + WDTHOLD; // stop WDT
test1();
test2();
test3();
test4();
test5();
test6();
test7();
while(1) {}
}