ack/mach/pdp/top/table
1988-04-11 09:38:31 +00:00

108 lines
2.4 KiB
Plaintext

/* 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;
mov A,A -> tst A;
/* 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;
mov X,A : tst A -> mov X,A;
/* 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;
}
}