104 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
/* PDP-11 desciptor table for ACK target optimizer */
 | 
						|
 | 
						|
/* Tunable constants: */
 | 
						|
 | 
						|
MAXOP		2;
 | 
						|
LABEL_STARTER	'I';
 | 
						|
OPC_TERMINATOR	' ';
 | 
						|
 | 
						|
%%;
 | 
						|
 | 
						|
/* useful addressing modes: */
 | 
						|
 | 
						|
ZERO		{strcmp(VAL,"$00") == 0			};
 | 
						|
ONE		{strcmp(VAL,"$01") == 0			};
 | 
						|
CONST		{VAL[0] == '$'				};	/* constant */
 | 
						|
A,B		{no_side_effects(VAL)			};
 | 
						|
X,Y		{TRUE					};
 | 
						|
REG		{is_register(VAL)			};	/* register */
 | 
						|
SREG		{is_scratchreg(VAL)			};	/* scratch reg */
 | 
						|
M_ONE		{strcmp(VAL,"$-1") == 0			};	/* -1	*/
 | 
						|
LAB,L1,L2	{VAL[0] == 'I'				};	/* label */
 | 
						|
 | 
						|
%%;
 | 
						|
 | 
						|
/* optimization patterns: */
 | 
						|
 | 
						|
add ZERO,A  {carry_dead(REST)}	->	;
 | 
						|
add ONE, X  {carry_dead(REST)}	->	inc X;
 | 
						|
sub ONE, X  {carry_dead(REST)}	->	dec X;
 | 
						|
 | 
						|
/* tst-elimination */
 | 
						|
tst (sp)+ : tst X		->	mov X,(sp)+;
 | 
						|
tst (sp)+ : mov X,-(sp) 	->	mov X,(sp);
 | 
						|
mov A,X : tst A			->	mov A,X;
 | 
						|
 | 
						|
/* register subsumption */
 | 
						|
mov REG,A : ANY A,X 		->	mov REG,A : ANY REG,X;
 | 
						|
mov REG,A : ANY *A 		->	mov REG,A : ANY *REG;
 | 
						|
mov REG,A : ANY *A,X 		->	mov REG,A : ANY *REG,X;
 | 
						|
mov REG,A : ANY X,*A 		->	mov REG,A : ANY X,*REG;
 | 
						|
 | 
						|
/* compare with -1 */
 | 
						|
cmp SREG,M_ONE : jeq LAB	->	inc SREG : jeq LAB;
 | 
						|
cmp SREG,M_ONE : jne LAB	->	inc SREG : jne LAB;
 | 
						|
 | 
						|
/* skip over jump */
 | 
						|
jeq L1 : jbr L2: labdef L1	->	jne L2 : labdef L1;
 | 
						|
jge L1 : jbr L2: labdef L1	->	jlt L2 : labdef L1;
 | 
						|
jgt L1 : jbr L2: labdef L1	->	jle L2 : labdef L1;
 | 
						|
jlt L1 : jbr L2: labdef L1	->	jge L2 : labdef L1;
 | 
						|
jle L1 : jbr L2: labdef L1	->	jgt L2 : labdef L1;
 | 
						|
jne L1 : jbr L2: labdef L1	->	jeq L2 : labdef L1;
 | 
						|
 | 
						|
/* byte-test */
 | 
						|
clr SREG : bisb X,SREG : tst SREG : jeq LAB
 | 
						|
				->	tstb X : jeq LAB;
 | 
						|
clr SREG : bisb X,SREG : tst SREG : jne LAB
 | 
						|
				->	tstb X : jne LAB;
 | 
						|
 | 
						|
%%;
 | 
						|
 | 
						|
/* 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_register(s)
 | 
						|
	register char *s;
 | 
						|
{
 | 
						|
	return *s++ == 'r' && *s >= '0' && *s <= '5';
 | 
						|
}
 | 
						|
 | 
						|
int is_scratchreg(s)
 | 
						|
	register char *s;
 | 
						|
{
 | 
						|
	return *s++ == 'r' && (*s == '0' || *s == '1' || *s == '3');
 | 
						|
}
 | 
						|
 | 
						|
int carry_dead(s)
 | 
						|
	char *s;
 | 
						|
{
 | 
						|
	switch(*s++) {
 | 
						|
		case 'a':	/* adc and adcb */
 | 
						|
			return *s++ != 'd' || *s != 'c';
 | 
						|
		case 'b':	/* bcc, bcs, bhi, bhis, blo, blos */
 | 
						|
			return *s != 'c' && *s != 'h' &&
 | 
						|
				(*s++ != 'l' || *s != 'o');
 | 
						|
		case 's':	/* sbc and sbcb */
 | 
						|
			return *s++ != 'b' || *s != 'c';
 | 
						|
		default:
 | 
						|
			return TRUE;
 | 
						|
	}
 | 
						|
}
 |