[net.micro.68k] MIT 68K C Compiler bug fix

jlilien@sdcrdcf.UUCP (Joel Lilienkamp) (02/22/84)

I worked on the MIT 68K C Compiler when I was at MIT Lincoln Laboratory.
The version of the compiler I have may be slightly out of date, although
I suspect that the fix I list here would not have to be changed much.

The bug in the compiler can be fixed by adding one additional entry in
table.c.  The offending entry in the table is near the beginning, and
looks something like this.

ASSIGN,	INAREG|FOREFF|FORCC,
	EAA,	TSCALAR|TFLOAT,
	EA,	TSCALAR|TFLOAT,
		0,	RLEFT|RRIGHT|RESCC,
		"\tmovZB\tAR,AL\t;\n",

The bug can be fixed by adding the following entry immediately before it.

ASSIGN,	INAREG|FOREFF|FORCC,
	EAA,	TCHAR,
	SBREG|STBREG,	TCHAR,
		NAREG|NASR,	RLEFT|RRIGHT|RESCC,
		"\tmovl\tAR,A1\n\tmovZB\tA1,AL\t;\n",

Purists may want to change the EA in the third row of the original entry
to EAA, but since the table is sorted linearly, it should make little
difference.  Do your own thing.

While this fixes the example problem, I have not tested throughly, nor
have I looked for bizarre side effects.  I only hacked around for a half
hour or so.
	Joel

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

> Purists may want to change the EA in the third row of the original entry
> to EAA, but since the table is sorted linearly, it should make little
> difference.  Do your own thing.
> 
> While this fixes the example problem, I have not tested throughly, nor
> have I looked for bizarre side effects.  I only hacked around for a half
> hour or so.
> 	Joel
Not exactly correct.  Your table entry is exactly what is needed to
resolve the address to byte problem, but the latter suggestion noted
above is wrong (and don't get me wrong, it was easy to test the proposed
fix out and I'm MUCH more grateful for the fix than disheartened by the
above).

The suggestion to change EA to EAA is wrong, because then there would be
no table entry for normal assigments from address registers to shorts
or longs.  You have to keep the EA in rather than EAA and depend on the
ordering of the 2 entries to resolve the problem, whereby your new
table entry catches the byte problem and lets all the others drop through.

Note that for bytes, one extra movl instruction is generated (and I guess
there is a more optimal way to do this), but from what I see, the times
this occurs is minimal and optimizations efforts are better served elsewhere).

While on this vein, has anyone fixed this code found in code.c
so that the jump table is not hardwired to be right after the code (messing
up later optimization efforts on placing the table)?  Note my solution
was to ifdef out the bad code, but that's definitely not too hot.  Also
note my efforts to begin a fix.  I don't have the time to monkey with this,
so I'd appreciate comments from those of you who have.

-------------------------------------------------
genswitch(p,n) register struct sw *p;{
	/*	p points to an array of structures, each consisting
		of a constant value and a label.
		The first is >=0 if there is a default label;
		its value is the label number
		The entries p[1] to p[n] are the nontrivial cases
		*/
	register i;
	register CONSZ j, range;
	register dlab, swlab;

	range = p[n].sval-p[1].sval;

#ifdef MAKES_BAD_CODE
	if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */

		dlab = p->slab >= 0 ? p->slab : getlab();

		if( p[1].sval ){
			printf( "	subl	#" );
			printf( CONFMT, p[1].sval );
			printf( ",.d0\n" );
			}

		/* note that this is a cl; it thus checks
		   for numbers below range as well as out of range.
		   */
		printf( "	cmpl	#%ld,.d0\n", range );
		printf( "	bhi	.L%d\n", dlab );

		printf( "	addw	.d0,.d0\n" );
#ifdef PORT68
		/*
		 * The compiler produces code hardwiring the table to
		 * be right after this code, but the optimizer moves
		 * it to wherever.  We make the movw a bit more relative
		 * to allow for later movement of the jump table.
		 * Note, we need to get the label here (used for the
		 * relative jump) rather than below.
THIS IS WRONG AS IT IS, SO DON'T un indef
		 * Steve Kramer 2/20/84
		 */
		swlab = getlab();
		printf( "	movw	.d0,.a0\n" );
		printf( "	addw	.a0,.a0\n" );
		printf( "	movw	.a0@(.L%d),.a0\n" );
		printf( "	jmp	.pc@(2,.a0:w)\n" );
#else
		printf( "	movw	.pc@(6,.d0:w),.d0\n" );
		printf( "	jmp	.pc@(2,.d0:w)\n" );
#endif

		/* output table */

#ifdef PORT68
		/*
		 * In the bug fix right above, the label has already been
		 * obtained.
		 * Steve Kramer 2/20/84
		 */
		printf( ".L%d = .\n", swlab);
#else
		printf( ".L%d = .\n", swlab=getlab() );
#endif

		for( i=1,j=p[1].sval; i<=n; ++j ){

			printf( "	.word	.L%d-.L%d\n", ( j == p[i].sval ) ?
				p[i++].slab : dlab, swlab );
			}

		if( p->slab< 0 ) deflab( dlab );
		return;

		}

#endif
	genbinary(p,1,n,0);
}
-- 
	--steve kramer
	{allegra,genrad,ihnp4,utzoo,philabs,uw-beaver}!linus!axiom!smk	(UUCP)
	linus!axiom!smk@mitre-bedford					(MIL)