-------------------------------------------------------------------------------
* RELEASE 4.40 BUGLIST                                                        *
* Update - 01/08/93                                                           *
*                                                                             *
* This file contains a list of bugs in the release 4.xx of the 320C30 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.                                                          *
*                                                                             *
-------------------------------------------------------------------------------

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

4528     V4.40  will fix in V4.41
  The compiler may use a RPTS instruction for a structure assign even though 
the -mi option has been selected.


4542     V4.40  will fix next release
  In rare instances multi-dimensioned arrays referenced using a constant index
value may produce incorrect code. 

	Example:
		extern float *p[2][2];
		extern float *f;

		void main()
		{
			int i;
                             .
                             . 
                             .
			p[i][1] = f;
		}

Work Around:
	Use a variable, instead of a constant, to index the array.
	Note: this may not work when using the optimizer.

	Example:
		extern float *p[2][2];
		extern float *f;

		void main()
		{
			int i, index = 1;
		             .
                             .
                             .
                        p[i][index] = f;
		}


4552     V4.40  will fix next release
  The compiler may generate incorrect code when two arrays indexed
by the same variable appear in a comparison within a for loop.

e.g.
        for(ix=0;ix<20;ix++)
	if (array[ix]>array2[ix])

Workaround:  Use pointers to access elements of the array

          int array[20],array2[20];
          .
          .
         int *arr1=array, *arr2=array2;
          .
          .
 
          for(ix=0;ix<20;ix++) {
            if (*arr1++>*arr2++)
              .
              .
              .


4560     V4.40  will fix next release
  In some cases the compiler may use AR1 within an interrupt service routine, 
but fails to generate the code to save/restore the contents of AR1 on 
entry/exit from the interrupt service routine.


Workaround: 1. Include a dummy function call within the interrupt
	    service routine.

	    2. Include asm statements at the start and end of the routine 
	    to push/pop AR1 from the stack.

	    i.e.

	    c_int01()
	    {
	      asm ("    push AR1");
	      ...
	      ...
	      ...

	      asm ("	pop AR1");
            }


4574     V4.40  will fix next release
  The compiler may not generate code for an inline function, when that function
is declared with STATIC attribute.

e.g.

typdef struct { int a } AStructure;

/*
 *  no code is generated for this function becasue it is "static inline"
 */

 static inline
 AStructure
 AnInlineFunction(void){
	AStructure	b;
	b.a = 1;
	return (b);
 }

 AStructure c;

 /*
  *  tries to call AnInlineFunction() normally
  */

 void
 CallingFunction(void) {
	c = AnInlineFunction();
 }


4575     V4.40  will fix next release
  The compiler fails to generate code to clear the repeat mode, RM, status bit 
at entrance to an interrupt service routine after pushing the value of the
status register on the stack. If the interrupt being serviced occurred
during execution of a RPT block, this would leave the device in repeat
mode on entering the service routine. If the RE register is then modified
within the interrupt service routine such that its value corresponds to 
the value stored in the PC, the device will branch to the location stored in 
the RS register, leading to spurious results.


Workaround:  Include an "asm" statement at the start of the interrupt
	     service routine to clear the RM bit in the status register.

	     i.e.

	     c_int01()
	     {
		asm("	ANDN  0100h,ST");
		...
		...
              }


4579     V4.40  will fix next release
  Note: This is an optimization problem only!
In rare instances the compiler may generate an invalid parallel instruction
FIX || STF., when a floating point conversion to int is followed immediately
by a floating point store and the source for the conversion is same as the
destination for the store.

e.g.

void bug()
{
 int i;
 unsigned int i_temp;
 float *s_ptr, *d_ptr;   /* these are pointers to addreses */

 for (i=0;i<10;i++)
 {
   i_temp = *d_ptr;       /* Error occurs here */
   *d_ptr++ = *s_ptr;
   *s_ptr = i_temp++;
 }
}

Workaround:  Compile without optimization.


4588     V4.40  will fix next release
  The compiler errs when generating code for the condition on a while loop,
when the control is a simple instance of a variable name and that variable
is unsigned.

e.g.

main()
{
unsigned int count;

count = -1;

while (count -- )                 ; Compiler generates code to branch to
				  ; loop start when count >= 0, so loop
				  ; is not executed correctly.
    printf( "count=%d\n",count);
}


4590     V4.40  will fix next release
  Note: This is a level 2 optimization problem only!!
Under some circumstances the optimizer may generate the wrong address for a
structure element when there are several structures of the same type appearing
in the same function, and each of the references to these seperate structures
accesses the same structure member.

i.e.

tpyedef struct { int a,b,c,d,e; } STYPE;


STYPE	s1,s2,s3,s4;


func()
{
     ...
     ...

     s1.a = dummy;
     s1.d = dummy * 2;

     ...

     s2.a = dummy + 1;        /* incorrect address will be generated here */
     s2.d = 2 * dummy + 1;

     ...
     ...

     s3.a = dummy + 2;        /* incorrect address will be generated here */
     s3.d = 2 * dummy + 2;

     ...
     ...


WORKAROUND:  compile without optimization , or compile with level 1
	     optimization only.


4677     V4.40  will fix next release
  The compiler may sometimes treat signed bit fields as unsigned.

i.e.

typedef struct
{
	int 	signed_bits:16;
	int	junk1:16;
	int	junk2:16;
	int	junk3:16;
} TEST_STRUCT;

TEST_STRUCT test_struct;
int fail;

main()
{
	test_struct.signed_bits = -1;

	if (test_struct.signed_bits < 0)
	{
	    fail = 0;      /* correct */
	}
	else
	{
	    fail = 1;      /* wrong */
	}
}


4689     V4.40  will fix next release
  In some rare instances when the optimizer attempts to share a register
with a loop control variable and a variable initialized prior to the
loop, the code generated may not update the loop variable properly.


Workaround: compile without optimization or with optimization level
	    -o1.


4692     V4.40  will fix next release
  The compiler may incorrectly flag the error "type never completed" for
an external array that is declared with unknown size.

i.e.

struct inmodel1 {
double length, width, as , ad, ps, pd;
double vto, kp, gamma, phi, lambda, gd, gs, cox, cjo, cjsw;
double sqrthi, fixvto, cg, cs, cd;
int modelnum, type;
};

extern struct inmodel1 *mod1array[];
struct inmodel1 *mod1array[];         /* Error generated for this declaration */


main()
{
}


4693     V4.40  will fix next release
  The compiler may generate incorrect code for expressions involving the 
autoincrement of bit fields.

/* test.c */

main()
{
  struct t { unsigned i9: 9 , i1: 1, i11: 11, i10: 10; };
  static struct t x = { 15, 1, 16, 17 };

  x.i11 = x.i10++ + 10;

...
...


Workaround:  Perform autoincrement in separate statement.

i.e.    x.i11 = x.i10 + 10 ;  x.i10++;


4694     V4.40  will fix next release
  If a Struct & union/enum have the same name, the compiler correctly generates
an error message but then hangs. 

i.e.

/* test.c */
main()
{
 union u_tag { int a; float b; };
 struct u_tag { intc, d; };          /* Error message is generated then
					program hangs */
}


4695     V4.40  will fix next release
  The compiler may generate incorrect code for calculating the initiliazion
value for a pointer, when the pointer is initialized using a constant 
expresion invloving addition/subtration to/from the address of a string 
literal constant.

i.e.

static char *x = "string" + 1;   /* Incorrect code generated */

main()
{

...
...


4710     V4.40  will fix next release
  The compiler does not properly initialize character strings literals that
have been typed as wide char.

i.e.

  wchar_t a, *e;

  e = L"what's up?';      /* e will not be initialized correctly */


4761     V4.40  will fix next release
  Note: This is a PC problem only!!      
In some rare instances the compiler may exit with the DOS error:

	run-time error M6101: MATH
	- floating point error: invalid

The error may occur under the following circumstances:

      1.  The code contains a flotaing point expression.
      2.  The floating point expression has at least one operand that
	  is a conmstant known at compile time and the value of that
	  constant has an exponent > e18.
      3.  At elast one of the other operands is a variable.

i.e.

#define cuthi ( (float) 1.304e19)
void
main(void)
{
  volatile float hitest,x;
  volatile long n;
/* this does not crash the compiler */
x = cuthi
/* this does */
hitest = cuthi / ( (float) n );
}


4763     V4.40  will fix next release
  The compiler may perform incorrect integral promotions for unsigned bit
fields, unsigned chars, and unsigned shorts.  The compiler will incorrectly
promote these values to unsigned int, rather than int as required by the 
ANSI standard. This means that for some expressions, incorrect results may 
be generated.

i.e. 

int result;

int main(void)
{
   unsigned char uc = 2;
   struct {
      unsigned x: 8;
      unsigned z: MAX_SIGNED;
   } str;
   str.x = 2;
   str.z = 2;

   result = 5/(~str.x);    /* All three assignment should return a result
   result = 5/(~str.z);        of   -1 ,  but return   0 instead          */
   result = 5/(~uc);
}

Workaround: Explicitly cast the expressions as int.
            i.e.

	    result = 5/(int)(~str.x);


4764     V4.40  will fix next release
  Note: This is a problem when using -mr option only!
In some rare instances the compiler may generate an illegal LDF instruction 
to an AR register when trying to convert a float/double arguement that is 
being passed to a function and the corresponding function parameter has been 
prototyped as int.

#define MAX_VERTICES   150

typedef struct vector {
	float x;
	float y;
	float z;
} VECTOR;

VECTOR UNIVRAD;

float arctan0(int,int);

void func(int obj)
{
  float bufferx[MAX_VERTICES] ; 
  float buffery[MAX_VERTICES] ;
  float bufferz[MAX_VERTICES] ;

  int vert[4];
  VECTOR N;

  UNIVRAD.x = arctan0(N.x,N.y);
}


Workaround: Compile without -mr option.


4769     V4.40  will fix next release
  In very rare instances the compiler may generate an undefined label in
the assembly code for a series of if and switch statements which
follow back-to-back.  This causes errors when trying to assemble
the resultant code.

i.e.

main()
{
  
  int a;

  a = 9;

  switch (1) {

   default : a=1;
  }

  if (a!=1) {}

  switch (1) {

   case 1 : a=2;
  }

  if (a!=2) {}

  switch (1) {

  }

  if (a!=2) {}

  switch (1) {

   case 1 : a=3;
            break;
   default : a=1;
  }

  if (a!=3) {}

  switch (1) {

   case 2  : a=4;
  }

  if (a!=3) {}

  switch (1) {

   case 2 : a=2;
            break;
   default : a=5;
  }

  if (a!=5) {}
}


Workaround:  Include "default" cases for each switch statement


4772     V4.40  will fix next release
  The compiler may generate incorrect code for calculating the address of
an array element when a negative constant is used to index the array
and the value of the negative constant has absolute value greater than 255.

#define N 512

int data[N];

main()
{
int i, *p;

for (i=0;i<N;i++)
    data[i]=i;

p=&data[N-1];


printf("[255] = %d  ",p[-256]);     /* incorrect addresses calculated here */
printf("[254] = %d  ",p[-257]);

}

Workaround:  Use pointer arithmetic instead

	     i.e.  printf("[255] = %d  ",p-256);


4776     V4.40  will fix next release
  Note: This is an optimization problem only!
The optimizer may under some circumstances incorrectly optimize out
a comparison, when a constant expression has been used to set the 
values of the members of a structure and these members are then
used in the comparison.  It does so believing that it knows
the values of the elements despite the fact that a subsequent
assignment was made to the structure.

/* Cut down version of RR0084.C */

#include <stdio.h>

struct {int e,f;} s1,s2;

main()
{
   s1.e = 3; s1.f = 5; s2.e = 1; s2.f = 8;
   s1 = s2;
   if((s1.e!=1) || (s1.f!=8)) printf("Fail: struct assignment\n");
   /* Optimizer optimizes out the above compare and generates code
      for printf statement */
}


4780     V4.40  will fix next release
  The compiler fails to issue an error message when it encounters an "elif"
preprocessing directive that does not have a corresponding "if" clause.  

i.e.

#include <stdio.h>

main ()
{
#define AAA 5
#elif AAA == 5
   printf("should not have compiled (a)\n");
#endif
   printf("should not have compiled (b)\n");
}


4828     V4.40  will fix next release
  The following code produces a "REGISTER ALLOCATION FAILURE" message when
compiled and then proceeds to asssemble the .asm file despite the error.

struct
{
 int a;
 int b;
} table1[10];

struct
{
 int x;
 int y;
} table2[10];

void function(int index)
{
 table1[table2[index.x].a = table1[table2[index].y].b;
}


4865     V4.40  will fix next release
  Under some rare circumstances the compiler fails to generate code for the TRUE
portion of a conditional assignment statement.

i.e.

struct a
{
	int b;
	int x;
	int x1;
	int x2;
};

void bug(struct a *p)
{
	p->x = (p->b) ? p->x1 : p->x2;   /* code for TRUE result never
					    genertaed */
}


Workaround:  Use a temporary variable in the assign

i.e.

int y;


y = (p->b) ? p->x1 : p->x2;
p->x = y;


4866     V4.40  will fix next release
  Under some rare circumstances the compiler may not generate code to
increment a loop variable, when that loop variable is unsigned and is
used as an array index within the loop.

typedef struct{
   struct {
   int c;
   } b[10];
} test_t;

test_t u;

void main()
{
unsigned int i,j;  

  for (i=0; i < 9; i++)

     j+= a.b[i+1].c; 
} 


Workaround:  increment variable within the loop

i.e.

  for(i=0; i<9;)
   j+= a.b[++i].c;


4880     V4.40  will fix next release
  In some rare cases the header on the assembler line will show the line
"Opt30 Not Run", even though the optimizer was indeed invoked.


4943     V4.40  will fix next release
  The compiler may generate incorrect code for an   if  condition
when :

    1) The condition on the if consists of the simple evaluation of
       a structure element.

	i.e.    if (p->a) ....

    2) And, the THEN portion of the IF , contains an assignment to 
       that same element from another element within the same structure 
       whose offset is greater than 255

       i.e.     if (p->a)
		  p->a = p->b       (offset of b is greater than 255)


Under these circumstances the  IF contidion may not be evaluated
correctly.

Workaround: Use a temporary variable in the place of the element
	    whose offest is greater than 255.

	    i.e.   volatile int tmp;

		   .
		   .
		   tmp = p->b;
		   if (p->a)
		     p->a = tmp;


4946     V4.40  will fix next release
  In some instances when two structure pointers of the same type are
used in a structure assignment and both are CAST to another structure
pointer type, the compiler may ignore the cast and generate code
to make the structure assignment based on the original type of the
structure pointers.

i.e.

typedef struct {
	float		x;
	float 		y;
	float 		z;
} POINT3;

typedef struct {
	float		x;
	float 		y;
	float		z;
	float		w;
} POINT4;

typedef struct {
	POINT4		z;
	POINT4		a;
	POINT4		b;
	POINT4		c;
} BIGONE;

void sub1 (POINT4 *a, POINT4 *b, POINT4 *c, BIGONE *v)
{

   *(POINT3 *) &v->b = *(POINT3 *) &v->c;   /* Compiler generates code
					       as if v->c and v->b are
					       both type POINT4 even
					       though they have been 
					       cast to type POINT3 .

Workaround: Use a temporary var in the assign

i.e.    POINT3 *tmp;

	tmp = (POINT3 *) &v->c;
	*(POINT3 *) &v->b = *tmp;


4958     V4.40  will fix next release
  The compiler may generate a register allocation failure under the following
circumstances:

   1. A statement consists only of the instance of a union/structure element.

   2. The element address is the result of the dereferencing of
      a CASTed expresssion that consists of a constant expression.

   3. And the result type of the casted expression is pointer to union
      type.

  	i.e.

	typedef volatile union vunion {
  	unsigned mask;   
  	struct {
    	int a;
    	int b;                   
    	int c[2];
  	} first;
  	struct {
    	int status;
    	int :1; int :0;              
    	int :16; int result: 16;
  	} second;
	} VUNION;
