51e34acab1
Use the new syntax in the mips, pdp, powerpc tables to declare functions before calling them. These declarations prevent compiler warnings about implicitly declaring functions. They also provide prototypes of the function parameters. Also fix a warning in the powerpc table: use `bsearch(...) != NULL` to avoid converting the pointer from bsearch() to an int. The syntax for topgen is a block `{...}` among the parameters in the top table. It looks like the syntax of LLgen, but topgen doesn't allow nested blocks, so declarations like `struct whatever {...};` don't work. The token OPEN_BRACKET that begins a declaration_block doesn't conflict with the LETTER that begins a parameter_line or the '%' that begins a separator. Because a block writes a #line command to gen.h, a parameter line now also writes a #line command to gen.h, so it doesn't get a wrong line number from a previous block.
115 lines
2.5 KiB
Plaintext
115 lines
2.5 KiB
Plaintext
/* PDP-11 desciptor table for ACK target optimizer */
|
|
|
|
/* Tunable constants: */
|
|
|
|
MAXOP 2;
|
|
LABEL_STARTER 'I';
|
|
OPC_TERMINATOR ' ';
|
|
|
|
{
|
|
int no_side_effects(char *);
|
|
int is_register(char *);
|
|
int is_scratchreg(char *);
|
|
int carry_dead(char *);
|
|
}
|
|
|
|
%%;
|
|
|
|
/* 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;
|
|
}
|
|
}
|