From: DSP Hotline

Subject: Fixed Pt. Processor (320C1x/2x/5x) Code Generation Tools Bug List

-------------------------------------------------------------------------------
* RELEASE 6.40 BUGLIST                                                        *
* Update - 08/20/93                                                           *
*                                                                             *
* This file contains a list of bugs in the release 6.40 of the 320C1x/2x/5x   *
* code generation tools.                                                      *
*                                                                             *
* All bugs will be fixed in the next production release unless otherwise     *
* indicated. There will sometimes be references to internal versions in       *
* this list. For that reason you must always refer to the release status      *
* information (published every two weeks) to verify the availability of a     *
* specific revision.                                                          *
*                                                                             *
-------------------------------------------------------------------------------


				Part 1

 COMPILER
-------------------------------------------------------------------------------

4847     V6.40  will fix next release
  The compiler may fail to generate code for a shift operation, when
the shift is applied to an expression that was calculated in 
an immediately preceeding statement and the expression still
resides in the accumulator.  

Note: This same problem may occur in cases where the compiler
      itself generates a shift operation , for example if
      you have the expression  m * 4, the compiler may
      generate  m << 2.

i.e.


    channel = 8 * module + ch;
    b = MCHN + (channel << 3) + 1;   /* This line compiles incorrectly */
                         /* since value of channel is already */
                         /* in the accumulator as a result of */
                         /* the previous statement            */


Workaround:   
 
      1. Use the -ma option. (Although this will alleviate the
      problem it may cause inefficient code generation,
      since this will turn off all register tracking. )

      2. Intersperse another instruction between the two offending
      instructions that uses the accumulator.

      3. Or if possible simply reuse the expression from the
      first statement in the calculation carried out in the
      second statement

      i.e.

         b = MCHN + ((8 * module + ch) << 3) + 1


4923     V6.40  will fix next release
  The compiler may generate incorrect code for an unsigned long
expression of the form " *mem & k " under the following
circumstances:


    1) mem is a pointer to an unsigned long

    2) k is a constant value whose lower half == 0

    3) the expression   *mem & k   is not directly
       assigned to anything.


    Workarounds for the problem include:

    1) Use a temporary to store value of K

    i.e.


       k = 0x80000000;

       if ( *mem & k) { ...


    2) Store the value pointed to by "mem" into a temporary
       abd use this in the compare

       i.e.

       unsigned long tmp;

       tmp = *mem;

       if ( tmp & 0x80000000) { ...


4994     V6.40  will fix next release
  When compiling C source that contains a declaration of the form:

      const unsigned long x=0;

An error will be generated at assemble time:

     In assembly phase
      .EVAL $,X
        : ABSOLUTE VALUE REQUIRED
    
This implies that the long cannot be page aligned.


4997     V6.40  will fix next release
  The compiler errs in generating an illegal shift for an LAC instruction when
evaluating the offest for an indexed array, when the index has been declared
as a "long".  

i.e.

long temp;

for(temp=1;temp<=no_pulses;temp++)
      if(detect[temp].tys_diff<=MAX_VAR_TSYS &&
      detect[temp].tdia_diff<=MAX_VAR_TDIA &&
      detect[temp].pa_diff<=MAX_VAR_PA)
      { no_good_pulses++;
      }


Workaround: Declare the index to be "int" instead.


5032     V6.40  will fix next release
  Under some circumstances the compiler may inadvertently generate an
SPLK instruction with TREG1 as argument but fails to set DP to zero 
before the instruction, causing incorrect shift value to be loaded.

e.g.

int i;
int j;
main() {

   i = 0x7ff0;
   j = 0x3ff0;
   j = (int) (   ( ( (long) (i) * (j) + 0x4000) >> 15) );
}


5037     V6.40  will fix next release
  In some instances when a loop variable is used as both an index for an
arrayed data item and the also appears on the right-hand side of the
assignment where it is used as an index, the compiler/optimizer may generate
incorrect code.

e.g.

void test(void)
{
   int i;
   for (i=0; i<10; i++)
   {
      x[i] = i+1;
   }
}


Workaround: 1) Compile without optimization
         2) Rewrite the code so that the loop varaible does not
            appear as both index on the left-hand side of the 
            assignment and as part of the expression on the
            right-hand side ofthe assignment.

            i.e.

            int i,j;

            for(i=0,j=0; i<10; i++)
            {
           x[i] = ++j;
               }


5054     V6.40  will fix next release
  The compiler errs when generating code for the construct *p++, when
the pointer, p, is of type  pointer-to-long or pointer-to-struct.

Note: In some cases the optimizer may change an access to an arrayed
structure or long into the form *p++. So you need to be careful about
optimizing any code that contains an indexed structure or long array.


struct fred {
   int a,b,c,d;
} george[10], *barney, wilma;

barney = &george[2];

