/* VAX descriptor table for ACK target optimizer, */ /* tunable constants-> */ MAXOP 4; MAXLINELEN 50; LABEL_STARTER 'I'; OPC_TERMINATOR ' '; %%; ZERO {strcmp(VAL,"$0") == 0}; ONE {strcmp(VAL,"$1") == 0}; M_ONE {strcmp(VAL,"$-1") == 0}; CONST {VAL[0] == '$'}; NUM,NUM1 {is_number(VAL)}; REG {is_register(VAL)}; SREG {is_scratchreg(VAL)}; LAB,LAB2 {VAL[0] == LABEL_STARTER}; A,B {no_side_effects(VAL) }; NO_INDEX {strchr(VAL, '[') == 0}; X,Y,LOG {TRUE}; %%; movab 1(X),X -> incl X; movab -1(X),X -> decl X; movzbw ZERO,X -> clrw X; movzbl ZERO,X -> clrl X; movb ZERO,X -> clrb X; movw ZERO,X -> clrw X; movl ZERO,X -> clrl X; cvtbw ZERO,X -> clrw X; cvtww ZERO,X -> clrw X; cvtbl ZERO,X -> clrl X; cvtwl ZERO,X -> clrl X; /* change 3-operand instructions to 2-operand instructions */ addw3 X,A,A -> addw2 X,A; addl3 X,A,A -> addl2 X,A; addf3 X,A,A -> addf2 X,A; addd3 X,A,A -> addd2 X,A; addw3 A,Y,A -> addw2 Y,A; addl3 A,Y,A -> addl2 Y,A; addf3 A,Y,A -> addf2 Y,A; addd3 A,Y,A -> addd2 Y,A; subw3 X,A,A -> subw2 X,A; subl3 X,A,A -> subl2 X,A; subf3 X,A,A -> subf2 X,A; subd3 X,A,A -> subd2 X,A; mulw3 X,A,A -> mulw2 X,A; mull3 X,A,A -> mull2 X,A; mulf3 X,A,A -> mulf2 X,A; muld3 X,A,A -> muld2 X,A; mulw3 A,Y,A -> mulw2 Y,A; mull3 A,Y,A -> mull2 Y,A; mulf3 A,Y,A -> mulf2 Y,A; muld3 A,Y,A -> muld2 Y,A; divw3 X,A,A -> divw2 X,A; divl3 X,A,A -> divl2 X,A; divf3 X,A,A -> divf2 X,A; divd3 X,A,A -> divd2 X,A; xorw3 X,A,A -> xorw2 X,A; xorl3 X,A,A -> xorl2 X,A; bisw3 X,A,A -> bisw2 X,A; bisl3 X,A,A -> bisl2 X,A; bisw3 A,Y,A -> bisw2 Y,A; bisl3 A,Y,A -> bisl2 Y,A; bicw3 X,A,A -> bicw2 X,A; bicl3 X,A,A -> bicl2 X,A; /* eliminate negative constants */ addw2 $-NUM,X -> subw2 $NUM,X; addl2 $-NUM,X -> subl2 $NUM,X; addw3 $-NUM,X,Y -> subw3 $NUM,X,Y; addl3 $-NUM,X,Y -> subl3 $NUM,X,Y; addw3 X,$-NUM,Y -> subw3 $NUM,X,Y; addl3 X,$-NUM,Y -> subl3 $NUM,X,Y; subw2 $-NUM,X -> addw2 $NUM,X; subl2 $-NUM,X -> addl2 $NUM,X; subw3 $-NUM,X,Y -> addw3 $NUM,X,Y; subl3 $-NUM,X,Y -> addl3 $NUM,X,Y; /* use special instructions */ addw2 ONE,X -> incw X; addl2 ONE,X -> incl X; subw2 ONE,X -> decw X; subl2 ONE,X -> decl X; addw2 M_ONE,X -> decw X; addl2 M_ONE,X -> decl X; subw2 M_ONE,X -> incw X; subl2 M_ONE,X -> incl X; /* careful! jbs has byte argument, jlbs has long argument, so be very careful with indexed mode */ bitw $NUM,NO_INDEX : jneq LAB {is_poweroftwo(NUM,LOG)}-> jbs $LOG,NO_INDEX,LAB; bitl $NUM,NO_INDEX : jneq LAB {is_poweroftwo(NUM,LOG)}-> jbs $LOG,NO_INDEX,LAB; bitw $NUM,NO_INDEX : jeql LAB {is_poweroftwo(NUM,LOG)}-> jbc $LOG,NO_INDEX,LAB; bitl $NUM,NO_INDEX : jeql LAB {is_poweroftwo(NUM,LOG)}-> jbc $LOG,NO_INDEX,LAB; bitw ONE,NO_INDEX : jneq LAB -> jlbs NO_INDEX,LAB; bitl ONE,A : jneq LAB -> jlbs A,LAB; bitw ONE,NO_INDEX : jneq LAB -> jlbc NO_INDEX,LAB; bitl ONE,A : jneq LAB -> jlbc A,LAB; ashl $-NUM,A,REG : bicw2 $~NUM1,REG {is_p2m1(NUM1,LOG)} -> extzv $NUM,$LOG,A,REG; ashl $-NUM,A,REG : bicl2 $~NUM1,REG {is_p2m1(NUM1,LOG)} -> extzv $NUM,$LOG,A,REG; /* stack optimizations */ movl (sp)+,X : pushl X -> movl (sp),X; tstw (sp)+ : movw X,-(sp) -> movw X,(sp); tstl (sp)+ : movl X,-(sp) -> movl X,(sp); tstw (sp)+ : clrw -(sp) -> clrw (sp); tstl (sp)+ : clrl -(sp) -> clrl (sp); tstw (sp)+ : movzbw X,-(sp) -> movzbw X,(sp); tstl (sp)+ : movzbl X,-(sp) -> movzbl X,(sp); tstw (sp)+ : cvtbw X,-(sp) -> cvtbw X,(sp); tstl (sp)+ : cvtbl X,-(sp) -> cvtbl X,(sp); tstw (sp)+ : tstw X -> movw X,(sp)+; tstl (sp)+ : tstl X -> movl X,(sp)+; tstl (sp)+ : pushl X -> movl X,(sp); tstl (sp)+ : pushab X -> movab X,(sp); tstl (sp)+ : pushaw X -> movaw X,(sp); tstl (sp)+ : pushal X -> moval X,(sp); tstl (sp)+ : pushaq X -> movaq X,(sp); /* push constants */ clrw -(sp) : movw $NUM,-(sp) -> pushl $NUM; clrw -(sp) : mnegw $NUM, -(sp) -> movzwl $-NUM,-(sp); clrw -(sp) : movw X,-(sp) -> movzwl X,-(sp); clrw -(sp) : cvtbw $NUM,-(sp) -> pushl $NUM; clrw -(sp) : cvtbw CONST,-(sp) -> movzwl CONST,-(sp); /* compare with zero */ cmpb X,ZERO -> tstb X; cmpw X,ZERO -> tstw X; cmpl X,ZERO -> tstl X; cmpb ZERO,X : jneq LAB -> tstb X: jneq LAB; cmpw ZERO,X : jneq LAB -> tstw X: jneq LAB; cmpl ZERO,X : jneq LAB -> tstl X: jneq LAB; cmpb ZERO,X : jeql LAB -> tstb X: jeql LAB; cmpw ZERO,X : jeql LAB -> tstw X: jeql LAB; cmpl ZERO,X : jeql LAB -> tstl X: jeql LAB; cmpb ZERO,X : jgtr LAB -> tstb X: jlss LAB; cmpw ZERO,X : jgtr LAB -> tstw X: jlss LAB; cmpl ZERO,X : jgtr LAB -> tstl X: jlss LAB; cmpb ZERO,X : jlss LAB -> tstb X: jgtr LAB; cmpw ZERO,X : jlss LAB -> tstw X: jgtr LAB; cmpl ZERO,X : jlss LAB -> tstl X: jgtr LAB; cmpb ZERO,X : jgeq LAB -> tstb X: jleq LAB; cmpw ZERO,X : jgeq LAB -> tstw X: jleq LAB; cmpl ZERO,X : jgeq LAB -> tstl X: jleq LAB; cmpb ZERO,X : jleq LAB -> tstb X: jgeq LAB; cmpw ZERO,X : jleq LAB -> tstw X: jgeq LAB; cmpl ZERO,X : jleq LAB -> tstl X: jgeq LAB; /* compare with -1 */ cmpw M_ONE,SREG : jeql LAB -> incw SREG : jeql LAB; cmpl M_ONE,SREG : jeql LAB -> incl SREG : jeql LAB; cmpw M_ONE,SREG : jneq LAB -> incw SREG : jneq LAB; cmpl M_ONE,SREG : jneq LAB -> incl SREG : jneq LAB; /* eliminate redundant tests */ movw X,A : tstw A -> movw X,A; movl X,A : tstl A -> movl X,A; movw A,X : tstw A -> movw A,X; movl A,X : tstl A -> movl A,X; /* skip over jumps */ jeql LAB : jbr LAB2 : labdef LAB -> jneq LAB2 : labdef LAB; jgeq LAB : jbr LAB2 : labdef LAB -> jlss LAB2 : labdef LAB; jgtr LAB : jbr LAB2 : labdef LAB -> jleq LAB2 : labdef LAB; jlss LAB : jbr LAB2 : labdef LAB -> jgeq LAB2 : labdef LAB; jleq LAB : jbr LAB2 : labdef LAB -> jgtr LAB2 : labdef LAB; jneq LAB : jbr LAB2 : labdef LAB -> jeql LAB2 : labdef LAB; /* Register propagation */ movl REG,A : ANY *A -> movl REG,A : ANY (REG); movl REG,A : ANY *A,X -> movl REG,A : ANY (REG),X; movl REG,A : ANY X,*A -> movl REG,A : ANY X,(REG); movl REG,A : ANY *A,X,Y -> movl REG,A : ANY (REG),X,Y; movl REG,A : ANY X,*A,Y -> movl REG,A : ANY X,(REG),Y; movl REG,A : ANY X,Y,*A -> movl REG,A : ANY X,Y,(REG); /* convert floats, doubles */ cvtlf X,A : cvtfd A,A -> cvtld X,A; cvtdf A,B : cvtfd B,A -> cvtdf A,B; %%; /* Auxiliary routines: */ int is_number(s) register char *s; { while (*s >= '0' && *s <= '9') s++; return *s == '\0'; } int is_poweroftwo(s,t) char *s,*t; { long arg, pow; register int i; arg = atol(s); pow = 1; i = 0; while (pow > 0) { if (pow == arg) { sprintf(t,"%d",i); return 1; } pow <<= 1; i++; } return 0; } int is_p2m1(s,t) char *s,*t; { long arg; char buf[MAXLINELEN]; arg = atol(s)+1; sprintf(buf,"%ld",arg); return is_poweroftwo(buf,t); } 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; { if (*s++ == 'r' && *s >= '0' && *s <= '9') { if (*s++ == '1' && (*s == '0' || *s == '1')) s++; return *s == '\0'; } return FALSE; } int is_scratchreg(s) register char *s; { return *s++ == 'r' && *s >= '0' && *s++ <= '3' && *s == '\0'; }