From: DSP Hotline

Subject: 320C1x/2x/5x Code Generation Tools Bug List

-------------------------------------------------------------------------------
* RELEASE 6.40 BUGLIST                                                        *
* Update - 11/18/94                                                           *
*                                                                             *
* 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 othwerwise     *
* 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".


5422     V6.40  will fix next release
  The compiler errs in generating incorrect code for the assignment
of an unsigned long variable to a volatile unsigned long.

The compiler generates an erroneous LAC ? instruction.

e.g.

extern volatile unsigned long A,C;

Main()

{
    A = C;
}

Workaround: Rewrite as follows;

         A = C+1;
         --A;


5534     V6.40  will fix in V6.41
  The code generator crashes when compiling the following IF-THEN-ELSE:

      point->code[index] = index ? point->code[0] : local;



WORK AROUND:
============

Replace the code above with the following code,
which compiles without error:

     if (index)
           {
           point->code[index] = point->code[0];
           }
       else
           {
           point->code[index] = local;
           }


5597     V6.40  Fixed in V6.41 
  Pointers to longs (or structures) are lost on occassion when
the optimizer assigns the base pointer to a register then 
attempts to manipulate the register incorrectly.  This will
not occur in every case; only situations identified by the
optimizer as warranted.  This has been corrected for the next
release.

EXAMPLE:
The base pointer is lost in the first assignment, which 
means that the second assignment is based on a wrong pointer, 
as seen in the following code:  

void link_in_timer(union SIGNAL *l_p)
{
    union SIGNAL *t_p;
 
    pp = &first;    /* "first" is a long or structure  */
 
    l_p->vmt_timer_start.next = t_p;
    *pp = l_p;
}

The order of the statements affects the code's validity; the
following ordering will correct the above statements for the
case in question:
 
       *pp = l_p;
       l_p->comm_timer_start.next = t_p;
 
Compiled with the following options:
       -ea.s50 -c -v50 -mx -o0 -s -g -mn -al -as


5747     V6.40  will fix in V6.48
  The customer is having problems with 7,000 symbols and 
they need to use 30,000 symbols.  Is there any work 
around.  Lot of the symbols are coming from C-code.

WORK AROUND/SOLUTION:
=====================
This problem can be solved by using version 7.10 of the 
OS/2 C5x debugger and the 6.48 Beta release of the 
Assembler/Linker.  The new assm/lnk creates few symbols
and the new debugger is required to interpret the output
from the new code generation tools.


5750     V6.40  Fixed in V6.43 
  Compiler fails to deal with long integers. Only the lower half
of the accumalotr is checked for 0 when the entire accumulator
should be checked.

volatile int signal = 0;

void main(void )
{
  unsigned long timeout;
  timeout = 65537;
  while ((long) timeout && !signal)
        timeout--;
}

WORK AROUND/SOLUTION:
=====================
Turning off optimization eliminates this problem; also,
altering the code to prevent the problem from being 
generated by the optimizer.  This problem has already
been corrected for the next release.

Also, the problem can be worked around bydeclaring 
'timeout' to be 'long' and not doing any casts to 
'unsigned long'.


5751     V6.40  Fixed in V6.43 
  Optimizer incorrectly calculates indexes.

#include "header.h"
extern struct bogus {
      struct {
               int foo;
               int bar;
      } foobar[2];
} *bogusArray;

extern int *start;
extern int count;

void main()
{
  volatile int i;
  int *intPtr;

  for (i = 0, intPtr = start; i < count; i++, intPtr++)
      *intPtr = bogusArray[i].foobar[0].bar; /* problem statement */
}

WORK AROUND/SOLUTION:
=====================
The problem has already been corrected for
the next release.  Turning off optimization
will eliminate the problem; also, altering the
code to prevent the optimizer from producing
the exact same code can prevent the problem
from occuring.


5752     V6.40  will fix next release
  When a forward reference is made to a struct in a C file
from a header file, the version 6.40 C2x/C5x SUN compiler
gives a core dump.

/**************************  header.h  ***********************/
struct bogus *bogusArray;

