ack/mach/powerpc/top/table
George Koehler 51e34acab1 Add a syntax to declare functions in a top table
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.
2019-10-30 18:36:55 -04:00

197 lines
6.1 KiB
Text

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