Hello maintainers,
I am using msp430-gcc and friends, and I have found some possible bugs. My computer is setup according to: cat /etc/slackware-version Slackware 9.0.0 uname -a Linux gaston 2.4.20 #2 Mon Mar 17 22:02:15 PST 2003 i686 unknown I have included some source-code in this message, which begins at "Listing 1", and also some assembly output which begins at "Listing 2". The following files have been downloaded and installed: msp430-gcc-3.2.2.20030214.tar.bz2 msp430-libc-1.0.20030207.tar.bz2 The commandline used to compile the program in listing 1 was: msp430-gcc -O -S -fpeephole -fpeephole2 -mmcu=msp430x147 bugsdemo.c -o bugsdemo.s The reason that I activated the flag -fpeephole2, was that I was not satisfied with the optimization when using the datatype long int. The flag made the optimizer remove a few redundant instructions, but also, as we will see, a few necessary instructions as well. Now to the details: 1. Sourcecode line 63 and line 74 generates an invalid opcode, "jne &0x0000", as can be seen in lines 44 and 61 in the assembly listing. The workaround was to rewrite the macros DISABLE_TX_INTR and ENABLE_TX_INTR to generate function calls. This is not a very efficient way of coding however. 2. Sourcecode line 137 generates an invalid opcode, "jl &0x001D", as can be seen in line 151 in the assembly listing. The workaround was to rewrite the macro DATA_DIR_OUT to generate a function call. The phenomenom seems to be related the one above. 3. Lines 237 to 244 have an #if/#else/#endif macro. If the first case is compiled, the value of grid[0] will not be correct when the call to pr_txchar( grid[0] ) in line 239 is made. A "mov @r11, r15" between lines 266 and 267 would save the day. The second case of the macro always compile correctly. During the writing of this message I found that the problem disappeared when I omitted the flag -fpeephole2 on the commandline. The commndline now was: msp430-gcc -O -S -fpeephole -mmcu=msp430x147 bugsdemo.c -o bugsdemo.s I do not know if -O automatically sets -fpeephole, is there any way of checking this ? NOTE that the line-numbers above refers to line-numbers in the source, not to line-numbers in this text. The code in the example below is copied from different files in production code. With Best Regards, Tommy Andersson tommy.anders...@geodynamik.com --- Listing 1 begins here --------------------------------------- #include <io.h> #include <signal.h> #define ENABLE_TX_INTR SFR_CMD(bis.b,IE1,UTXIE0) #define DISABLE_TX_INTR SFR_CMD(bic.b,IE1,UTXIE0) #define U0_BUFSIZE 10 #define PRC_PRINTER 2 // Push flags and disable interrupts inline static void pushf_disable( void ) { asm volatile ( "push r2 \n\t" : : ); dint(); asm volatile ( "nop \n\t" : : ); // dint() is delayed 1 clock ! } // Pop the flags, possibly enabling interrupts inline static void popf( void ) { asm volatile ( "pop r2 \n\t" : : ); } typedef unsigned char BYTE; /*** Global control variables: ***/ extern volatile unsigned char curr_pid; /*---------------------------------------------------------------------- Local variables ----------------------------------------------------------------------*/ static volatile BYTE tx0_buffer[U0_BUFSIZE]; static volatile BYTE *tx0_head = tx0_buffer; static volatile BYTE *tx0_tail = tx0_buffer; static volatile BYTE tx0_stop; static volatile BYTE tx0_pending; static volatile BYTE suspended, wait_data_flag; /*---------------------------------------------------------------------- Transmit a character through the serial interface. Returns -1 on a failure, otherwise 0 is returned. ----------------------------------------------------------------------*/ int pr_txchar( char ch ) { BYTE *ptr; retry: DISABLE_TX_INTR; if ( !tx0_pending ) { // NO pending transmissions U0TXBUF = ch; tx0_pending = 1; } else { ptr = tx0_head; if (++ptr >= tx0_buffer+U0_BUFSIZE) ptr = tx0_buffer; if (ptr == tx0_tail) { // Buffer is FULL ! ENABLE_TX_INTR; if ( curr_pid == PRC_PRINTER ) { pushf_disable(); suspended = 1; // This flag MUST BE SET before suspending the proc ! proc_suspend( PRC_PRINTER ); // Suspend printer process popf(); goto retry; } else return -1; // Otherwise, return error. } *tx0_head = ch; // Save next printer character. tx0_head = ptr; } ENABLE_TX_INTR; return 0; } #define CLOCK_LOW SFR_CMD( bic, P4OUT, 1<<0 ) #define CLOCK_HIGH SFR_CMD( bis, P4OUT, 1<<0 ) #define DATA_LOW SFR_CMD( bic, P4OUT, 1<<1 ) #define DATA_HIGH SFR_CMD( bis, P4OUT, 1<<1 ) #define DATA_DIR_IN SFR_CMD( bic, P4DIR, 1<<1 ) #define DATA_DIR_OUT SFR_CMD( bis, P4DIR, 1<<1 ) #define DATA_IN (P4IN&(1<<1)) /*---------------------------------------------------------------------- Read one byte of data from the RTC. The argument 'bytecount' shall be assigned the number of to be read at this 'session', and is used to control the acknowledge bit. ----------------------------------------------------------------------*/ static unsigned char rtc_read( signed char bytecount ) { unsigned char bitcount, data_read; static signed char count; if (bytecount) count = bytecount-1; else --count; DATA_DIR_IN; // DATA goes high (hi-z) for (bitcount = 0; bitcount < 8; bitcount++ ) { CLOCK_HIGH; delay_us( 4 ); data_read <<= 1; if ( DATA_IN ) data_read |= (1<<0); else data_read &= ~(1<<0); CLOCK_LOW; delay_us( 4 ); } DATA_LOW; if ( count > 0 ) DATA_DIR_OUT; // DATA goes low -> Acknowledge */ delay_us( 2 ); CLOCK_HIGH; delay_us( 4 ); CLOCK_LOW; delay_us( 2 ); DATA_DIR_IN; return data_read; } #define LF 10 #define FF 12 #define CR 13 #define ESC 27 #define WIDTH_CHAR 12 #define WIDTH_PRINTROW 400 #define MAXWIDTH_PRINTROW (WIDTH_PRINTROW>WIDTH_LOGO?WIDTH_PRINTROW:WIDTH_LOGO) #define LOGO_HORZ_TAB ((480-300)/2) #define HDR_HORZ_TAB 49 #define DATA_HORZ_TAB 49 #define FOOT_HORZ_TAB 49 #define HEIGHT_TEXTLINE 12 #define HEIGHT_PRINTROW 8 #define HEIGHT_FOOTER (12*HEIGHT_TEXTLINE) #define HEIGHT_A4 ((int)(VERT_DPI*297/25.4)) #define HORZ_GRIDLINE_SPACE 30 #define COARSE_VERT_GRIDLINE_SPACE 67 #define FINE_VERT_GRIDLINE_SPACE 100 #define CURVE_WIDTH 3 #define PC_BEGIN_LOGO {pr_txchar(ESC);pr_txchar('L');\ pr_txchar((WIDTH_LOGO+LOGO_HORZ_TAB)&0xff);\ pr_txchar((WIDTH_LOGO+LOGO_HORZ_TAB)>>8);} #define PC_BEGIN_HDRTAB {pr_txchar(ESC);pr_txchar('L');\ pr_txchar(LOGO_HORZ_TAB&0xff);\ pr_txchar(LOGO_HORZ_TAB>>8);} #define PC_BEGIN_GRAPHIC {pr_txchar(ESC);pr_txchar('L');\ pr_txchar((WIDTH_PRINTROW)&0xff);\ pr_txchar((WIDTH_PRINTROW)>>8);} #define PC_BEGIN_GRA_RMV {pr_txchar(ESC);pr_txchar('L');\ pr_txchar((WIDTH_PRINTROW+5)&0xff);\ pr_txchar((WIDTH_PRINTROW+5)>>8);} #define PC_SET_LINESPACING(x) {pr_txchar(ESC);pr_txchar('A');pr_txchar(x);} #define PC_SET_GRLINESPACING {pr_txchar(ESC);pr_txchar('A');pr_txchar(8);} #define PC_SET_TXTLINESPACING {pr_txchar(ESC);pr_txchar('A');pr_txchar(12);} #define PC_SELECT_CHARSET(x) {pr_txchar(ESC);pr_txchar('R');pr_txchar(x);\ pr_txchar(ESC);pr_txchar('t');pr_txchar(x);} #define PC_CRLF {pr_txchar(CR);pr_txchar(LF);} #define PC_PIXELTAB(x) {int q;pr_txchar(ESC);pr_txchar('L');\ pr_txchar((x)&0xff);pr_txchar((x)>>8);\ for(q=(x);q;q--)pr_txchar(0);} #define PC_FEED pr_txchar(FF) #define PC_SET_CONDENSED pr_txchar(0x0f) #define PC_SET_NORMAL pr_txchar(0x12) static int timeaxis; unsigned char *make_grid_and_frame( int horz_pos, int vert_pos ); unsigned char create_data_curve( int pos ); int print_data( void ) { int printbyte; unsigned char vline8, *grid; PC_SET_GRLINESPACING; // Left margin grid = make_grid_and_frame( 0, timeaxis ); if (grid[1] != 128) { #if (DATA_HORZ_TAB - 4*WIDTH_CHAR -1) < 0 #error "***** Not enough space for numeric scale at left edge *****" #else #if (DATA_HORZ_TAB - 4*WIDTH_CHAR -1) > 0 PC_PIXELTAB(DATA_HORZ_TAB - 4*WIDTH_CHAR -1); #endif #endif pr_txnum_i( (timeaxis+7-grid[1])/3, 3 ); pr_txchar( 's' ); PC_PIXELTAB(1); } else PC_PIXELTAB(DATA_HORZ_TAB); // Data PC_BEGIN_GRA_RMV; for (printbyte = 0; printbyte<WIDTH_PRINTROW; printbyte++ ) { grid = make_grid_and_frame( printbyte, timeaxis ); #ifndef COMPILER_BUG // This does not work due to a compiler bug grid[0] |= create_data_curve( printbyte ); pr_txchar( grid[0] ); #else vline8 = grid[0]; vline8 |= create_data_curve( printbyte ); pr_txchar( vline8 ); #endif } pr_txchar( 0 ); pr_txchar( 0 ); vline8 = create_rmv8( printbyte ); pr_txchar( vline8 ); pr_txchar( vline8 ); pr_txchar( vline8 ); PC_CRLF; timeaxis += 8; return HEIGHT_PRINTROW; } --- Listing 2 begins here --------------------------------------- .file "bugsdemo.c" .arch msp430x147 /* Hardware multiplier registers: */ __MPY=0x130 __MPYS=0x132 __MAC=0x134 __MACS=0x136 __OP2=0x138 __RESLO=0x13a __RESHI=0x13c __SUMEXT=0x13e .data .p2align 1,0 .type tx0_head,@object .size tx0_head,2 tx0_head: .short tx0_buffer .p2align 1,0 .type tx0_tail,@object .size tx0_tail,2 tx0_tail: .short tx0_buffer .text .p2align 1,0 .global pr_txchar .type pr_txchar,@function /*********************** * Function `pr_txchar' ***********************/ pr_txchar: /* prologue: frame size = 0 */ .L__FrameSize_pr_txchar=0x0 .L__FrameOffset_pr_txchar=0x2 push r11 /* prologue end (size=1) */ mov.b r15, r11 .L2: /* #APP */ bic.b #llo(-128), &0x0000 /* #NOAPP */ cmp.b #llo(0), &tx0_pending jne &0x0000 mov.b r11, &0x0077 mov.b #llo(1), &tx0_pending jmp .L4 .L3: mov &tx0_head, r14 add #llo(1), r14 cmp #tx0_buffer+10, r14 jlo .L5 mov #tx0_buffer, r14 .L5: cmp &tx0_tail, r14 jne .L6 /* #APP */ bis.b #llo(-128), &0x0000 /* #NOAPP */ cmp.b #llo(2), &curr_pid jne &0x0000 /* #APP */ push r2 dint nop /* #NOAPP */ mov.b #llo(1), &suspended mov #llo(2), r15 call #proc_suspend /* #APP */ pop r2 /* #NOAPP */ jmp .L2 .L7: mov #llo(-1), r15 jmp .L1 .L6: mov &tx0_head, r15 mov.b r11, @r15 mov r14, &tx0_head .L4: /* #APP */ bis.b #llo(-128), &0x0000 /* #NOAPP */ mov #llo(0), r15 .L1: /* epilogue: frame size=0 */ pop r11 ret /* epilogue end (size=2) */ /* function pr_txchar size 64 (61) */ .Lfe1: .size pr_txchar,.Lfe1-pr_txchar /********* End of function ******/ .local count.0 .comm count.0,1 .p2align 1,0 .type rtc_read,@function /*********************** * Function `rtc_read' ***********************/ rtc_read: /* prologue: frame size = 0 */ .L__FrameSize_rtc_read=0x0 .L__FrameOffset_rtc_read=0x4 push r11 push r10 /* prologue end (size=2) */ cmp.b #llo(0), r15 jeq .L12 add.b #llo(-1), r15 mov.b r15, &count.0 jmp .L13 .L12: add.b #llo(-1), &count.0 .L13: /* #APP */ bic #llo(2), &0x001E /* #NOAPP */ mov.b #llo(0), r10 .L20: /* #APP */ bis #llo(1), &0x001D /* #NOAPP */ mov #llo(4), r15 call #delay_us rla.b r11 bit.b #llo(2),&0x001C jeq .L18 bis.b #llo(1), r11 jmp .L19 .L18: bic.b #llo(1),r11 .L19: /* #APP */ bic #llo(1), &0x001D /* #NOAPP */ mov #llo(4), r15 call #delay_us add.b #llo(1), r10 cmp.b #llo(8), r10 jlo .L20 /* #APP */ bic #llo(2), &0x001D /* #NOAPP */ cmp.b #llo(1), &count.0 jl &0x001D ; &0x001D /* #APP */ bis #llo(2), &0x001E /* #NOAPP */ .L21: mov #llo(2), r15 call #delay_us /* #APP */ bis #llo(1), &0x001D /* #NOAPP */ mov #llo(4), r15 call #delay_us /* #APP */ bic #llo(1), &0x001D /* #NOAPP */ mov #llo(2), r15 call #delay_us /* #APP */ bic #llo(2), &0x001E /* #NOAPP */ mov.b r11, r15 /* epilogue: frame size=0 */ pop r10 pop r11 ret /* epilogue end (size=3) */ /* function rtc_read size 61 (56) */ .Lfe2: .size rtc_read,.Lfe2-rtc_read /********* End of function ******/ .p2align 1,0 .global print_data .type print_data,@function /*********************** * Function `print_data' ***********************/ print_data: /* prologue: frame size = 0 */ .L__FrameSize_print_data=0x0 .L__FrameOffset_print_data=0x4 push r11 push r10 /* prologue end (size=2) */ mov.b #llo(27), r15 call #pr_txchar mov.b #llo(65), r15 call #pr_txchar mov.b #llo(8), r15 call #pr_txchar mov &timeaxis, r14 mov #llo(0), r15 call #make_grid_and_frame cmp.b #llo(-128), 1(r15) jeq .L25 mov.b 1(r15), r15 mov &timeaxis, r14 sub r15, r14 mov r14, r15 add #llo(7), r15 mov r15, r12 mov #llo(3), r10 call #__divmodhi4 mov r12, r15 mov #llo(3), r14 call #pr_txnum_i mov.b #llo(115), r15 call #pr_txchar mov.b #llo(27), r15 call #pr_txchar mov.b #llo(76), r15 call #pr_txchar mov.b #llo(1), r15 call #pr_txchar mov.b #llo(0), r15 call #pr_txchar mov #llo(1), r11 .L30: mov.b #llo(0), r15 call #pr_txchar add #llo(-1), r11 jeq .L31 jmp .L30 .L25: mov.b #llo(27), r15 call #pr_txchar mov.b #llo(76), r15 call #pr_txchar mov.b #llo(49), r15 call #pr_txchar mov.b #llo(0), r15 call #pr_txchar mov #llo(49), r11 .L36: mov.b #llo(0), r15 call #pr_txchar add #llo(-1), r11 jne .L36 .L31: mov.b #llo(27), r15 call #pr_txchar mov.b #llo(76), r15 call #pr_txchar mov.b #llo(-107), r15 call #pr_txchar mov.b #llo(1), r15 call #pr_txchar mov #llo(0), r10 .L41: mov &timeaxis, r14 mov r10, r15 call #make_grid_and_frame mov r15, r11 mov r10, r15 call #create_data_curve bis.b r15, @r11 call #pr_txchar add #llo(1), r10 cmp #llo(400), r10 jl .L41 ; .L41 mov.b #llo(0), r15 call #pr_txchar mov.b #llo(0), r15 call #pr_txchar mov r10, r15 call #create_rmv8 mov r15, r11 call #pr_txchar mov.b r11, r15 call #pr_txchar mov.b r11, r15 call #pr_txchar mov.b #llo(13), r15 call #pr_txchar mov.b #llo(10), r15 call #pr_txchar add #llo(8), &timeaxis mov #llo(8), r15 /* epilogue: frame size=0 */ pop r10 pop r11 ret /* epilogue end (size=3) */ /* function print_data size 153 (148) */ .Lfe3: .size print_data,.Lfe3-print_data /********* End of function ******/ .local tx0_buffer .comm tx0_buffer,10,2 .local tx0_stop .comm tx0_stop,1 .local tx0_pending .comm tx0_pending,1 .local suspended .comm suspended,1 .local wait_data_flag .comm wait_data_flag,1 .local timeaxis .comm timeaxis,2,2 /********************************************************************* * File bugsdemo.c: code size: 278 words (0x116) * incl. words in prologues: 5, epilogues: 8 *********************************************************************/ --- End Of File ---------------------------------------