int value = 10;
int *start = &value;
int count = 10;
/*************************************************************/

/***************************  bug.c  *************************/
#include "header.h"

extern struct bogus {
      struct {
               int foo;
               int bar;
      } foobar[2];
} *bogusArray;

extern int *start;
extern int count;

void main()
{
  int i;
  int *intPtr;

  for (i = 0, intPtr = start; i < count; i++, intPtr++)
      *intPtr = bogusArray[i].foobar[0].bar;
}
/*************************************************************/

WORK AROUND/SOLUTION:
=====================
Do not have forward references of data structures.

Just in case you're curious, here's what triggers it:
1) A tentative declaration has a forward reference to a structure tag.

   struct x *p;      /* struct x has not yet been defined */

2) A later external redeclaration of the same symbol completes the
   definition of the tag.

   extern struct x { int a, b; } *p;
                     /* p redeclared; struct x defined */

Since p is not rewritten to the i-file, the structure declaration was not
getting written either.


5754     V6.40  will fix next release
  C5x compiler optimizer removes "dummy reads" that are necessary for flushing
a buffer.  The volatile key word is used other locations to prevent code
from being removed, but that does not seem to work in this case.

WORK AROUND/SOLUTION:
=====================
The values on the left and the right side of the dummy
assignment can be declared "volatile"; not just one
or the other.  Also, declaring the variable as
"int * volatile ptr" or "volatile int * volatile ptr"
instead of "volatile int *ptr" will prevent incorrect
code from being generated.


5758     V6.40  will fix next release
  The assembler does not issue a warning for a possible
pipeline confliect when a ZAP instruction is followed  
immediately by an LPH instruction.

    ZAP        or     ZPR
    LPH               LPH

The problem is that ZAP will compete with LPH for use of
the product register and ZAP/ZPR will win out.  So that
the following load LPH will have null effect.  The
assembler should warn of this side effect.


5804     V6.40  Fixed in V6.48 
  The 'bcnd ov' clears the overflowbit and therefore the next 'bncd nov'
generates a wrong result!

WORK AROUND/SOLUTION:
=====================
This has been fixed for the next release.  For a work around, shift the 
numbers to the right once.  Due to the preshift, the numbers are again 
in a range the compiler handles correctly.

long CompilerError2 (long a,long b)
{
   if ((a>>1) > (b>>1))
    return a;
   else
    return b;
}


5805     V6.40  will fix next release
  A delayed branch is generated which is followed by a two word 
instruction and a one word instruction.  The one word instruction
does not get executed.  For example, in the following the SACL 
instruction is never executed:

         .
         .
         .
;>>>>                 *(int*)TEST_KONSTANT = *iptr+40;
     MAR     * ,AR2
     LARK     AR2,2
     MAR     *0+
     LAR     AR4,* ,AR4
     LAC     * ,AR3
     ADDK     40
     BD     L3
     LARK     AR3,028c8h
     SACL     * 

WORK AROUND/SOLUTION:
=====================
In some instances compiling with -g cause the generated code to
be correct.  Also, changing #define lines to const variables 
forces code to generate correctly.


5833     V6.40  will fix in V6.48
       The compiler generates incorrect code when a structure is declared as volatile and
it is assigned within a loop and compiled with optimization at level -o2 or -oe.

e.g.

struct struct1 { int x;};
struct struct2 {int y; int z;};
volatile struct struct1 OtherStruct;
volatile struct struct2 RightStruct;

void main(void)
{
     int count=1;
     
     while (count++<2){
          OtherStruct.x=1;
          RightStruct.z=2;
     };
}

     The last statement in the above code stores 2 in OtherStruct.z instead of 
RightStruct.z.

Workaround:

     Do not use optimization at level -o2 or -oe.  Bug will be fixed in next release.


5905     V6.40  Fixed in V6.48 
  The DSP compiler generates incorrect code whenenver there's a comparison between unsigned
long and a constant.  The assembly code generated from the C code only compares the 16 LSB
of the unsigned long to the constant.  Below is a sample C code that demonstrates the bug 
and also the corresponding assembly code in question.  

