178 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			178 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
 | 
						|
/* 68000 desciptor table for ACK target optimizer */
 | 
						|
 | 
						|
MAXOP 2;
 | 
						|
 | 
						|
%%;
 | 
						|
 | 
						|
/* useful addressing modes-> */
 | 
						|
 | 
						|
CONST		{VAL[0] == '#'			};	/* constant */
 | 
						|
NUM		{is_number(VAL)			};
 | 
						|
A,B		{no_side_effects(VAL)		};
 | 
						|
D		{VAL[0] != '#' && !is_areg(VAL)	};	/* not an addr. reg */
 | 
						|
X,Y		{TRUE				};
 | 
						|
DREG,DREG2 	{is_dreg(VAL)			};	 /* data register */
 | 
						|
DSREG		{is_dsreg(VAL)			};	/* data register */
 | 
						|
AREG		{is_areg(VAL)			};	/* addressregister */
 | 
						|
LAB,L1,L2 	{VAL[0] == 'I'			};	/* label */
 | 
						|
BITNO		{TRUE				};
 | 
						|
 | 
						|
%%;
 | 
						|
 | 
						|
/* optimization patterns-> */
 | 
						|
 | 
						|
/* rewriting rules */
 | 
						|
tst X					->	tst.w X ;
 | 
						|
cmp X,Y					->	cmp.w X,Y ;
 | 
						|
 | 
						|
/* special instructions */
 | 
						|
move.w #0,D				->	clr.w D ;
 | 
						|
move.l #0,D				->	clr.l D ;
 | 
						|
move.l #0,AREG				->	sub.l AREG,AREG ;
 | 
						|
 | 
						|
/* tst-elimination */
 | 
						|
add.l #2,sp : tst.w X {no_part("sp",X)}	->	move.w X,(sp)+ ;
 | 
						|
add.l #4,sp : tst.l D {no_part("sp",D)}	->	move.l D,(sp)+ ;
 | 
						|
add.l #2,sp : move.w X,-(sp)		->	move.w X,(sp) ;
 | 
						|
add.l #4,sp : move.l X,-(sp)		->	move.l X,(sp) ;
 | 
						|
move.w A,X : tst.w A			->	move.w A,X ;
 | 
						|
move.w X,A : tst.w A			->	move.w X,A ;
 | 
						|
move.l A,D : tst.l A {no_part(D,A)}	->	move.l A,D ;
 | 
						|
move.l X,D : tst.l D 			->	move.l X,D ;
 | 
						|
move.l A,AREG : tst.l A
 | 
						|
		{no_part(AREG,A)}	->	tst.l A: move.l A,AREG ;
 | 
						|
move.l X,AREG : move.l AREG,DREG :
 | 
						|
	tst.l DREG : beq LAB		->	move.l X,DREG :
 | 
						|
						move.l DREG,AREG: beq LAB ;
 | 
						|
move.l X,AREG : move.l AREG,DREG :
 | 
						|
	tst.l DREG : bne LAB		->	move.l X,DREG :
 | 
						|
						move.l DREG,AREG: bne LAB ;
 | 
						|
 | 
						|
/* redundant move */
 | 
						|
move.w DREG,DREG2 : move.w DREG2,DREG	->	move.w DREG,DREG2 ;
 | 
						|
 | 
						|
/* register subsumption */
 | 
						|
move.w DREG,A : ANY A,X
 | 
						|
	{reg_subs_allowed(ANY) &&
 | 
						|
	 !is_dreg(A)	}		->	move.w DREG,A : ANY DREG,X ;
 | 
						|
 | 
						|
/* change "cmp" into "add" or "sub" (possibly "addq" or "subq") */
 | 
						|
cmp.w #-NUM,DSREG : beq LAB		->	add.w #NUM,DSREG : beq LAB ;
 | 
						|
cmp.l #-NUM,DSREG : beq LAB		->	add.l #NUM,DSREG : beq LAB ;
 | 
						|
cmp.w #-NUM,DSREG : bne LAB		->	add.w #NUM,DSREG : bne LAB ;
 | 
						|
cmp.l #-NUM,DSREG : bne LAB		->	add.l #NUM,DSREG : bne LAB ;
 | 
						|
 | 
						|
cmp.w #NUM,DSREG : beq LAB		->	sub.w #NUM,DSREG : beq LAB ;
 | 
						|
cmp.l #NUM,DSREG : beq LAB		->	sub.l #NUM,DSREG : beq LAB ;
 | 
						|
cmp.w #NUM,DSREG : bne LAB		->	sub.w #NUM,DSREG : bne LAB ;
 | 
						|
