1986-11-24 21:45:03 +00:00
|
|
|
/* PDP-11 desciptor table for ACK target optimizer */
|
|
|
|
|
|
|
|
/* Tunable constants: */
|
|
|
|
|
|
|
|
MAXOP 2;
|
|
|
|
LABEL_STARTER 'I';
|
|
|
|
OPC_TERMINATOR ' ';
|
|
|
|
|
2019-10-24 18:08:52 +00:00
|
|
|
{
|
|
|
|
int no_side_effects(char *);
|
|
|
|
int is_register(char *);
|
|
|
|
int is_scratchreg(char *);
|
|
|
|
int carry_dead(char *);
|
|
|
|
}
|
|
|
|
|
1986-11-24 21:45:03 +00:00
|
|
|
%%;
|
|
|
|
|
|
|
|
/* 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 */
|
1987-05-18 15:54:52 +00:00
|
|
|
M_ONE {strcmp(VAL,"$-1") == 0 }; /* -1 */
|
1986-11-24 21:45:03 +00:00
|
|
|
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;
|
|
|
|
|
1988-04-11 09:38:31 +00:00
|
|
|
mov A,A -> tst A;
|
|
|
|
|
1986-11-24 21:45:03 +00:00
|
|
|
/* 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;
|
1988-04-11 09:38:31 +00:00
|
|
|
mov X,A : tst A -> mov X,A;
|
1986-11-24 21:45:03 +00:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
}
|