main()
{
  int dummy=0;
  unsigned long ul=0x10000, zero=0;

  if(ul==0)    /* This condition evalutates to true, obviously this is wrong */
    dummy=1;
  if(ul==zero) /* This is fine - condition evaluates to false */
    dummy=1;
}

>From assembly file...

;>>>>     if(ul==0)    /* This condition evalutates to true, obviously this is wrong */
        SBRK    3
        ZALS    *+
        ADDH    * 
        ANDK    0FFFFh  ;<<<<bug: compares only the 16 LSB of ul to 0<<<<<<<<<<<<<<<<
        BNZ     L1

Workaround/Solution:

     1) Don't make the variable unsigned.
OR
     2) Make the constant and unsigned long.
OR
     3) Use newer version of the DSP Compiler.


5948     V6.40  will fix in V6.50
  The optimizer uncovers a bug in the codegen.  The bug appears when an array 
of structures is copied from one array to another and the array is declared as static, 
The following sample code should sufficiently demonstrate this bug.


typedef struct TEST{
        int a[5];
} TEST;

static TEST test1[2];
static TEST test2[2];

main(void)
{
        static TEST *source;
        static TEST *dest;
        int i;

        source=&test1[0];
        dest=&test2[0];

        for(i=0;i<2;i++){       
                *source=*dest; 
                source++;     
                dest++;      
        }
}


*******************************************************
*  TMS320C2x/C5x ANSI C Codegen    Version 6.40       *
*******************************************************
;     dspac -q -v25 -x -x x x.if 
;     dspopt -q -v25 -s -O2 x.if x.opt 
;     dspcg -q -o -v25 x.opt x.asm x.tmp 
     .file     "x.c"

     .stag     _TEST,80
     .member     _a,0,52,8,80,,5
     .eos
     .sym     _TEST,0,8,13,80,_TEST

     .sym     _main,_main,36,2,0
     .globl     _main

     .func     8
******************************************************
* FUNCTION DEF : _main
******************************************************
_main:

LF1     .set     1

     SAR     AR0,*+
     SAR     AR1,*
     LARK     AR0,2
     LAR     AR0,*0+
;     <save register vars>
     SAR     AR6,*+
     SAR     AR7,*+,AR2

     SSXM
*
* AR6     assigned to variable 'source'
* AR7     assigned to variable 'dest'
*
*** 7     -----------------------    source = &test1;
     .sym     L$1,1,4,1,16
     .line     7
     LRLK     AR6,_test1
*** 8     -----------------------    dest = &test2;
     .line     8


5949     V6.40  will fix in V6.50
  A customer claims that if a value greater than 2831068799 is passed to one of the 
timer functions, then the results returned is garbage.


Workaround/Solution:

Since our implemetation of the timer functions has jan 1, 1900 as the base, any 
numbers representing dates after sept, 17 1987 would fall out of range for the
members in struct tm, ie. tm_mday.  The following can be used as a workaround for
this bug.


/****************************************************************************/
/*  localtime V6.50                                                         */
/*  Copyright (c) 1990-1994 Texas Instruments Incorporated                  */
/****************************************************************************/
#include "time.h"

#define SECS_IN_MIN 60L
#define MINS_IN_HR  60L
#define HRS_IN_DAY  24L
#define SECS_IN_HR  (SECS_IN_MIN * MINS_IN_HR)
#define SECS_IN_DAY (SECS_IN_HR * HRS_IN_DAY)

#define LEAPYEAR(y) (    (y+1900) % 4   == 0                               \
               && ((y+1900) % 100 != 0 || (y+1900) % 400 == 0))
#define DAYS_IN_YR(y) (365L + LEAPYEAR(y))

struct tm *localtime(const time_t *timer)
{
   static struct tm local;
   time_t ltime  = timer ? *timer : 0;
   int year;

   local.tm_sec  = 0;
   local.tm_min  = 0;
   local.tm_hour = 0;
   local.tm_mday = 1;
   local.tm_mon  = 0;
   local.tm_year = 0;

