397 lines
8.2 KiB
C
397 lines
8.2 KiB
C
/*
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
*/
|
|
#ifndef NORCSID
|
|
static char rcsid[] = "$Id$";
|
|
#endif
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "param.h"
|
|
#include "set.h"
|
|
#include "reg.h"
|
|
#include "lookup.h"
|
|
#include "token.h"
|
|
#include "property.h"
|
|
#include "expr.h"
|
|
#include "regvar.h"
|
|
#include <cgg_cg.h>
|
|
#include <em_reg.h>
|
|
#include "extern.h"
|
|
|
|
extern set_t l_sets[];
|
|
|
|
int i_expr(expr_t e)
|
|
{
|
|
|
|
if (e.ex_typ != TYPINT)
|
|
error("Expression should be integer");
|
|
return (e.ex_index);
|
|
}
|
|
|
|
int b_expr(expr_t e)
|
|
{
|
|
if (e.ex_typ != TYPBOOL)
|
|
error("Expression should be boolean");
|
|
return (e.ex_index);
|
|
}
|
|
|
|
expr_t make_expr(int type, int operator, int op1, int op2)
|
|
{
|
|
expr_t result;
|
|
|
|
result.ex_typ = type;
|
|
result.ex_index = ex_lookup(operator, op1, op2);
|
|
return (result);
|
|
}
|
|
|
|
expr_t regno_expr(int regno)
|
|
{
|
|
expr_t result;
|
|
register int i;
|
|
|
|
result.ex_typ = TYPREG;
|
|
result.ex_index = ex_lookup(EX_REG, regno, 0);
|
|
for (i = 0; i < SZOFSET(MAXREGS); i++)
|
|
result.ex_regset[i] = 0;
|
|
BIS(result.ex_regset, regno);
|
|
return (result);
|
|
}
|
|
|
|
expr_t ident_expr(char *name)
|
|
{
|
|
register symbol *sy_p;
|
|
|
|
sy_p = lookup(name, symany, mustexist);
|
|
if (sy_p->sy_type == symconst)
|
|
return (make_expr(TYPINT, EX_CON,
|
|
(int) (sy_p->sy_value.syv_cstval & 0xFFFF),
|
|
(int) (sy_p->sy_value.syv_cstval >> 16)));
|
|
else if (sy_p->sy_type == symsconst)
|
|
return (make_expr(TYPADDR, EX_STRING, sy_p->sy_value.syv_stringno, 0));
|
|
else if (sy_p->sy_type != symreg)
|
|
error("Wrong type of identifier %s", name);
|
|
return (regno_expr(sy_p->sy_value.syv_regno));
|
|
}
|
|
|
|
expr_t subreg_expr(int tokarg, int subreg)
|
|
{
|
|
expr_t result;
|
|
|
|
result.ex_typ = TYPREG;
|
|
subregset(l_sets[tokpatset[tokarg > 0 ? tokarg - 1 : tokarg]].set_val,
|
|
subreg, result.ex_regset);
|
|
result.ex_index = ex_lookup(EX_SUBREG, tokarg, subreg);
|
|
return (result);
|
|
}
|
|
|
|
void subregset(register short *sp, int subreg, register short *regset)
|
|
{
|
|
register int i;
|
|
register reginfo *rp;
|
|
|
|
for (i = 0; i < SZOFSET(MAXREGS); i++)
|
|
regset[i] = 0;
|
|
for (i = 1; i < nregs; i++)
|
|
if (BIT(sp, i))
|
|
{
|
|
if (subreg)
|
|
{
|
|
rp = &l_regs[i];
|
|
if (rp->ri_memb[subreg - 1] == 0)
|
|
error("Register %s in set has no member %d", rp->ri_name,
|
|
subreg);
|
|
BIS(regset, rp->ri_memb[subreg - 1]);
|
|
}
|
|
else
|
|
BIS(regset, i);
|
|
}
|
|
for (; i < nregs + MAXTOKENS; i++)
|
|
if (BIT(sp, i))
|
|
error("Set contains %s, which is not a register",
|
|
l_tokens[i - nregs]->tk_name);
|
|
}
|
|
|
|
int membset(int setno, char *name, short *regset, char *appearance, int restyp, int *typp)
|
|
{
|
|
register short *sp;
|
|
register token_p tp;
|
|
register int i, j, k;
|
|
int thistyp;
|
|
int typesdiffer = 0;
|
|
int res_j = -1;
|
|
|
|
if (setno < 0)
|
|
return 0;
|
|
sp = l_sets[setno].set_val;
|
|
for (i = 1; i < nregs; i++)
|
|
if (BIT(sp, i))
|
|
{
|
|
error("Set in %s contains %s, which is not a token", appearance,
|
|
l_regs[i].ri_name);
|
|
break;
|
|
}
|
|
for (i = 0; i < SZOFSET(MAXREGS); i++)
|
|
regset[i] = 0;
|
|
for (i = nregs; i < nregs + MAXTOKENS; i++)
|
|
if (BIT(sp, i))
|
|
{
|
|
tp = l_tokens[i - nregs];
|
|
for (j = 0;
|
|
j < MAXATT
|
|
&& (tp->tk_att[j].ta_type == -3
|
|
|| strcmp(tp->tk_att[j].ta_name, name));
|
|
j++)
|
|
;
|
|
if (j == MAXATT)
|
|
error("Token %s does not contain %s", tp->tk_name, name);
|
|
else if (j != res_j && res_j != -1)
|
|
typesdiffer = 1;
|
|
else
|
|
{
|
|
res_j = j;
|
|
thistyp = tp->tk_att[j].ta_type;
|
|
if (thistyp == -2)
|
|
{
|
|
if (restyp != TYPADDR && restyp != 0)
|
|
typesdiffer = 1;
|
|
else
|
|
restyp = TYPADDR;
|
|
}
|
|
else if (thistyp == -1)
|
|
{
|
|
if (restyp != TYPINT && restyp != 0)
|
|
typesdiffer = 1;
|
|
else
|
|
restyp = TYPINT;
|
|
}
|
|
else
|
|
{
|
|
if (restyp != TYPREG && restyp != 0)
|
|
typesdiffer = 1;
|
|
else
|
|
{
|
|
restyp = TYPREG;
|
|
for (k = 0; k < SZOFSET(MAXREGS); k++)
|
|
regset[k] |=
|
|
l_props[tp->tk_att[j].ta_type].pr_regset[k];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (typesdiffer)
|
|
error("%s is not a valid expression; types differ in the set",
|
|
appearance);
|
|
*typp = restyp == 0 ? TYPINT : restyp;
|
|
return (res_j == -1 ? 0 : res_j);
|
|
}
|
|
|
|
expr_t memb_expr(int setno, char *name, char *appearance, int tokarg)
|
|
{
|
|
expr_t result;
|
|
int res_j;
|
|
|
|
res_j = membset(setno, name, result.ex_regset, appearance, 0,
|
|
&result.ex_typ);
|
|
result.ex_index = ex_lookup(EX_TOKFIELD, tokarg, res_j + 1);
|
|
return (result);
|
|
}
|
|
|
|
expr_t tokm_expr(int tokarg, char *name)
|
|
{
|
|
char app[100];
|
|
int tokarg1 = tokarg > 0 ? tokarg : 1;
|
|
|
|
sprintf(app, "%%%d.%s", tokarg1, name);
|
|
return (memb_expr(tokpatset[tokarg1 - 1], name, app, tokarg));
|
|
}
|
|
|
|
expr_t perc_ident_expr(char *name)
|
|
{
|
|
char app[100];
|
|
|
|
sprintf(app, "%%%s", name);
|
|
return (memb_expr(cursetno, name, app, 0));
|
|
}
|
|
|
|
expr_t all_expr(int all_no, int subreg)
|
|
{
|
|
set_t localset;
|
|
register int i;
|
|
register short *sp;
|
|
expr_t result;
|
|
|
|
sp = l_props[allreg[all_no]].pr_regset;
|
|
for (i = 0; i < SETSIZE; i++)
|
|
localset.set_val[i] = i < SZOFSET(MAXREGS) ? sp[i] : 0;
|
|
subregset(localset.set_val, subreg, result.ex_regset);
|
|
result.ex_typ = TYPREG;
|
|
result.ex_index = ex_lookup(EX_ALLREG, all_no + 1, subreg);
|
|
return (result);
|
|
}
|
|
|
|
int eq2expr(expr_t e1, expr_t e2)
|
|
{
|
|
|
|
if (e1.ex_typ != e2.ex_typ)
|
|
error("Expressions around == should have equal type");
|
|
switch (e1.ex_typ)
|
|
{
|
|
default:
|
|
assert(0);
|
|
case TYPBOOL:
|
|
error("== on booleans not implemented");
|
|
case TYPINT:
|
|
return (EX_NCPEQ);
|
|
case TYPADDR:
|
|
return (EX_SCPEQ);
|
|
case TYPREG:
|
|
return (EX_RCPEQ);
|
|
}
|
|
}
|
|
|
|
int ne2expr(expr_t e1, expr_t e2)
|
|
{
|
|
|
|
if (e1.ex_typ != e2.ex_typ)
|
|
error("Expressions around != should have equal type");
|
|
switch (e1.ex_typ)
|
|
{
|
|
default:
|
|
assert(0);
|
|
case TYPBOOL:
|
|
error("!= on booleans not implemented");
|
|
case TYPINT:
|
|
return (EX_NCPNE);
|
|
case TYPADDR:
|
|
return (EX_SCPNE);
|
|
case TYPREG:
|
|
return (EX_RCPNE);
|
|
}
|
|
}
|
|
|
|
expr_t sum_expr(expr_t e1, expr_t e2)
|
|
{
|
|
int operator, op1, op2;
|
|
expr_t result;
|
|
|
|
operator = EX_CAT;
|
|
op1 = e1.ex_index;
|
|
op2 = e2.ex_index;
|
|
if (e1.ex_typ == e2.ex_typ)
|
|
{
|
|
result.ex_typ = e1.ex_typ;
|
|
if (e1.ex_typ == TYPINT)
|
|
operator = EX_PLUS;
|
|
else if (e1.ex_typ != TYPADDR)
|
|
error("+ is not implemented on this type");
|
|
}
|
|
else
|
|
{
|
|
result.ex_typ = TYPADDR;
|
|
if (e1.ex_typ != TYPADDR)
|
|
{
|
|
if (e1.ex_typ != TYPINT)
|
|
error("Wrong left operand of +");
|
|
op1 = ex_lookup(EX_TOSTRING, op1, 0);
|
|
}
|
|
if (e2.ex_typ != TYPADDR)
|
|
{
|
|
if (e2.ex_typ != TYPINT)
|
|
error("Wrong right operand of +");
|
|
op2 = ex_lookup(EX_TOSTRING, op2, 0);
|
|
}
|
|
}
|
|
result.ex_index = ex_lookup(operator, op1, op2);
|
|
return (result);
|
|
}
|
|
|
|
expr_t iextoaddr(expr_t e)
|
|
{
|
|
expr_t result;
|
|
|
|
result.ex_typ = TYPADDR;
|
|
result.ex_index = ex_lookup(EX_TOSTRING, e.ex_index, 0);
|
|
return (result);
|
|
}
|
|
|
|
expr_t regvar_expr(expr_t e, int regtyp, int regsiz)
|
|
{
|
|
expr_t result;
|
|
int i, regno, s, two_sizes;
|
|
|
|
two_sizes = (regtyp == reg_float && reglap != 0);
|
|
if (regsiz == -1)
|
|
{
|
|
/* reglap: Can't guess between 2 sizes of reg_float. */
|
|
if (two_sizes && regsiz == -1)
|
|
error("Must use regvar_w() or regvar_d()");
|
|
else
|
|
regsiz = rvsize[regtyp];
|
|
}
|
|
|
|
result = make_expr(TYPREG, EX_REGVAR, i_expr(e), regsiz);
|
|
for (i = 0; i < SZOFSET(MAXREGS); i++)
|
|
result.ex_regset[i] = 0;
|
|
|
|
/* s = the size of the registers in rvnumbers[regtyp] */
|
|
s = two_sizes ? reglap : rvsize[regtyp];
|
|
if (s == regsiz)
|
|
{
|
|
for (i = 0; i < nregvar[regtyp]; i++)
|
|
BIS(result.ex_regset, rvnumbers[regtyp][i]);
|
|
}
|
|
/* reglap: Also check the 2nd size of reg_float. */
|
|
if (two_sizes && rvsize[regtyp] == regsiz)
|
|
{
|
|
for (i = 0; i < nregvar[regtyp]; i++)
|
|
{
|
|
/* regno = first subregister */
|
|
regno = l_regs[rvnumbers[regtyp][i]].ri_memb[0];
|
|
if (regno != 0)
|
|
BIS(result.ex_regset, regno);
|
|
}
|
|
}
|
|
return (result);
|
|
}
|
|
|
|
/*
|
|
* Node table lookup part
|
|
*/
|
|
|
|
node_t nodes[MAXNODES];
|
|
int nnodes = 0;
|
|
|
|
void initnodes(void)
|
|
{
|
|
|
|
nodes[0].ex_operator = EX_CON;
|
|
nodes[0].ex_lnode = 0;
|
|
nodes[0].ex_rnode = 0;
|
|
nnodes++;
|
|
}
|
|
|
|
int ex_lookup(int operator, int lnode, int rnode)
|
|
{
|
|
register node_p p;
|
|
|
|
for (p = nodes + 1; p < &nodes[nnodes]; p++)
|
|
{
|
|
if (p->ex_operator != operator)
|
|
continue;
|
|
if (p->ex_lnode != lnode)
|
|
continue;
|
|
if (p->ex_rnode != rnode)
|
|
continue;
|
|
return (p - nodes);
|
|
}
|
|
NEXT(nnodes, MAXNODES, "Node");
|
|
p->ex_operator = operator;
|
|
p->ex_lnode = lnode;
|
|
p->ex_rnode = rnode;
|
|
return (p - nodes);
|
|
}
|