cmp.l #NUM,DSREG : bne LAB		->	sub.l #NUM,DSREG : bne LAB ;
 | 
						|
 | 
						|
/* addq and subq */
 | 
						|
lea -1(AREG),AREG			->	sub.l #1,AREG ;
 | 
						|
add.w #-NUM,X				->	sub.w #NUM,X ;
 | 
						|
add.l #-NUM,X				->	sub.l #NUM,X ;
 | 
						|
sub.w #-NUM,X				->	add.w #NUM,X ;
 | 
						|
sub.l #-NUM,X				->	add.l #NUM,X ;
 | 
						|
 | 
						|
/* bit-test instruction */
 | 
						|
move.b X,DSREG : and.w #NUM,DSREG : 
 | 
						|
 tst.w DSREG : beq LAB 
 | 
						|
 { bitno(NUM,BITNO)}			->	btst #BITNO,X ;
 | 
						|
 | 
						|
/* skip over jump */
 | 
						|
beq L1 : bra L2: labdef L1		->	bne L2 : labdef L1 ;
 | 
						|
bge L1 : bra L2: labdef L1		->	blt L2 : labdef L1 ;
 | 
						|
bgt L1 : bra L2: labdef L1		->	ble L2 : labdef L1 ;
 | 
						|
blt L1 : bra L2: labdef L1		->	bge L2 : labdef L1 ;
 | 
						|
ble L1 : bra L2: labdef L1		->	bgt L2 : labdef L1 ;
 | 
						|
bne L1 : bra L2: labdef L1		->	beq L2 : labdef L1 ;
 | 
						|
 | 
						|
%%;
 | 
						|
 | 
						|
/* auxiliary routines: */
 | 
						|
 | 
						|
int no_side_effects(s)
 | 
						|
	register char *s;
 | 
						|
{
 | 
						|
 | 
						|
	for(;;) {
 | 
						|
		switch(*s++) {
 | 
						|
			case '\0': return TRUE;
 | 
						|
			case '-':  if (*s == '(') return FALSE; break;
 | 
						|
			case ')':  if (*s == '+') return FALSE; break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	/* NOTREACHED */
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int is_dreg(s)
 | 
						|
	register char *s;
 | 
						|
{
 | 
						|
	return *s++ == 'd' && *s >= '0' && *s++ <= '7' && *s == '\0';
 | 
						|
}
 | 
						|
 | 
						|
int is_dsreg(s)
 | 
						|
	register char *s;
 | 
						|
{
 | 
						|
	return *s++ == 'd' && *s >= '0' && *s++ <= '2' && *s == '\0';
 | 
						|
}
 | 
						|
 | 
						|
int is_areg(s)
 | 
						|
	register char *s;
 | 
						|
{
 | 
						|
	return *s++ == 'a' && *s >= '0' && *s++ <= '6' && *s == '\0';
 | 
						|
}
 | 
						|
 | 
						|
int no_part(part,s)
 | 
						|
	char *part,*s;
 | 
						|
{
 | 
						|
	char *tmp1,*tmp2;
 | 
						|
 | 
						|
	while (*s != '\0') {
 | 
						|
		if (*s == *part) {
 | 
						|
			for (tmp1=part,tmp2=s;;  tmp1++,tmp2++) {
 | 
						|
				if (*tmp1== '\0') return FALSE;
 | 
						|
				if (*tmp1 != *tmp2) break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		s++;
 | 
						|
	}
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* see if register subsumption is allowed for instruction Opc */
 | 
						|
 | 
						|
int reg_subs_allowed(opc)
 | 
						|
	char *opc;
 | 
						|
{
 | 
						|
	return strcmp(opc,"cmp") != 0 && strcmp(opc,"lea") != 0;
 | 
						|
}
 | 
						|
 | 
						|
int is_number(s)
 | 
						|
	register char *s;
 | 
						|
{
 | 
						|
	while (*s != '\0') {
 | 
						|
		if (*s < '0' || *s++ > '9') return FALSE;
 | 
						|
	}
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
int bitno(s,no)
 | 
						|
	char *s,*no;
 | 
						|
{
 | 
						|
	int n,i;
 | 
						|
 | 
						|
	n = atoi(s);
 | 
						|
	if (n < 1 || n > 128) return FALSE;
 | 
						|
	for (i = 0; i < 8 ; i++) {
 | 
						|
		if (n == 1) {
 | 
						|
			sprintf(no,"%d",i);
 | 
						|
			return TRUE;
 | 
						|
		}
 | 
						|
		n >>= 1;
 | 
						|
	}
 | 
						|
	return FALSE;
 | 
						|
}
 |