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,"$037777777777") == 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;
 | |
| 	}
 | |
| }
 |