0576641cae
Also add `static` and remove `register` in mach/proto/top/top.c. A static function is only in one file, so its function declaration may go in that file, instead of a header file.
198 lines
6.1 KiB
Plaintext
198 lines
6.1 KiB
Plaintext
|
|
/* PowerPC table for ACK target optimizer */
|
|
|
|
MAXOP 5;
|
|
LABEL_STARTER '.';
|
|
|
|
{
|
|
int not_using_sp(const char *);
|
|
int positive(const char *);
|
|
int lift(const char *);
|
|
int plus(const char *, const char *, char *);
|
|
}
|
|
|
|
%%;
|
|
|
|
L1, L2, L3, L4, L5 { not_using_sp(VAL) };
|
|
RNZ { strcmp(VAL, "r0") }; /* not r0 */
|
|
UP { positive(VAL) };
|
|
X, Y, Z { TRUE };
|
|
|
|
%%;
|
|
|
|
/* Whitespace is significant here! */
|
|
|
|
addi RNZ, RNZ, 0 -> ;
|
|
addis RNZ, RNZ, 0 -> ;
|
|
|
|
addi RNZ, RNZ, X : addi RNZ, RNZ, Y { plus(X, Y, Z) }
|
|
-> addi RNZ, RNZ, Z ;
|
|
|
|
/* Lower "addi sp, sp, UP" by lifting other instructions, looking for
|
|
* chances to merge or delete _addi_ instructions, and assuming that
|
|
* the code generator uses "sp" not "r1".
|
|
*/
|
|
addi sp, sp, UP : ANY L1 { lift(ANY) }
|
|
-> ANY L1 : addi sp, sp, UP ;
|
|
addi sp, sp, UP : ANY L1, L2 { lift(ANY) }
|
|
-> ANY L1, L2 : addi sp, sp, UP ;
|
|
addi sp, sp, UP : ANY L1, L2, L3 { lift(ANY) }
|
|
-> ANY L1, L2, L3 : addi sp, sp, UP ;
|
|
addi sp, sp, UP : ANY L1, L2, L3, L4 { lift(ANY) }
|
|
-> ANY L1, L2, L3, L4 : addi sp, sp, UP ;
|
|
addi sp, sp, UP : ANY L1, L2, L3, L4, L5 { lift(ANY) }
|
|
-> ANY L1, L2, L3, L4, L5 : addi sp, sp, UP ;
|
|
addi sp, sp, UP : lmw Y, L1 { Y[0]=='r' && atoi(Y+1)>1 }
|
|
-> lmw Y, L1 : addi sp, sp, UP ;
|
|
|
|
/* Merge _addi_ when popping from the stack. */
|
|
addi sp, sp, X : lwz L1, Y(sp) { plus(X, Y, Z) && Z[0]!='-' }
|
|
-> lwz L1, Z(sp) : addi sp, sp, X ;
|
|
addi sp, sp, X : lfs L1, Y(sp) { plus(X, Y, Z) && Z[0]!='-' }
|
|
-> lfs L1, Z(sp) : addi sp, sp, X ;
|
|
addi sp, sp, X : lfd L1, Y(sp) { plus(X, Y, Z) && Z[0]!='-' }
|
|
-> lfd L1, Z(sp) : addi sp, sp, X ;
|
|
|
|
/* Lower or delete _addi_ when pushing to the stack. */
|
|
addi sp, sp, X : stwu L1, Y(sp) { plus(X, Y, Z) && Z[0]!='-' }
|
|
-> stw L1, Z(sp) : addi sp, sp, Z ;
|
|
addi sp, sp, X : stfsu L1, Y(sp) { plus(X, Y, Z) && Z[0]!='-' }
|
|
-> stfs L1, Z(sp) : addi sp, sp, Z ;
|
|
addi sp, sp, X : stfdu L1, Y(sp) { plus(X, Y, Z) && Z[0]!='-' }
|
|
-> stfd L1, Z(sp) : addi sp, sp, Z ;
|
|
addi sp, sp, 4 : stfdu L1, -8(sp) -> stfdu L1, -4(sp) ;
|
|
|
|
/* Delete _addi_ when setting the stack pointer. */
|
|
addi sp, sp, X : addi sp, L1, Y -> addi sp, L1, Y ;
|
|
addi sp, sp, X : lwz sp, L1 -> lwz sp, L1 ;
|
|
|
|
or X, Y, Y -> mr X, Y ;
|
|
or. X, Y, Y -> mr. X, Y ;
|
|
|
|
mr X, X -> ;
|
|
fmr X, X -> ;
|
|
|
|
add X, Y, Z : mr. X, X -> add. X, Y, Z ;
|
|
and X, Y, Z : mr. X, X -> and. X, Y, Z ;
|
|
andc X, Y, Z : mr. X, X -> andc. X, Y, Z ;
|
|
divw X, Y, Z : mr. X, X -> divw. X, Y, Z ;
|
|
divwu X, Y, Z : mr. X, X -> divwu. X, Y, Z ;
|
|
extsb X, Y, Z : mr. X, X -> extsb. X, Y, Z ;
|
|
extsh X, Y, Z : mr. X, X -> extsh. X, Y, Z ;
|
|
eqv X, Y, Z : mr. X, X -> eqv. X, Y, Z ;
|
|
mullw X, Y, Z : mr. X, X -> mullw. X, Y, Z ;
|
|
nand X, Y, Z : mr. X, X -> nand. X, Y, Z ;
|
|
nor X, Y, Z : mr. X, X -> nor. X, Y, Z ;
|
|
or X, Y, Z : mr. X, X -> or. X, Y, Z ;
|
|
orc X, Y, Z : mr. X, X -> orc. X, Y, Z ;
|
|
slw X, Y, Z : mr. X, X -> slw. X, Y, Z ;
|
|
slwi X, Y, Z : mr. X, X -> slwi. X, Y, Z ;
|
|
subf X, Y, Z : mr. X, X -> subf. X, Y, Z ;
|
|
sraw X, Y, Z : mr. X, X -> sraw. X, Y, Z ;
|
|
srawi X, Y, Z : mr. X, X -> srawi. X, Y, Z ;
|
|
srw X, Y, Z : mr. X, X -> srw. X, Y, Z ;
|
|
srwi X, Y, Z : mr. X, X -> srwi. X, Y, Z ;
|
|
xor X, Y, Z : mr. X, X -> xor. X, Y, Z ;
|
|
|
|
b X : labdef X -> labdef X ;
|
|
|
|
/* IFFALSE=4, IFTRUE=12, ALWAYS=20 */
|
|
/* LT=0, GT=1, EQ=2, OV=3 */
|
|
|
|
%%;
|
|
|
|
/* Is it a word character? 0-9A-Za-z_ */
|
|
static int isword(char c) {
|
|
return
|
|
(c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') ||
|
|
(c >= 'a' && c <= 'z') || (c == '_');
|
|
}
|
|
|
|
/* Does operand _s_ not use the stack pointer? */
|
|
int not_using_sp(const char *s) {
|
|
int boundary;
|
|
|
|
boundary = 1;
|
|
while (*s) {
|
|
if (boundary &&
|
|
((s[0]=='s' && s[1]=='p') || (s[0]=='r' && s[1]=='1')) &&
|
|
!isword(s[2]))
|
|
return 0;
|
|
boundary = !isword(*s);
|
|
s++;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
int positive(const char *s) {
|
|
long n;
|
|
char *end;
|
|
|
|
n = strtol(s, &end, 10);
|
|
return *s != '\0' && *end == '\0' && n > 0;
|
|
}
|
|
|
|
|
|
/* Instructions to lift(), sorted in strcmp() order. These are from
|
|
* ../ncg/table, minus branch instructions.
|
|
*/
|
|
const char *liftables[] = {
|
|
"add", "add.", "addi",
|
|
"and", "andc", "andi.", "andis.",
|
|
"cmp", "cmpi", "cmpl", "cmpli",
|
|
"cmplw", "cmplwi", "cmpw", "cmpwi",
|
|
"divw", "divwu", "eqv", "extlwi", "extrwi", "extsb", "extsh",
|
|
"fadd", "fadds", "fcmpo", "fctiwz", "fdiv", "fdivs",
|
|
"fmr", "fmul", "fmuls", "fneg", "frsp", "fsub", "fsubs",
|
|
"lbz", "lbzx",
|
|
"lfd", "lfdu", "lfdx", "lfs", "lfsu", "lfsx",
|
|
"lha", "lhax", "lhz", "lhzx",
|
|
"li", "lis", "lwz", "lwzu", "lwzx",
|
|
"mfcr", "mfspr", "mr", "mr.", "mtspr", "mullw",
|
|
"nand", "neg", "nor", "or", "or.", "ori", "oris",
|
|
"rlwinm", "rlwnm", "rotlwi", "rotrwi",
|
|
"slw", "slwi", "sraw", "srawi", "srw", "srwi",
|
|
"stb", "stbx",
|
|
"stfd", "stfdu", "stfdx", "stfs", "stfsu", "stfsx",
|
|
"sth", "sthx", "stw", "stwx", "stwu",
|
|
"subf", "xor", "xori", "xoris",
|
|
};
|
|
|
|
static int liftcmp(const void *a, const void *b) {
|
|
return strcmp(*(const char **)a, *(const char **)b);
|
|
}
|
|
|
|
/* May we lift instruction _s_ above "addi SP, SP, X"? */
|
|
int lift(const char *s) {
|
|
return bsearch(&s, liftables,
|
|
sizeof(liftables) / sizeof(liftables[0]),
|
|
sizeof(liftables[0]), liftcmp) != NULL;
|
|
}
|
|
|
|
|
|
/* Does it fit a signed 16-bit integer? */
|
|
static int fits16(long l) {
|
|
return l >= -32768 && l <= 32767;
|
|
}
|
|
|
|
/* Tries sum = a + b with signed 16-bit integers. */
|
|
int plus(const char *a, const char *b, char *sum)
|
|
{
|
|
long la, lb, lsum;
|
|
char *end;
|
|
|
|
la = strtol(a, &end, 10);
|
|
if (*a == '\0' || *end != '\0' || !fits16(la))
|
|
return 0;
|
|
lb = strtol(b, &end, 10);
|
|
if (*b == '\0' || *end != '\0' || !fits16(lb))
|
|
return 0;
|
|
|
|
lsum = la + lb;
|
|
if (!fits16(lsum))
|
|
return 0;
|
|
snprintf(sum, 7, "%ld", lsum);
|
|
return 1;
|
|
}
|