main()
{
     *barney++ =  wilma;      /* Error will occur here with/without 
                        optimization  */
     for (i=1; i<10 ; i++)
        george[i] = george[0]; /* Error will occur here only with
                         optimization  */
}


5059     V6.40  will fix next release
  The compiler errs when generating code for an if statement contained in
a for loop when 

    1.  the compiler/optimizer uses a RPTB to implement
        the  for loop 
     
    2.  and the if statement is the last statement in the loop


Under these circumstances the compiler/optimizer may generate a branch
for the case where the if contdition fails to a label that is outside
of the RPTB/loop body.

e.g.


for (n =0; n< length ; n++)
{

   *to++ = *from++;
   if (from == (char *)ram + limit)
   {
       from = (char *)ram + start;
   }
}

label:  /* When if condition is false - code branches here */


Workaround: compile without optimization


5074     V6.40  will fix next release
  The compiler generates incorrect code whenever there is an expression of
the form ptr->member_of_structure and the offset of the structure member 
is > 0.

typedef struct _stag{
struct {
      int a,b,c,d;
       }y;
} STAG;

STAG x[3];
STAG *ptr;

void func1(int i)
{
  x[i].y.b = 0;
  x[i].y.d = 0;     /* This code will generate the error only when
  x[i].y.c = 0;        Optimization is turned on                  */
  x[i].y.a = 0;
}


5114     V6.40  will fix next release
  When handling the 32-bit expression

     mem = mem <bitwise-op> <expr>;

where

     mem          - 32-bit memory operand, same one in each instance
     <bitwise-op> - Bitwise operation, &, |, or ^
     <expr>       - a 32-bit expression that ends up in the accumulator

the compiler errs by using the upper half of 'mem' as a temporary while
evaluating the expression.  


i.e.

      unsigned long x,y;

      x = x & (~y);


Workaround: rewrite the expression in the form

            mem <bitwise->op>= <expr>;
      
            i.e.

            x &= ~y;


5128     V6.40  will fix next release
  Note: This is an optimization problem only!
Under some rare circumstances, when optimization is used, the compiler may 
fail to set AR1 as the currently selected AR register (ARP=1) prior to
a function call.  Since AR1 is used to set the stack and frame pointers,
this leads to erroneous results when the function is executed.

int rd_msg_buf[4];

void pol123(void)
{
   for(;;) {

     wait(2000);     <====== AR1 is not selected before this call.
     rd_msg_buf[3] = rd_msg_buf[2];
     if (rd_msg_buf[1] != 0) {
       switch(rd_msg_buf[2]) {
       case 5:
       rdcmd_decode();
       break;
       case 12:
       vwcmd_decode();
       break;
       }
     }
   }
}


5155     V6.40  will fix next release
  Note: This is a problem that affects Debugger & Simulator only!!
   The compiler fails to generate the correct line number information to
be used for debugging purposes when compiling a function whose contents
consists solely of code generated by C "asm( )" statements.
This has no basic effect on the operation of the code - it can cause
problems with execution in the debugger and simulator since both of
these tools require this information for proper execution.

i.e.
    func(){
      asm(" NOP");
      asm(" NOP");
      asm(" NOP");
      asm(" NOP");
      asm(" NOP");
    }


5194     V6.40  will fix next release
  On rare occasions when compiling with optimization and the code
contains a for loop of the form:

     for ( i .... ++i)
     {

        x[i] = ....
        ... i+1 ...
     }

the optimizer gets confused and may not generate code to increment 
the temporary it assigns for the indexed array "x".  Therefore the 
address x[i] does not get computed correctly.


Workaround: 1) Compile without optimization
         2) Use a different variable for the array index.


5280     V6.40  will fix next release
  If in a simple loop there are one or more assignments of array elements,
addresses of objects, or through pointers to array elements or through
pointers, and the last assigment in the loop is the integer 0, then 
an error in register tracking may cause the compiler to perform the
assignment of 0 incorrectly.

For example:

int a[10], b[10];
int *p;

try()
{
    int i;

    for (i = 0; i < 10; i++)
    {
      a[i] = *p++;
      b[i] = 0;            /* ERROR OCCURS HERE */
    }
}

This error occurs only compiling with optimization (-o).

Workaround:

Move the assignment of 0 elsewhere in the loop.


5399     V6.40  will fix next release
  Under some circumstances, when optimization has been turned on,
the compiler may fail to recognize the code sequence described in 
the TMS320C2x/5x Optimizing C Compiler User's Guide [pg 4-18], that 
is designed to access the upper 16 bits of a 16 bit multiply. The
failure to recognize the code sequence results in the compiler
generating code to perform a 32 by 32 bit multiply instead.

i.e.

    int m1, m2;
    int result;

    result = ((long) m1 * (long) m2) >> 16;


Workaround:  1) Do not use optimization
             2) Declare both symbols in the multiply expression to
          be "volatile".