   if (timer == 0 || ltime == (time_t)-1) return &local;

   /*------------------------------------------------------------------*/
   /* MAKE SURE


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


5519     V6.40  will fix in V6.41
  The following message:  WARNING - REGISTER CONVERTED TO IMMEDIATE
is generated assembling the file below:

;
        .mmregs
zwsp2   .set    1
        .asect  "abs1",2000h
 
        .label  eram1
 
ipo19   lacl    zwsp2           ;= t1
        sub     #1
        samm    ar5             ;= t1-1
        add     #2
        samm    ar6             ;= t1+1
        mar     *,ar5
        lacl    *,ar6
        sub     *
        bcnd    ipo22,geq
        lacl    zwsp2   ;(t1+1) > (t1-1)
        sub     *,ar7
        sub     #32
        bcnd    ipo20,leq
        lacl    #0
ipo20
ipo22   nop


5551     V6.40  will fix in V6.41
  The following code will cause a segmentation fault of the assembler             when compiled with the -s option:

          .ref     YZ
     x     .set     YZ

which means that x is chained to YZ.  

WORK AROUND
===========
To avoid this problem, use external symbols
directly in expressions.


5566     V6.40  will fix next release
  The C5x assembler (v4.5) directive .bes will put a label on the last word
reserved only if the last bit reserved is not on a word boundary.
Otherwise, the label goes on the next word.    In other words,
if the number of bits specified by the ".bes" directive is evenly
divisible by the word size (16 bits), then the label points to
the word after the last word that contains reserved bits.

For example:

label1 .bes 18    ; label1 is 0x1, where the directive
                  ; reserves two words at 0x0000 and
                  ;                       0x0001
            ; This is correct.


label2 .bes 32    ; label2 is 0x2, where the
                  ; reserves two words at 0x0000 and
                  ;                       0x0001
            ; This is NOT correct.
            ; label2 should be 0x1


Workaround
----------
When the number of bits specified in the .bes directive is an even
multiple of 16, the value of label should be one less than the value
it is assigned.


5795     V6.40  will fix next release
  Failure of the -w (pipeline warning) switch:
 
            sacl  arcr
            samm  arcr
            lmmr  arcr, #address
 
            sacl  indx
            samm  indx
            lmmr  indx, #address
 
All of these should generate a pipeline warning, just as sacl, samm, or lmmr
with an auxiliary register as a destination do, since they have the same
potential for pipeline conflict.
 
I also noticed that if the .mmregs directive precedes the .version directive
in an assembly source file, the assembler will flag as errors the use of the
`C5x only register mnemonics, such as arcr, indx, and so on


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


5563     V6.40  will fix in V6.41
  The Fixed_Point Assembly Language Tools User's Guide fails to
mention that -c / -cr options should not be used on incremental
links. These options should only be used on the final link.
The reason that this is necessary is that a zero word is appended
to the end of the .cinit section when -c/-cr options are specified.
The zero word is used by the initialization code in boot.asm to
mark end of .cinit data. Thus all of the data may not be initialized.


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 and TREG2.  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     *+
        LAMM    TREG2
        SACL    *+

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

        LAC     *-
        SAMM    TREG2
     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.


6107     V6.40  will fix next release
  The realloc run time library function contains a bug which causes 
it to work incorrectly. The routine may give an error message that memory
cannot be allocated even though there should be memory remaining in the
heap.

Workaround:

  1. Extract the file memory.c from the rts.src library

     dspar x rts.src memory.c


  2. Edit the file, making the following change:

     old line 310: ((PACKET *)pptr)->packet_size = -(temp + 1);

     new line 310:  ((PACKET *)pptr)->packet_size = -(temp - 1);


  3. Recompile the file with whatever options were used to make
     your version of the rtsxx.lib. (For versions shipped with the
     compiler tools, these are compiled with options -v50 -o -mx
     for rts50.lib , and -o for rts25.lib)

     dspcl -v50 -o -mx memory.c
     dspar r rts50.lib memory.obj


  4. Replace the old memory.c  with newly edited source in rts.src.

     dspar r rts.lib memory.c


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


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