/* 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; } }