1 /** bug2729218.c 2 */ 3 4 #include <testfwk.h> 5 6 /* 7 8 sdcc appears to compile the following file incorrectly. I have attached 9 the C source code, and the generated assembly code, with some comments 10 that explain the bug. 11 12 The basic problem is that a memory location is post-incremented, but 13 the register variable that shadows that memory location is NOT 14 increment, and this incorrect value is used in later calculations. 15 16 I compiled it with these options: 17 18 sdcc -mmcs51 --model-small --std-sdcc99 --code-loc 0xf000 -c bug.c 19 20 Here is the "sdcc -v" output: 21 22 SDCC : mcs51/gbz80/z80/avr/ds390/pic16/pic14/TININative/xa51/ds400/hc08 2.9.1 #5422 (Apr 3 2009) (UNIX) 23 24 */ 25 26 struct iglobals 27 { 28 unsigned char rx_byte; 29 unsigned char input_cnt; 30 }; 31 32 #if !defined(__SDCC_gbz80) && !defined(__SDCC_pdk14) 33 #define ig (*(__idata struct iglobals *) 0xf0) 34 #else 35 struct iglobals ig; 36 #endif 37 38 unsigned char count; 39 40 unsigned char do_command(void)41do_command(void) 42 { 43 // In the following statement, the post-increment is saved in 44 // memory, but not in the value stored in the r7 register 45 count = ig.input_cnt++; 46 47 // In the following statement, the value of "input_cnt" stored in 48 // the r7 register is used, but it is wrong (never incremented). 49 return ig.input_cnt; 50 } 51 testBug(void)52void testBug(void) 53 { 54 #ifdef __SDCC 55 ig.rx_byte = 0; 56 ig.input_cnt = 1; 57 58 ASSERT (do_command() == 2); 59 ASSERT (ig.input_cnt == 2); 60 ASSERT (count == 1); 61 #endif 62 } 63