1167 lines
25 KiB
C
1167 lines
25 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include "em_spec.h"
|
|
#include "em_flag.h"
|
|
#include "em_reg.h"
|
|
|
|
#define EXTERN extern
|
|
#include "booth.h"
|
|
#undef EXTERN
|
|
|
|
/* Forward local declarations. */
|
|
static void debug(void);
|
|
static void verbose(void);
|
|
static void outregvar(void);
|
|
static void finishio(void);
|
|
static void inittables(void);
|
|
static void initio(void);
|
|
static int eqregclass(int r1, int r2);
|
|
static void compueq(void);
|
|
|
|
static int want_verbose = 0;
|
|
|
|
|
|
char *myalloc(int n)
|
|
{
|
|
register char *p;
|
|
|
|
p = malloc((unsigned) n);
|
|
if (p == 0)
|
|
{
|
|
yyerror("Out of core");
|
|
exit(1);
|
|
}
|
|
return (p);
|
|
}
|
|
|
|
void tstint(expr_t e)
|
|
{
|
|
|
|
if (e.expr_typ != TYPINT)
|
|
yyerror("Must be integer expression");
|
|
}
|
|
|
|
void tstbool(expr_t e)
|
|
{
|
|
|
|
if (e.expr_typ != TYPBOOL)
|
|
yyerror("Must be boolean expression");
|
|
}
|
|
|
|
int structsize(register list2 s)
|
|
{
|
|
register list1 l;
|
|
register int sum;
|
|
|
|
sum = 0;
|
|
while (s != 0)
|
|
{
|
|
l = s->l2list->l1next;
|
|
while (l != 0)
|
|
{
|
|
sum++;
|
|
l = l->l1next;
|
|
}
|
|
s = s->l2next;
|
|
}
|
|
return (sum);
|
|
}
|
|
|
|
static int isasc(int c)
|
|
{
|
|
if ((c >= 0 && c <= 0177))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
list2 lookstruct(list2 ll)
|
|
{
|
|
list3 l3;
|
|
list2 l21, l22;
|
|
list1 l11, l12;
|
|
|
|
for (l3 = structpool; l3 != 0; l3 = l3->l3next)
|
|
{
|
|
for (l21 = l3->l3list, l22 = ll; l21 != 0 && l22 != 0; l21 =
|
|
l21->l2next, l22 = l22->l2next)
|
|
{
|
|
for (l11 = l21->l2list, l12 = l22->l2list;
|
|
l11 != 0 && l12 != 0
|
|
&& strcmp(l11->l1name, l12->l1name) == 0;
|
|
l11 = l11->l1next, l12 = l12->l1next)
|
|
;
|
|
if (l11 != 0 || l12 != 0)
|
|
goto contin;
|
|
}
|
|
if (l21 == 0 && l22 == 0)
|
|
return (l3->l3list);
|
|
contin: ;
|
|
}
|
|
l3 = (list3) myalloc(sizeof(struct list3str));
|
|
l3->l3next = structpool;
|
|
l3->l3list = ll;
|
|
structpool = l3;
|
|
return (ll);
|
|
}
|
|
|
|
int instno(inst_t inst)
|
|
{
|
|
register int i, j;
|
|
|
|
for (i = 1; i < narinstance; i++)
|
|
{
|
|
if (arinstance[i].in_which != inst.in_which)
|
|
continue;
|
|
for (j = 0; j < TOKENSIZE; j++)
|
|
if (arinstance[i].in_info[j] != inst.in_info[j])
|
|
goto cont;
|
|
return (i);
|
|
cont: ;
|
|
}
|
|
chktabsiz(narinstance, MAXINSTANCE, "Instance table");
|
|
arinstance[narinstance] = inst;
|
|
return (narinstance++);
|
|
}
|
|
|
|
string scopy(string s)
|
|
{
|
|
register string t;
|
|
|
|
t = (char *) myalloc(strlen(s) + 1);
|
|
strcpy(t, s);
|
|
return (t);
|
|
}
|
|
|
|
int strlookup(string s)
|
|
{
|
|
register int i;
|
|
|
|
for (i = 0; i < ncodestrings; i++)
|
|
if (strcmp(s, codestrings[i]) == 0)
|
|
return (i);
|
|
chktabsiz(ncodestrings, MAXSTRINGS, "string table");
|
|
codestrings[ncodestrings] = scopy(s);
|
|
return (ncodestrings++);
|
|
}
|
|
|
|
int stringno(register string s)
|
|
{
|
|
char buf[256];
|
|
register char *p = buf;
|
|
|
|
while (*s != 0)
|
|
switch (*s)
|
|
{
|
|
default:
|
|
*p++ = *s++;
|
|
continue;
|
|
case '$':
|
|
s++;
|
|
switch (*s)
|
|
{
|
|
default:
|
|
yyerror("Bad character after $ in codestring");
|
|
case '$':
|
|
*p++ = *s++;
|
|
continue;
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
*p++ = argtyp(patmnem[*s - '0']) == TYPINT ?
|
|
PR_EMINT : PR_EMSTR;
|
|
*p++ = *s++ - '0';
|
|
continue;
|
|
}
|
|
case '%':
|
|
s++;
|
|
if (*s != '[')
|
|
{
|
|
if (*s == '%')
|
|
{
|
|
*p++ = *s++;
|
|
continue;
|
|
}
|
|
else
|
|
yyerror("Bad character following %% in codestring");
|
|
}
|
|
else
|
|
s++;
|
|
if (isdigit(*s))
|
|
{
|
|
int num;
|
|
num = *s++ - '0';
|
|
if (num < 1 || num > tokpatlen)
|
|
yyerror("Number within %[] out of range");
|
|
if (*s == ']')
|
|
{
|
|
s++;
|
|
*p++ = PR_TOK;
|
|
*p++ = num;
|
|
}
|
|
else if (*s++ != '.')
|
|
yyerror(
|
|
"Bad character following %%[digit in codestring");
|
|
else
|
|
{
|
|
char field[256];
|
|
register char *f = field;
|
|
int type, offset;
|
|
|
|
while (*s != ']' && *s != 0)
|
|
*f++ = *s++;
|
|
*f++ = 0;
|
|
if (*s != ']')
|
|
yyerror(
|
|
"Unterminated %[] construction in codestring");
|
|
else
|
|
s++;
|
|
if (isdigit(field[0]))
|
|
{
|
|
chkregexp(pattokexp[num]);
|
|
*p++ = PR_SUBREG;
|
|
*p++ = num;
|
|
*p++ = atoi(field);
|
|
}
|
|
else
|
|
{
|
|
offset = findstructel(pattokexp[num], field, &type);
|
|
*p++ = PR_TOKFLD;
|
|
*p++ = num;
|
|
*p++ = offset;
|
|
}
|
|
}
|
|
}
|
|
else if (*s >= 'a' && *s < 'a' + nallreg)
|
|
{
|
|
int reg, subreg;
|
|
reg = *s++ - 'a' + 1;
|
|
if (*s == ']')
|
|
subreg = 255;
|
|
else
|
|
{
|
|
if (*s != '.')
|
|
yyerror(
|
|
"Bad character following %%[x in codestring");
|
|
s++;
|
|
if (!isdigit(*s))
|
|
yyerror(
|
|
"Bad character following %%[x. in codestring");
|
|
subreg = *s - '0';
|
|
s++;
|
|
if (*s != ']')
|
|
yyerror(
|
|
"Bad character following %%[x.y in codestring");
|
|
}
|
|
s++;
|
|
*p++ = PR_ALLREG;
|
|
*p++ = reg;
|
|
*p++ = subreg;
|
|
}
|
|
else
|
|
yyerror("Bad character following %%[ in codestring");
|
|
}
|
|
*p++ = 0;
|
|
return (strlookup(buf));
|
|
}
|
|
|
|
void tabovf(string tablename)
|
|
{
|
|
char buf[256];
|
|
|
|
sprintf(buf, "%s overflow", tablename);
|
|
yyerror(buf);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
|
|
while (--argc)
|
|
{
|
|
++argv;
|
|
if (argv[0][0] == '-')
|
|
{
|
|
switch (argv[0][1])
|
|
{
|
|
case 'h':
|
|
hname = &argv[0][2];
|
|
break;
|
|
case 'c':
|
|
cname = &argv[0][2];
|
|
break;
|
|
case 'v':
|
|
want_verbose = 1;
|
|
break;
|
|
default:
|
|
fprintf(stderr, "Bad flag %s\n", argv[0]);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
iname = argv[0];
|
|
}
|
|
}
|
|
inithash();
|
|
initio();
|
|
inittables();
|
|
yyparse();
|
|
if (nerrors == 0)
|
|
{
|
|
compueq();
|
|
hashpatterns();
|
|
finishio();
|
|
if (want_verbose)
|
|
verbose();
|
|
}
|
|
if (want_verbose)
|
|
debug();
|
|
exit(nerrors);
|
|
}
|
|
|
|
int lookup(int comm, int operator, int lnode, int rnode)
|
|
{
|
|
register node_p p;
|
|
|
|
for (p = nodes + 1; p < lastnode; p++)
|
|
{
|
|
if (p->ex_operator != operator)
|
|
continue;
|
|
if (!((p->ex_lnode == lnode && p->ex_rnode == rnode)
|
|
|| (comm && p->ex_lnode == rnode && p->ex_rnode == lnode)))
|
|
continue;
|
|
return (p - nodes);
|
|
}
|
|
if (lastnode >= &nodes[MAXNODES])
|
|
yyerror("node table overflow");
|
|
lastnode++;
|
|
p->ex_operator = operator;
|
|
p->ex_lnode = lnode;
|
|
p->ex_rnode = rnode;
|
|
return (p - nodes);
|
|
}
|
|
|
|
static void compueq(void)
|
|
{
|
|
register int i, j;
|
|
|
|
for (i = 1; i < nmachregs; i++)
|
|
{
|
|
for (j = 1; j < i; j++)
|
|
if (eqregclass(i, j))
|
|
{
|
|
stregclass[i] = stregclass[j];
|
|
break;
|
|
}
|
|
if (j == i)
|
|
stregclass[i] = nregclasses++;
|
|
}
|
|
}
|
|
|
|
static int eqregclass(int r1, int r2)
|
|
{
|
|
register reginfo rp1, rp2;
|
|
register int i;
|
|
short regbits[(MAXREGS + 15) >> 4];
|
|
int member;
|
|
|
|
rp1 = machregs[r1];
|
|
rp2 = machregs[r2];
|
|
for (i = 0; i < ((nprops + 15) >> 4); i++)
|
|
if (rp1->rprop[i] != rp2->rprop[i])
|
|
return (0);
|
|
for (i = 0; i < ((MAXREGS + 15) >> 4); i++)
|
|
regbits[i] = 0;
|
|
for (i = 0; i < maxmembers; i++)
|
|
{
|
|
if ((member = rp1->rmembers[i]))
|
|
regbits[member >> 4] |= (1 << (member & 017));
|
|
}
|
|
for (i = 0; i < maxmembers; i++)
|
|
{
|
|
member = rp2->rmembers[i];
|
|
if (regbits[member >> 4] & (1 << (member & 017)))
|
|
return (0);
|
|
}
|
|
return (1);
|
|
}
|
|
|
|
unsigned hash(register string name)
|
|
{
|
|
register unsigned sum;
|
|
register int i;
|
|
|
|
for (sum = i = 0; *name; i += 3)
|
|
sum ^= (*name++) << (i & 07);
|
|
return (sum);
|
|
}
|
|
|
|
ident_p ilookup(string name, int enterf)
|
|
{
|
|
register ident_p p, *pp;
|
|
|
|
pp = &identtab[hash(name) % ITABSIZE];
|
|
while (*pp != 0)
|
|
{
|
|
if (strcmp((*pp)->i_name, name) == 0)
|
|
{
|
|
if (enterf != ENTER)
|
|
return (*pp);
|
|
else
|
|
yyerror("Multiply defined symbol");
|
|
}
|
|
pp = &(*pp)->i_next;
|
|
}
|
|
if (enterf == LOOKUP)
|
|
yyerror("Undefined symbol");
|
|
if (enterf == JUSTLOOKING)
|
|
return (0);
|
|
p = *pp = (ident_p) myalloc(sizeof(ident_t));
|
|
p->i_name = name;
|
|
p->i_next = 0;
|
|
p->i_type = 0;
|
|
return (p);
|
|
}
|
|
|
|
static void initio(void)
|
|
{
|
|
|
|
if (iname != 0 && freopen(iname, "r", stdin) == NULL)
|
|
{
|
|
fprintf(stderr, "Can't open %s\n", iname);
|
|
exit(-1);
|
|
}
|
|
if ((cfile = fopen(cname, "w")) == NULL)
|
|
{
|
|
fprintf(stderr, "Can't create %s\n", cname);
|
|
exit(-1);
|
|
}
|
|
if ((hfile = fopen(hname, "w")) == NULL)
|
|
{
|
|
fprintf(stderr, "Can't create %s\n", hname);
|
|
exit(-1);
|
|
}
|
|
fprintf(cfile, "#include \"param.h\"\n");
|
|
fprintf(cfile, "#include \"tables.h\"\n");
|
|
fprintf(cfile, "#include \"types.h\"\n");
|
|
fprintf(cfile, "#include <cg_pattern.h>\n");
|
|
fprintf(cfile, "#include \"data.h\"\n");
|
|
fprintf(cfile, "\nbyte coderules[] = {\n");
|
|
patbyte(0);
|
|
}
|
|
|
|
int exprlookup(set_t sett)
|
|
{
|
|
register int i, j, ok;
|
|
|
|
for (i = 0; i < nmachsets; i++)
|
|
{
|
|
ok = (sett.set_size == machsets[i].set_size);
|
|
for (j = 0; j < SETSIZE; j++)
|
|
{
|
|
if (sett.set_val[j] == machsets[i].set_val[j])
|
|
continue;
|
|
ok = 0;
|
|
break;
|
|
}
|
|
if (ok)
|
|
return (i);
|
|
}
|
|
chktabsiz(nmachsets, MAXSETS, "Expression table");
|
|
machsets[nmachsets] = sett;
|
|
return (nmachsets++);
|
|
}
|
|
|
|
static void inittables(void)
|
|
{
|
|
register reginfo r;
|
|
register int i;
|
|
inst_t inst;
|
|
set_t sett;
|
|
|
|
nodes[0].ex_operator = EX_CON;
|
|
nodes[0].ex_lnode = 0;
|
|
nodes[0].ex_rnode = 0;
|
|
cocopropno = nprops++;
|
|
r = (reginfo) myalloc(sizeof(struct reginfo));
|
|
r->rname = "cc reg";
|
|
r->rrepr = "CC";
|
|
r->rsize = -1;
|
|
r->rregvar = -1;
|
|
for (i = 0; i < MAXMEMBERS; i++)
|
|
r->rmembers[i] = 0;
|
|
for (i = 0; i < PROPSETSIZE; i++)
|
|
r->rprop[i] = 0;
|
|
r->rprop[cocopropno >> 4] |= (1 << (cocopropno & 017));
|
|
chktabsiz(nmachregs, MAXREGS, "Register table");
|
|
machregs[nmachregs++] = r;
|
|
inst.in_which = IN_RIDENT;
|
|
inst.in_info[0] = nmachregs - 1;
|
|
for (i = 1; i < TOKENSIZE; i++)
|
|
inst.in_info[i] = 0;
|
|
ccinstanceno = instno(inst);
|
|
ccregexpr = lookup(0, EX_REG, nmachregs - 1, 0);
|
|
sett.set_size = 0;
|
|
for (i = 0; i < SETSIZE; i++)
|
|
sett.set_val[i] = 0;
|
|
sett.set_val[nmachregs >> 4] |= (01 << (nmachregs & 017));
|
|
cocosetno = exprlookup(sett);
|
|
}
|
|
|
|
static void outregs(void)
|
|
{
|
|
register int i, j, k;
|
|
static short rset[(MAXREGS + 15) >> 4];
|
|
int t, ready;
|
|
|
|
fprintf(cfile, "char stregclass[] = {\n");
|
|
for (i = 0; i < nmachregs; i++)
|
|
fprintf(cfile, "\t%d,\n", stregclass[i]);
|
|
fprintf(cfile, "};\n\nstruct reginfo machregs[] = {\n{0},\n");
|
|
for (i = 1; i < nmachregs; i++)
|
|
{
|
|
fprintf(cfile, "{%d,%d", strlookup(machregs[i]->rrepr),
|
|
machregs[i]->rsize);
|
|
if (maxmembers != 0)
|
|
{
|
|
fprintf(cfile, ",{");
|
|
for (j = 0; j < maxmembers; j++)
|
|
fprintf(cfile, "%d,", machregs[i]->rmembers[j]);
|
|
/* now compute and print set of registers
|
|
* that clashes with this register.
|
|
* A register clashes with al its children (and theirs)
|
|
* and with all their parents.
|
|
*/
|
|
for (j = 0; j < ((MAXREGS + 15) >> 4); j++)
|
|
rset[j] = 0;
|
|
rset[i >> 4] |= (1 << (i & 017));
|
|
do
|
|
{
|
|
ready = 1;
|
|
for (j = 1; j < nmachregs; j++)
|
|
if (rset[j >> 4] & (1 << (j & 017)))
|
|
for (k = 0; k < maxmembers; k++)
|
|
if ((t = machregs[j]->rmembers[k]) != 0)
|
|
{
|
|
if ((rset[t >> 4] & (1 << (t & 017))) == 0)
|
|
ready = 0;
|
|
rset[t >> 4] |= (1 << (t & 017));
|
|
}
|
|
} while (!ready);
|
|
do
|
|
{
|
|
ready = 1;
|
|
for (j = 1; j < nmachregs; j++)
|
|
for (k = 0; k < maxmembers; k++)
|
|
if ((t = machregs[j]->rmembers[k]) != 0)
|
|
if (rset[t >> 4] & (1 << (t & 017)))
|
|
{
|
|
if ((rset[j >> 4] & (1 << (j & 017))) == 0)
|
|
ready = 0;
|
|
rset[j >> 4] |= (1 << (j & 017));
|
|
}
|
|
} while (!ready);
|
|
fprintf(cfile, "},{");
|
|
for (j = 0; j < ((nmachregs + 15) >> 4); j++)
|
|
fprintf(cfile, "%d,", rset[j]);
|
|
fprintf(cfile, "}");
|
|
}
|
|
if (machregs[i]->rregvar >= 0)
|
|
fprintf(cfile, ",1");
|
|
fprintf(cfile, "},\n");
|
|
}
|
|
fprintf(cfile, "};\n\n");
|
|
}
|
|
|
|
static void finishio(void)
|
|
{
|
|
register int i;
|
|
register node_p np;
|
|
int j;
|
|
int setsize;
|
|
register move_p mp;
|
|
|
|
fprintf(cfile, "};\n\n");
|
|
if (wsize > 0)
|
|
fprintf(hfile, "#define TEM_WSIZE %d\n", wsize);
|
|
else
|
|
yyerror("Wordsize undefined");
|
|
if (psize > 0)
|
|
fprintf(hfile, "#define TEM_PSIZE %d\n", psize);
|
|
else
|
|
yyerror("Pointersize undefined");
|
|
if (bsize >= 0)
|
|
fprintf(hfile, "#define TEM_BSIZE %d\n", bsize);
|
|
else
|
|
yyerror("EM_BSIZE undefined");
|
|
if (fmt != 0)
|
|
fprintf(hfile, "#define WRD_FMT \"%s\"\n", fmt);
|
|
fprintf(hfile, "#define MAXALLREG %d\n", maxallreg);
|
|
setsize = (nmachregs + 1 + nmachtokens + 15) >> 4;
|
|
fprintf(hfile, "#define SETSIZE %d\n", setsize);
|
|
fprintf(hfile, "#define NPROPS %d\n", nprops);
|
|
fprintf(hfile, "#define NREGS %d\n", nmachregs);
|
|
fprintf(hfile, "#define REGSETSIZE %d\n", (nmachregs + 15) >> 4);
|
|
fprintf(hfile, "#define TOKENSIZE %d\n", maxtokensize);
|
|
fprintf(hfile, "#define MAXMEMBERS %d\n", maxmembers);
|
|
fprintf(hfile, "#define LONGESTPATTERN %d\n", maxempatlen);
|
|
fprintf(hfile, "#define MAXRULE %d\n", maxrule);
|
|
fprintf(hfile, "#define NMOVES %d\n", nmoves);
|
|
fprintf(hfile, "#define NC1 %d\n", nc1);
|
|
if (nc2)
|
|
{
|
|
assert(maxsplit != 0);
|
|
fprintf(hfile, "#define NC2 %d\n", nc2);
|
|
fprintf(hfile, "#define MAXSPLIT %d\n", maxsplit);
|
|
}
|
|
fprintf(hfile, "#define NC3 %d\n", nc3);
|
|
outregs();
|
|
fprintf(cfile, "tkdef_t tokens[] = {\n");
|
|
for (i = 0; i < nmachtokens; i++)
|
|
{
|
|
fprintf(cfile, "{%d,{%d,%d},{", machtokens[i].t_size,
|
|
machtokens[i].t_cost.c_size, machtokens[i].t_cost.c_time);
|
|
for (j = 0; j < maxtokensize; j++)
|
|
fprintf(cfile, "%d,", machtokens[i].t_fields[j].t_type);
|
|
fprintf(cfile, "},%d},\n", machtokens[i].t_format);
|
|
}
|
|
fprintf(cfile, "};\n\nnode_t enodes[] = {\n");
|
|
for (np = nodes; np < lastnode; np++)
|
|
fprintf(cfile, "{%d,%d,%d},\n", np->ex_operator, np->ex_lnode,
|
|
np->ex_rnode);
|
|
fprintf(cfile, "};\n\nstring codestrings[] = {\n");
|
|
for (i = 0; i < ncodestrings; i++)
|
|
{
|
|
register char *p;
|
|
p = codestrings[i];
|
|
fprintf(cfile, "\t\"");
|
|
while (*p)
|
|
{
|
|
register int c = (*p) & BMASK;
|
|
if (!isasc(c) || iscntrl(c))
|
|
{
|
|
/* The next line used to have (c>>6)&03,
|
|
but this triggered a bug in GCC 2.4.5
|
|
on SPARC.
|
|
*/
|
|
fprintf(cfile, "\\%c%c%c", ((*p >> 6) & 03) + '0',
|
|
((c >> 3) & 07) + '0', (c & 07) + '0');
|
|
}
|
|
else
|
|
putc(c, cfile);
|
|
p++;
|
|
}
|
|
fprintf(cfile, "\",\n");
|
|
}
|
|
fprintf(cfile, "};\n\nset_t machsets[] = {\n");
|
|
for (i = 0; i < nmachsets; i++)
|
|
{
|
|
fprintf(cfile, "{%d,{", machsets[i].set_size);
|
|
for (j = 0; j < setsize; j++)
|
|
fprintf(cfile, "0%o,", machsets[i].set_val[j] & 0xFFFF);
|
|
fprintf(cfile, "}},\n");
|
|
}
|
|
fprintf(cfile, "};\n\ninst_t tokeninstances[] = {\n");
|
|
for (i = 0; i < narinstance; i++)
|
|
{
|
|
fprintf(cfile, "{ %d, {", arinstance[i].in_which);
|
|
for (j = 0; j <= maxtokensize; j++)
|
|
fprintf(cfile, "%d,", arinstance[i].in_info[j]);
|
|
fprintf(cfile, "}},\n");
|
|
}
|
|
fprintf(cfile, "};\n\nmove_t moves[] = {\n");
|
|
for (i = 0; i < nmoves; i++)
|
|
{
|
|
mp = &machmoves[i];
|
|
fprintf(cfile, "{%d,%d,%d,%d,%d,{%d,%d}},\n", mp->m_set1, mp->m_expr1,
|
|
mp->m_set2, mp->m_expr2, mp->m_cindex, mp->m_cost.c_size,
|
|
mp->m_cost.c_time);
|
|
}
|
|
fprintf(cfile, "};\n\nbyte pattern[] = {\n");
|
|
for (i = 0; i < npatbytes; i++)
|
|
{
|
|
fprintf(cfile, "%3d,", pattern[i] & BMASK);
|
|
if ((i % 10) == 9)
|
|
fprintf(cfile, "\n");
|
|
}
|
|
fprintf(cfile, "\n};\n\nint pathash[256] = {\n");
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
fprintf(cfile, "%6d,", pathash[i]);
|
|
if ((i & 07) == 07)
|
|
fprintf(cfile, "\n");
|
|
}
|
|
fprintf(cfile, "};\n\nc1_t c1coercs[] = {\n");
|
|
for (i = 0; i < nc1; i++)
|
|
fprintf(cfile, "{%d,%d,%d,%d,{%d,%d}},\n", c1coercs[i].c1_texpno,
|
|
c1coercs[i].c1_expr, c1coercs[i].c1_prop, c1coercs[i].c1_codep,
|
|
c1coercs[i].c1_cost.c_size, c1coercs[i].c1_cost.c_time);
|
|
if (nc2)
|
|
fprintf(cfile, "};\n\nc2_t c2coercs[] = {\n");
|
|
for (i = 0; i < nc2; i++)
|
|
{
|
|
fprintf(cfile, "{%d,%d,{", c2coercs[i].c2_texpno,
|
|
c2coercs[i].c2_nsplit);
|
|
for (j = 0; j < maxsplit; j++)
|
|
fprintf(cfile, "%d,", c2coercs[i].c2_repl[j]);
|
|
fprintf(cfile, "},%d},\n", c2coercs[i].c2_codep);
|
|
}
|
|
fprintf(cfile, "};\n\nc3_t c3coercs[] = {\n");
|
|
for (i = 0; i < nc3; i++)
|
|
fprintf(cfile, "{%d,%d,%d,%d},\n", c3coercs[i].c3_texpno,
|
|
c3coercs[i].c3_prop, c3coercs[i].c3_repl, c3coercs[i].c3_codep);
|
|
fprintf(cfile, "};\n\n");
|
|
for (i = 0; i < nprops; i++)
|
|
{
|
|
fprintf(cfile, "struct reginfo *rlist%d[] = {\n", i);
|
|
for (j = 2; j <= nmachregs; j++)
|
|
{
|
|
if (machregs[j - 1]->rregvar < 0
|
|
&& (machprops[i].propset.set_val[j >> 4] & (1 << (j & 017))))
|
|
fprintf(cfile, "\t&machregs[%d],\n", j - 1);
|
|
}
|
|
fprintf(cfile, "\t0\n};\n");
|
|
}
|
|
fprintf(cfile, "struct reginfo **reglist[] = {\n");
|
|
for (i = 0; i < nprops; i++)
|
|
{
|
|
fprintf(cfile, "\trlist%d,\n", i);
|
|
}
|
|
fprintf(cfile, "};\n");
|
|
fprintf(cfile, "unsigned cc1 = %u;\n", cc1);
|
|
fprintf(cfile, "unsigned cc2 = %u;\n", cc2);
|
|
fprintf(cfile, "unsigned cc3 = %u;\n", cc3);
|
|
fprintf(cfile, "unsigned cc4 = %u;\n", cc4);
|
|
if (rvused)
|
|
outregvar();
|
|
}
|
|
|
|
static void outregvar(void)
|
|
{
|
|
register int i, j;
|
|
|
|
fprintf(hfile, "#define REGVARS\n");
|
|
fprintf(cfile, "#include \"regvar.h\"\n");
|
|
fprintf(cfile, "int nregvar[4] = { ");
|
|
for (i = 0; i < 4; i++)
|
|
fprintf(cfile, "%d, ", nregvar[i]);
|
|
fprintf(cfile, "};\n");
|
|
for (i = 0; i < 4; i++)
|
|
if (nregvar[i] > 0)
|
|
fprintf(cfile, "struct regassigned ratar%d[%d];\n", i, nregvar[i]);
|
|
for (i = 0; i < 4; i++)
|
|
if (nregvar[i] > 0)
|
|
{
|
|
fprintf(cfile, "int rvtar%d[] = {", i);
|
|
for (j = 0; j < nregvar[i]; j++)
|
|
fprintf(cfile, "%d,", rvnumbers[i][j]);
|
|
fprintf(cfile, "};\n");
|
|
}
|
|
fprintf(cfile, "\nint *rvnumbers[] = {\n");
|
|
for (i = 0; i < 4; i++)
|
|
if (nregvar[i] > 0)
|
|
fprintf(cfile, "\trvtar%d,\n", i);
|
|
else
|
|
fprintf(cfile, "\t0,\n");
|
|
fprintf(cfile, "};\n\nstruct regassigned *regassigned[] = {\n");
|
|
for (i = 0; i < 4; i++)
|
|
if (nregvar[i] > 0)
|
|
fprintf(cfile, "\tratar%d,\n", i);
|
|
else
|
|
fprintf(cfile, "\t0,\n");
|
|
fprintf(cfile, "};\n");
|
|
}
|
|
|
|
static void verbose(void)
|
|
{
|
|
fprintf(stderr, "Codebytes %d\n", codebytes);
|
|
fprintf(stderr, "Registers %d(%d)\n", nmachregs, MAXREGS);
|
|
fprintf(stderr, "Properties %d(%d)\n", nprops, MAXPROPS);
|
|
fprintf(stderr, "Tokens %d(%d)\n", nmachtokens, MAXTOKENS);
|
|
fprintf(stderr, "Sets %d(%d)\n", nmachsets, MAXSETS);
|
|
fprintf(stderr, "Tokeninstances %d(%d)\n", narinstance, MAXINSTANCE);
|
|
fprintf(stderr, "Strings %d(%d)\n", ncodestrings, MAXSTRINGS);
|
|
fprintf(stderr, "Enodes %d(%d)\n", (int)(lastnode - nodes), MAXNODES);
|
|
fprintf(stderr, "Patbytes %d(%d)\n", npatbytes, MAXPATTERN);
|
|
}
|
|
|
|
void inbetween(void)
|
|
{
|
|
register ident_p ip;
|
|
register int i, j;
|
|
register move_p mp;
|
|
|
|
lookident = 1; /* for lexical analysis */
|
|
|
|
chktabsiz(nmachsets + 1, MAXSETS, "Expressiontable");
|
|
for (i = 0; i < SETSIZE; i++)
|
|
machsets[nmachsets].set_val[i] = (short)0xFFFF;
|
|
machsets[nmachsets].set_val[0] &= ~1;
|
|
machsets[nmachsets].set_size = 0;
|
|
ip = ilookup("SCRATCH", ENTER);
|
|
ip->i_type = IEXP;
|
|
ip->i_i.i_expno = nmachsets++;
|
|
|
|
for (i = 0; i < SETSIZE; i++)
|
|
machsets[nmachsets].set_val[i] = (short)0xFFFF;
|
|
machsets[nmachsets].set_size = 0;
|
|
ip = ilookup("ALL", ENTER);
|
|
ip->i_type = IEXP;
|
|
allexpno = ip->i_i.i_expno = nmachsets++;
|
|
mp = &machmoves[nmoves++];
|
|
mp->m_set1 = cocosetno;
|
|
mp->m_expr1 = 0;
|
|
mp->m_set2 = nmachsets - 1;
|
|
mp->m_expr2 = 0;
|
|
mp->m_cindex = 0;
|
|
mp->m_cost.c_size = 0;
|
|
mp->m_cost.c_time = 0;
|
|
|
|
/*
|
|
* Create sets of registers per property
|
|
*/
|
|
|
|
for (i = 0; i < nprops; i++)
|
|
{
|
|
short *sp = machprops[i].propset.set_val;
|
|
|
|
sp[0] |= 1;
|
|
for (j = 2; j <= nmachregs; j++)
|
|
if (machregs[j - 1]->rprop[i >> 4] & (1 << (i & 017)))
|
|
sp[j >> 4] |= (1 << (j & 017));
|
|
}
|
|
}
|
|
|
|
int formconversion(register char *p, register token_p tp)
|
|
{
|
|
char buf[256];
|
|
register char *q = buf;
|
|
char field[256];
|
|
register char *f;
|
|
int i;
|
|
|
|
if (p == 0)
|
|
return (0);
|
|
while (*p)
|
|
switch (*p)
|
|
{
|
|
default:
|
|
*q++ = *p++;
|
|
continue;
|
|
case '%':
|
|
p++;
|
|
if (*p == '%')
|
|
{
|
|
*q++ = *p++;
|
|
continue;
|
|
}
|
|
if (*p == '[')
|
|
p++;
|
|
else
|
|
yyerror("Bad character after % in format");
|
|
f = field;
|
|
while (*p != 0 && *p != ']')
|
|
*f++ = *p++;
|
|
*f++ = 0;
|
|
if (*p == ']')
|
|
p++;
|
|
else
|
|
yyerror("Unterminated %[] construct in format");
|
|
for (i = 0; i < TOKENSIZE - 1; i++)
|
|
if (strcmp(field, tp->t_fields[i].t_sname) == 0)
|
|
break;
|
|
if (i == TOKENSIZE - 1)
|
|
yyerror("Unknown field in %[] construct in format");
|
|
*q++ = i + 1;
|
|
}
|
|
*q++ = 0;
|
|
return (strlookup(buf));
|
|
}
|
|
|
|
void setfields(register token_p tp, string format)
|
|
{
|
|
register int i;
|
|
list2 ll;
|
|
register list1 l;
|
|
int type;
|
|
|
|
for (i = 0; i < TOKENSIZE - 1; i++)
|
|
tp->t_fields[i].t_type = 0;
|
|
i = 0;
|
|
for (ll = tp->t_struct; ll != 0; ll = ll->l2next)
|
|
{
|
|
l = ll->l2list;
|
|
if (strcmp(l->l1name, "REGISTER") == 0)
|
|
type = TYPREG;
|
|
else if (strcmp(l->l1name, "INT") == 0)
|
|
type = TYPINT;
|
|
else
|
|
type = TYPSTR;
|
|
for (l = l->l1next; l != 0; l = l->l1next)
|
|
{
|
|
tp->t_fields[i].t_type = type;
|
|
tp->t_fields[i].t_sname = l->l1name;
|
|
i++;
|
|
}
|
|
}
|
|
if (format != 0)
|
|
tp->t_format = formconversion(format, tp);
|
|
else
|
|
tp->t_format = -1;
|
|
}
|
|
|
|
void chkregexp(int number)
|
|
{
|
|
register int i;
|
|
|
|
for (i = nmachregs + 1; i < nmachregs + 1 + nmachtokens; i++)
|
|
if (machsets[number].set_val[i >> 4] & (01 << (i & 017)))
|
|
yyerror("No tokens allowed in this set");
|
|
}
|
|
|
|
int findstructel(int number, string name, int *t)
|
|
{
|
|
register int i;
|
|
register token_p tp;
|
|
register list2 structdecl;
|
|
int offset;
|
|
|
|
for (i = 1; i <= nmachregs; i++)
|
|
if (machsets[number].set_val[i >> 4] & (01 << (i & 017)))
|
|
yyerror("No registers allowed in this set");
|
|
structdecl = 0;
|
|
for (i = nmachregs + 1; i < nmachregs + 1 + nmachtokens; i++)
|
|
{
|
|
if (machsets[number].set_val[i >> 4] & (01 << (i & 017)))
|
|
{
|
|
if (structdecl == 0)
|
|
{
|
|
structdecl = machtokens[i - (nmachregs + 1)].t_struct;
|
|
tp = &machtokens[i - (nmachregs + 1)];
|
|
}
|
|
else if (structdecl != machtokens[i - (nmachregs + 1)].t_struct)
|
|
yyerror("Multiple structs in this set");
|
|
}
|
|
}
|
|
if (structdecl == 0)
|
|
{
|
|
yyerror("No structs in this set");
|
|
return (0);
|
|
}
|
|
for (offset = 0; offset < TOKENSIZE - 1; offset++)
|
|
if (tp->t_fields[offset].t_type != 0
|
|
&& strcmp(tp->t_fields[offset].t_sname, name) == 0)
|
|
{
|
|
*t = tp->t_fields[offset].t_type;
|
|
return (offset + 1);
|
|
}
|
|
yyerror("No such field in this struct");
|
|
return (0);
|
|
}
|
|
|
|
extern char em_flag[];
|
|
|
|
int argtyp(int mn)
|
|
{
|
|
|
|
switch (em_flag[mn - sp_fmnem] & EM_PAR)
|
|
{
|
|
case PAR_W:
|
|
case PAR_S:
|
|
case PAR_Z:
|
|
case PAR_O:
|
|
case PAR_N:
|
|
case PAR_L:
|
|
case PAR_F:
|
|
case PAR_R:
|
|
case PAR_C:
|
|
return (TYPINT);
|
|
default:
|
|
return (TYPSTR);
|
|
}
|
|
}
|
|
|
|
int commontype(expr_t e1, expr_t e2)
|
|
{
|
|
if (e1.expr_typ != e2.expr_typ)
|
|
yyerror("Type incompatibility");
|
|
return (e1.expr_typ);
|
|
}
|
|
|
|
extern char em_mnem[][4];
|
|
|
|
#define HASHSIZE (2*(sp_lmnem-sp_fmnem))
|
|
|
|
struct hashmnem
|
|
{
|
|
char h_name[3];
|
|
byte h_value;
|
|
} hashmnem[HASHSIZE];
|
|
|
|
void inithash(void)
|
|
{
|
|
register int i;
|
|
|
|
for (i = 0; i <= sp_lmnem - sp_fmnem; i++)
|
|
enter(em_mnem[i], i + sp_fmnem);
|
|
}
|
|
|
|
void enter(char *name, int value)
|
|
{
|
|
register unsigned h;
|
|
|
|
h = hash(name) % HASHSIZE;
|
|
while (hashmnem[h].h_name[0] != 0)
|
|
h = (h + 1) % HASHSIZE;
|
|
strncpy(hashmnem[h].h_name, name, 3);
|
|
hashmnem[h].h_value = value;
|
|
}
|
|
|
|
int mlookup(char *name)
|
|
{
|
|
register unsigned int h;
|
|
|
|
h = hash(name) % HASHSIZE;
|
|
while (strncmp(hashmnem[h].h_name, name, 3) != 0
|
|
&& hashmnem[h].h_name[0] != 0)
|
|
h = (h + 1) % HASHSIZE;
|
|
return (hashmnem[h].h_value & BMASK); /* 0 if not found */
|
|
}
|
|
|
|
void hashpatterns(void)
|
|
{
|
|
short index;
|
|
register byte *bp, *tp;
|
|
register short i;
|
|
unsigned short hashvalue;
|
|
int patlen;
|
|
|
|
index = prevind;
|
|
while (index != 0)
|
|
{
|
|
bp = &pattern[index];
|
|
tp = &bp[PO_MATCH];
|
|
i = *tp++ & BMASK;
|
|
if (i == BMASK)
|
|
{
|
|
i = *tp++ & BMASK;
|
|
i |= (*tp++ & BMASK) << BSHIFT;
|
|
}
|
|
patlen = i;
|
|
hashvalue = 0;
|
|
switch (patlen)
|
|
{
|
|
default: /* 3 or more */
|
|
hashvalue = (hashvalue << 4) ^ (*tp++ & BMASK);
|
|
case 2:
|
|
hashvalue = (hashvalue << 4) ^ (*tp++ & BMASK);
|
|
case 1:
|
|
hashvalue = (hashvalue << 4) ^ (*tp++ & BMASK);
|
|
}
|
|
assert(hashvalue!= ILLHASH);
|
|
i = index;
|
|
index = (bp[PO_NEXT] & BMASK) | (bp[PO_NEXT + 1] << BSHIFT);
|
|
bp[PO_HASH] = hashvalue >> BSHIFT;
|
|
hashvalue &= BMASK;
|
|
bp[PO_NEXT] = pathash[hashvalue] & BMASK;
|
|
bp[PO_NEXT + 1] = pathash[hashvalue] >> BSHIFT;
|
|
pathash[hashvalue] = i;
|
|
}
|
|
}
|
|
|
|
static void debug(void)
|
|
{
|
|
register int i, j;
|
|
|
|
for (i = 0; i < ITABSIZE; i++)
|
|
{
|
|
register ident_p ip;
|
|
for (ip = identtab[i]; ip != 0; ip = ip->i_next)
|
|
printf("%-14s %1d %3d\n", ip->i_name, ip->i_type, ip->i_i.i_regno);
|
|
}
|
|
|
|
for (i = 2; i < nmachregs; i++)
|
|
{
|
|
register reginfo rp;
|
|
|
|
rp = machregs[i];
|
|
printf("%s = (\"%s\", %d", rp->rname, rp->rrepr, rp->rsize);
|
|
for (j = 0; j < MAXMEMBERS; j++)
|
|
if (rp->rmembers[j] != 0)
|
|
printf(", %s", machregs[rp->rmembers[j]]->rname);
|
|
printf(")");
|
|
for (j = 0; j < nprops; j++)
|
|
if (rp->rprop[j >> 4] & (1 << (j & 017)))
|
|
printf(", %s", machprops[j].propname->i_name);
|
|
printf(".\n");
|
|
}
|
|
}
|
|
|
|
void out(int n)
|
|
{
|
|
|
|
assert(n >= 0);
|
|
if (n < 128)
|
|
outbyte(n);
|
|
else
|
|
{
|
|
outbyte(n / 256 + 128);
|
|
outbyte(n % 256);
|
|
}
|
|
}
|
|
|
|
void outbyte(int n)
|
|
{
|
|
|
|
fprintf(cfile, "%d, ", n & BMASK);
|
|
codebytes++;
|
|
}
|
|
|
|
void pat(int n)
|
|
{
|
|
|
|
assert(n >= 0);
|
|
if (n < 128)
|
|
patbyte(n);
|
|
else
|
|
{
|
|
patbyte(n / 256 + 128);
|
|
patbyte(n % 256);
|
|
}
|
|
}
|
|
|
|
void patshort(int n)
|
|
{
|
|
|
|
patbyte(n & BMASK);
|
|
patbyte(n >> BSHIFT);
|
|
}
|
|
|
|
void patbyte(int n)
|
|
{
|
|
chktabsiz(npatbytes, MAXPATTERN, "Pattern table");
|
|
pattern[npatbytes++] = n;
|
|
}
|
|
|
|
int max(int a, int b)
|
|
{
|
|
if (a > b)
|
|
return (a);
|
|
return (b);
|
|
}
|
|
|
|
int yywrap(void)
|
|
{
|
|
return 1;
|
|
}
|
|
|