[net.micro.68k] MIT 68000 C cross compiler bugs

sp@dutesta.UUCP (68000 project) (02/17/84)

We are using the MIT C cross compiler for the M68000 on our VAX 750 running
Unix Bsd4.1. However there are some bugs.

These are the ones we know of so far:

  1. sometimes dataregisters and addressregisters are mixed up. 
     In a routine to read data from an acia we found that after reading
     the acia status port the value read was transferred to an address-
     register and than the contents of that location were transferred to
     a location in bss space especcialy declared for that purpose by the
     compiler. This may cause address errors or bus errors.

  2. shorts may cause errors when they are used in long calculations.
     When performing long calculations the compiler sometimes makes
     room on the stack to store intermediate results. Shorts are than
     pushed on the stack as a word. When the compiler needs them later
     though, they are poped as a long.

  3. shift operations ( <<, >>, <<= and >>=) generate illegal opcodes.

Is there anyone who has discovered more bugs, or better has fixed them ?

Arrie v.d. Vliet
Delft University of Technology,
Department of Electrical Engineering
Switching laborotry

smk@axiom.UUCP (Steven M. Kramer) (02/20/84)

Well, you asked for more bugs.  Here's one I found today:

	The 68000 allows all kinds of effective addresses in moves with
one exception -- you cannot have a byte move with the source address
being the address direct register mode.  Well, try this out on the MIT
compiler:
-------------------------
struct line {
	char    len;
	char    l[80];
};

fixlines() {
	register struct line   *lp;
	register char  *p;

asm("before_bug:");
	lp->len = p +1 - lp->l;
asm("after_bug:");
}
--------------------------
The results getting computed, p+1 and lp->l, are both put into address
register because they point to addresses.  However, their result is
moved into lp->len, a byte move because len is a character.  The
offending instruction looks like:
movb	.a0,.a5@
where .a0 has the result and .a5 is lp, so .a5@ points to the first
element in the structure, or lp->len.

I think the trick is to assume (??) that all byte moves deal with
data since I can't think of a case where the compiler would produce
something different, and change the above assembler output to:
movl	.a0,.d0
movb	.d0,.a5@
I know it's a waste, but, hey, it's quick and dirty!  Now to find out
where this kludge goes...
-- 
	--steve kramer
	{allegra,genrad,ihnp4,utzoo,philabs,uw-beaver}!linus!axiom!smk	(UUCP)
	linus!axiom!smk@mitre-bedford					(MIL)

smk@axiom.UUCP (Steven M. Kramer) (02/20/84)

To followup the last article, I think the code table should handle
this strange case, but it doesn't.  It's using a 'movZB, AL, AR'
entry.  Anybody have the answer?

For now, I'm coercing the expression --
lp->len = (unsigned int)(p+1) + lp->l);
so that a data register is used rather than an address register.
-- 
	--steve kramer
	{allegra,genrad,ihnp4,utzoo,philabs,uw-beaver}!linus!axiom!smk	(UUCP)
	linus!axiom!smk@mitre-bedford					(MIL)

smk@axiom.UUCP (Steven M. Kramer) (02/22/84)

Another bug in the MIT compiler is that it tries to handle switch
statements a little TOO fancy.  In a switch where the case values are
ordered and each next case is an increment of 1 (thereby making a
nice sequential range) [I forget if it has to start at 0 or not],
it generates a jump table rather than if-then code.  However, the
computation to decide what to use in the switch table is hard coded
to assume the table is right after the decision code.  An optimizer will
move the table around and the hard coded assembler is no longer
valid.  I haven't written the fix (which should use the label right
before the switch table rather than the hardcoded 6 offset from the pc)
yet, but it belongs in genswitch() in code.c and involves replacing the movw
and jmp statements with non-hardcoded assembler that uses the label
generated next (so the getlab() should be done before the movw
so it is available then and swlab is used below without another call to
getlab()).

	To get rid of the bug temporarily, you can simple comment out the
if (range ...
statement (which is most of the routine).  This fixes everything, albeit
the code is now not optimal.

	Whoever fixes the bug must also remember the if (range ...) statement
depends on the number of instructions in the fix, because of the fix is 10
lines long, the range check should be altered.

	If someone fixes this (it shouldn't take too long but I'm new to the
68000 and I would rather have a pro generate the best instructions here),
please send me the fixes.

	Credit goes to Mike Larson who discoved the bug.
-- 
	--steve kramer
	{allegra,genrad,ihnp4,utzoo,philabs,uw-beaver}!linus!axiom!smk	(UUCP)
	linus!axiom!smk@mitre-bedford					(MIL)