ack/util/ncgg/instruct.c

212 lines
4.4 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 <string.h>
#include "param.h"
#include "instruct.h"
#include "pseudo.h"
#include "varinfo.h"
#include "set.h"
#include "expr.h"
#include "iocc.h"
#include "subr.h"
#include <cgg_cg.h>
#include "extern.h"
extern int niops;
extern iocc_t iops[];
extern int inproc;
extern set_t l_sets[];
extern inst_t l_instances[];
extern expr_t subreg_expr(), regno_expr();
static struct varinfo * setcoco(int n)
{
struct varinfo *vi;
NEW(vi, struct varinfo);
vi->vi_next = VI_NULL;
vi->vi_int[0] = INSSETCC;
vi->vi_int[1] = n;
return (vi);
}
static struct varinfo * generase(int n)
{
struct varinfo *vi;
NEW(vi, struct varinfo);
vi->vi_next = VI_NULL;
vi->vi_int[0] = INSERASE;
vi->vi_int[1] = n;
return (vi);
}
static struct varinfo * genremove(int n)
{
struct varinfo *vi;
NEW(vi, struct varinfo);
vi->vi_next = VI_NULL;
vi->vi_int[0] = INSREMOVE;
vi->vi_int[1] = n;
return (vi);
}
static int onlyreg(int argno)
{
register int bitno;
register short *sp;
if (!argno)
argno++;
sp = l_sets[tokpatset[argno - 1]].set_val;
for (bitno = nregs; bitno < nregs + ntokens; bitno++)
if (BIT(sp, bitno))
return (0);
return (1);
}
static void makescratch(int argno)
{
set_t s;
if (!argno)
argno++;
if (tokpatro[argno - 1])
error("Instruction destroys %%%d, not allowed here", argno);
s = l_sets[tokpatset[argno - 1]];
BIC(s.set_val, 0);
tokpatset[argno - 1] = setlookup(s);
}
struct varinfo *gen_inst(char *ident, int star)
{
register struct varinfo *vi, *retval, *eravi;
register instr_p ip;
register struct operand *op;
register int i;
register inst_p insta;
if (star && !inproc)
error("Variable instruction only allowed inside proc");
for (ip = l_instr; ip < l_instr + ninstr; ip++)
{
if (strcmp(ident, ip->i_name))
continue;
if (ip->i_nops != niops)
continue;
for (i = 0, op = ip->i_oplist; i < niops; i++, op = op->o_next)
{
if (!subset(iops[i].in_set, l_sets[op->o_setno].set_val, SETSIZE))
goto cont;
}
goto found;
/* oh well, one more won't hurt */
cont: ;
}
error("Such an \"%s\" does not exist", ident);
return (0);
found:
NEW(vi, struct varinfo);
vi->vi_int[0] = ip - l_instr;
vi->vi_int[1] = star;
vi->vi_next = 0;
retval = vi;
for (i = 0; i < niops; i++)
{
NEW(vi->vi_vi, struct varinfo);
vi = vi->vi_vi;
vi->vi_int[0] = iops[i].in_index;
}
vi->vi_vi = 0;
vi = retval;
for (i = 0, op = ip->i_oplist; i < niops; i++, op = op->o_next)
{
if (op->o_adorn & AD_CC)
{
vi->vi_next = setcoco(iops[i].in_index);
vi = vi->vi_next;
}
switch (op->o_adorn & AD_RWMASK)
{
default:
/* Nothing possible to do */
break;
case AD_RO:
/* It might be possible to do something
* here but not now.
*/
break;
case AD_RW:
case AD_WO:
/* Treated the same for now */
insta = &l_instances[iops[i].in_index];
switch (insta->in_which)
{
case IN_COPY:
if (insta->in_info[1] == 0
&& !onlyreg(insta->in_info[0]))
break;
makescratch(insta->in_info[0]);
vi->vi_next = generase(ex_lookup(
EX_SUBREG, insta->in_info[0], insta->in_info[1]));
vi = vi->vi_next;
break;
case IN_MEMB:
vi->vi_next = generase(ex_lookup(
EX_TOKFIELD, insta->in_info[0], insta->in_info[1]));
vi = vi->vi_next;
break;
case IN_RIDENT:
vi->vi_next = generase(ex_lookup(
EX_REG, insta->in_info[0], 0));
vi = vi->vi_next;
break;
case IN_ALLOC:
vi->vi_next = generase(ex_lookup(
EX_ALLREG, insta->in_info[0] + 1, insta->in_info[1]));
vi = vi->vi_next;
break;
case IN_S_DESCR:
case IN_D_DESCR:
{
int temp;
if (insta->in_which == IN_S_DESCR)
temp = wordsize;
else
temp = 2 * wordsize;
temp = ex_lookup(EX_REGVAR, insta->in_info[1], temp);
vi->vi_next = generase(temp);
vi = vi->vi_next;
vi->vi_next = genremove(temp);
vi = vi->vi_next;
break;
}
}
break;
}
}
for (eravi = ip->i_erases; eravi != VI_NULL ; eravi = eravi->vi_next)
{
if (eravi->vi_int[0] < 0)
vi->vi_next = setcoco(0);
else
{
vi->vi_next = generase(eravi->vi_int[0]);
vi = vi->vi_next;
vi->vi_next = genremove(eravi->vi_int[0]);
}
vi = vi->vi_next;
}
return (retval);
}