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  ---------------------------------------


Reply via email to