ASSEMBLER
-------------------------------------------------------------------------------

4884     V6.40  will fix next release
  The assembler may calculate the wrong size for a sturcture when that
structure has been defined with a non-zero beginning offset.

e.g.

34     0001     Localvar     .struct 1
35     0001     y          .word
36     0002     LVarSize     .endstruct        
...
...
   0003     c002     LARK          AR0,LVarSize    LVarSize should be 1
                              assembler assigns 2


4885     V6.40  will fix next release
  If a structure is defined with a non-zero beginning offset, then the
incorrect offset may subsequently be calculated for individual structure
members.

e.g.

37     0003     Para     .struct 3
38     0003     a          .word
39     0004     b          .word
40                    .endstruct
...
...

   0005     d200     LAR     AR2, #-Para.a     number should be -3
                           assembler returns -6.
   0006 fffa


4897     V6.40  will fix next release
  The  .mmregs directive does not work when -v26 option is selected.





Workaround: 1) Use .set directive to define memory-mapped regs.
          
          i.e.
               DRR     .set 0
               DXR     .set 1
               TIM     .set 2
               PRD     .set 3
               IMR     .set 4
               GREG     .set 5

            2) Since the CONF instruction is the only C26 instruction
            that is not supported in the C25 as weel, assemble with
            -v25 option and create a macro to perform the CONF
            instruction.

            CONF     .macro const
               .word 0CE3Ch | const
               .endm


5068     V6.40  will fix next release
  The assembler failes to properly encode the following instructions when
the -v26 option is used.

  LARP  ARx   ;  where x > 0
  OUT   dma,port  ; where port > 0


Workaround: Assemble/compile with -v25 option and define a macro for the
         C26 CONF instruction:

            i.e.

            CONF  .macro  const
                  .word   0CE3C|const
                  .endm


5170     V6.40  will fix next release
  The assembler does not correctly encode the BANZD instruction when
the decrement to the current ARx register is implied, rather than explicitly
included  in the assembly instruction.

i.e.

loop2  BANZD loop2,*-             <====== This instruction is encoded correctly


loop4  BANZD loop4                <====== This instruction will NOT be encoded
                           corereclty.


Workaround: Always explicitly decrement the current AR register when
         using the BANZD instruction.


5203     V6.40  will fix next release
  Note:  This is a problem when using -v26 option only!!!
The assembler issues Warning messages and does not correctly encode
the NORM instruction when an explicit argument is used in the
instruction,  

   i.e. NORM *   ,  NORM *+ ,   NORM *-



Workaround: Compile/assemble with -v25 option


DOCUMENTATION
-------------------------------------------------------------------------------

4886     V6.40  will fix next release
  There is an error in the example for using the .struct/.endstruct/.tag 
directives in the TMS320 Fixed-Point DSP Assembly Language Tools, User's 
Guide (1991)

p.4-66  Ex.1, line 4
     now:          real_len = 4
     shoulod read:     real_len = 2

     Ex.2, line 5
     now:          rec_len = 8
     should read:     cplx_len = 4

p.4-67  Ex.4, line 6
     now:          x_int = 67
     should read:     x_int = 66


4887     V6.40  will fix next release
   There is an error in the example given in the TMS320C2x/5x Optimizing C 
 Compiler User's Guide, rev. C, Aug. 91 on pg.4-10 that describes the
 code to properly terminate a function so that the C environment is
 preserved.


     Code Currently Reads:

     LAR     AR7, *-
     LAR     AR6, *-
     SBRK    SIZE
     .
     .

     Should  read:

     LAR     AR7, *-
     LAR     AR6, *-
     SBRK    SIZE + 1
     .
     .


RTS
-------------------------------------------------------------------------------

5035     V6.40  will fix next release
  The RTS routine that performs the context save/restore for interrupts, does 
not save/restore the value of the TREG1 register on interrupts.  To fix this
problem, the interrupt save/restore code must be modified to save/restore
TREG1.  Follow these steps:

1) Extract the interrupt save/restore code

     dspar -x saverest.asm rts.src

2) Edit saverest.asm

   Between current lines 61 and 62 add the following:

     LAMM     TREG1
     SACL     *+

   Between current lines 125 and 126 (lines 127 and 128 after the previous
   change) add the following:

     LAC     *-
     SAMM     TREG1

3) Re-assemble

     dspa -v50 saverest.asm

4) Replace in the library

     dspar -r rts50.lib saverest.obj


Now re-link your application using the newly modified RTS library.


LINKER
-------------------------------------------------------------------------------

5077     V6.40  will fix next release
  A bug occurs in the linker if you link two files which are both assembled from
this file:
 
        .global fred
fred    .equ 5
        .sym fred,5,4,2,8

The linker will give error message: >> internal error: : negative aux table id


-------------------------------------------------------------------------------
