ack/mach/proto/ncg/compute.c
George Koehler 307a8b996e Add regvar_w() and regvar_d() for use with reglap.
If the ncg table uses reglap, then regvar($1, reg_float) would have
two sizes of registers.  An error from ncgg would happen if regvar()
was in a token that allows only one size.  Now one can pick a size
with regvar_w() for word size or regvar_d() for double-word size.

Add regvar_d and regvar_w as keywords in ncgg.  Modify EX_REGVAR to
include the register size.  In ncg, add some checks for the register
size.  In tables without reglap, regvar() works as before, and ncg
ignores the register size in EX_REGVAR.
2017-10-17 12:05:41 -04:00

424 lines
12 KiB
C

#ifndef NORCSID
static char rcsid[] = "$Id$";
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "assert.h"
#include "param.h"
#include "tables.h"
#include "types.h"
#include <cgg_cg.h>
#include "data.h"
#include "result.h"
#include "glosym.h"
#include "extern.h"
#ifdef REGVARS
#include "regvar.h"
#endif
#ifdef USE_TES
#include "label.h"
#endif
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*
* Author: Hans van Staveren
*/
#define LLEAF 01
#define LDEF 02
#define RLEAF 04
#define RDEF 010
#define LLDEF LLEAF|LDEF
#define RLDEF RLEAF|RDEF
char opdesc[] = {
0, /* EX_TOKFIELD */
0, /* EX_ARG */
0, /* EX_CON */
0, /* EX_ALLREG */
LLDEF|RLDEF, /* EX_SAMESIGN */
LLDEF|RLDEF, /* EX_SFIT */
LLDEF|RLDEF, /* EX_UFIT */
0, /* EX_ROM */
LLDEF|RLDEF, /* EX_NCPEQ */
LLDEF|RLDEF, /* EX_SCPEQ */
LLDEF|RLDEF, /* EX_RCPEQ */
LLDEF|RLDEF, /* EX_NCPNE */
LLDEF|RLDEF, /* EX_SCPNE */
LLDEF|RLDEF, /* EX_RCPNE */
LLDEF|RLDEF, /* EX_NCPGT */
LLDEF|RLDEF, /* EX_NCPGE */
LLDEF|RLDEF, /* EX_NCPLT */
LLDEF|RLDEF, /* EX_NCPLE */
LLDEF, /* EX_OR2 */
LLDEF, /* EX_AND2 */
LLDEF|RLDEF, /* EX_PLUS */
LLDEF|RLDEF, /* EX_CAT */
LLDEF|RLDEF, /* EX_MINUS */
LLDEF|RLDEF, /* EX_TIMES */
LLDEF|RLDEF, /* EX_DIVIDE */
LLDEF|RLDEF, /* EX_MOD */
LLDEF|RLDEF, /* EX_LSHIFT */
LLDEF|RLDEF, /* EX_RSHIFT */
LLDEF, /* EX_NOT */
LLDEF, /* EX_COMP */
0, /* EX_COST */
0, /* EX_STRING */
LLEAF, /* EX_DEFINED */
0, /* EX_SUBREG */
LLDEF, /* EX_TOSTRING */
LLDEF, /* EX_UMINUS */
0, /* EX_REG */
0, /* EX_LOWW */
0, /* EX_HIGHW */
LLDEF, /* EX_INREG */
LLDEF, /* EX_REGVAR */
LLDEF|RLDEF, /* EX_OR */
LLDEF|RLDEF, /* EX_XOR */
LLDEF|RLDEF, /* EX_AND */
0, /* EX_ISROM */
#ifdef USE_TES
0, /* EX_TOPELTSIZE */
0, /* EX_FALLTHROUGH */
#endif
};
string salloc(),strcpy(),strcat();
string mycat(s1,s2) register string s1,s2; {
register string s;
if (s1==0 || *s1=='\0') return(s2);
if (s2==0 || *s2=='\0') return(s1);
s=salloc(strlen(s1)+strlen(s2)+1);
strcpy(s,s1);
strcat(s,"+");
strcat(s,s2);
return(s);
}
string mystrcpy(s) register string s; {
register string r;
r=salloc(strlen(s));
strcpy(r,s);
return(r);
}
char digstr[21][15];
string tostring(n) register word n; {
char buf[25];
if (n>=-20 && n<=20 && (n&1)==0) {
if (digstr[((int)n>>1)+10][0]==0)
sprintf(digstr[((int)n>>1)+10],WRD_FMT,n);
return(digstr[((int)n>>1)+10]);
}
sprintf(buf,WRD_FMT,n);
return(mystrcpy(buf));
}
void
compute(node, presult) register node_p node; register result_t *presult; {
result_t leaf1,leaf2;
register token_p tp;
int desc;
long mask,tmp;
int i,tmpreg;
glosym_p gp;
presult->e_typ = EV_UNDEF;
desc=opdesc[node->ex_operator];
if (desc&LLEAF) {
compute(&enodes[node->ex_lnode], &leaf1);
if (desc&LDEF && leaf1.e_typ==EV_UNDEF)
return;
}
if (desc&RLEAF) {
compute(&enodes[node->ex_rnode], &leaf2);
if (desc&RDEF && leaf2.e_typ==EV_UNDEF)
return;
}
presult->e_typ=EV_INT;
switch(node->ex_operator) {
default: assert(FALSE);
case EX_TOKFIELD:
if (node->ex_lnode==0)
if (curtoken) tp = curtoken;
else tp = &fakestack[stackheight-1];
else tp = &fakestack[stackheight-node->ex_lnode];
switch(presult->e_typ = tokens[tp->t_token].t_type[node->ex_rnode-1]) {
default:
assert(FALSE);
case EV_INT:
presult->e_v.e_con = tp->t_att[node->ex_rnode-1].aw;
break;
case EV_ADDR:
presult->e_v.e_addr = tp->t_att[node->ex_rnode-1].aa;
break;
case EV_REG:
presult->e_v.e_reg = tp->t_att[node->ex_rnode-1].ar;
break;
}
return;
case EX_ARG:
*presult = dollar[node->ex_lnode-1];
return;
case EX_CON:
presult->e_typ = EV_INT;
presult->e_v.e_con = ((long) node->ex_rnode << 16) | ((long)node->ex_lnode&0xffff);
return;
case EX_REG:
presult->e_typ = EV_REG;
presult->e_v.e_reg = node->ex_lnode;
return;
case EX_ALLREG:
presult->e_typ = EV_REG;
presult->e_v.e_reg = allreg[node->ex_lnode-1];
#if MAXMEMBERS!=0
if (node->ex_rnode!=0)
presult->e_v.e_reg = machregs[presult->e_v.e_reg].
r_members[node->ex_rnode-1];
#endif
return;
case EX_SAMESIGN:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_typ = EV_INT;
if (leaf1.e_v.e_con>=0)
presult->e_v.e_con= leaf2.e_v.e_con>=0;
else
presult->e_v.e_con= leaf2.e_v.e_con<0;
return;
case EX_SFIT:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
mask = 0xFFFFFFFFL;
for (i=0;i<leaf2.e_v.e_con-1;i++)
mask &= ~(1<<i);
tmp = leaf1.e_v.e_con&mask;
presult->e_v.e_con = tmp==0||tmp==mask;
return;
case EX_UFIT:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
mask = 0xFFFFFFFFL;
for (i=0;i<leaf2.e_v.e_con;i++)
mask &= ~(1<<i);
presult->e_v.e_con = (leaf1.e_v.e_con&mask)==0;
return;
case EX_ROM:
assert(node->ex_rnode>=0 &&node->ex_rnode<MAXROM);
leaf2=dollar[node->ex_lnode];
presult->e_typ = EV_UNDEF;
if (leaf2.e_typ != EV_ADDR)
return;
if (leaf2.e_v.e_addr.ea_off!=0)
return;
gp = lookglo(leaf2.e_v.e_addr.ea_str);
if (gp == (glosym_p) 0)
return;
if ((gp->gl_rom[MAXROM]&(1<<node->ex_rnode))==0)
return;
presult->e_typ = EV_INT;
presult->e_v.e_con = gp->gl_rom[node->ex_rnode];
return;
case EX_ISROM:
leaf2=dollar[node->ex_lnode];
if (leaf2.e_typ != EV_ADDR)
presult->e_v.e_con = 0;
else
presult->e_v.e_con = lookglo(leaf2.e_v.e_addr.ea_str) != 0;
return;
case EX_LOWW:
presult->e_v.e_con = saveemp[node->ex_lnode].em_u.em_loper&0xFFFF;
return;
case EX_HIGHW:
presult->e_v.e_con = saveemp[node->ex_lnode].em_u.em_loper>>16;
return;
case EX_NCPEQ:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con==leaf2.e_v.e_con;
return;
case EX_SCPEQ:
assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR);
presult->e_v.e_con =
(strcmp(leaf1.e_v.e_addr.ea_str,leaf2.e_v.e_addr.ea_str)==0 &&
leaf1.e_v.e_addr.ea_off==leaf2.e_v.e_addr.ea_off);
return;
case EX_RCPEQ:
assert(leaf1.e_typ == EV_REG && leaf2.e_typ == EV_REG);
presult->e_v.e_con = leaf1.e_v.e_reg==leaf2.e_v.e_reg;
return;
case EX_NCPNE:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con!=leaf2.e_v.e_con;
return;
case EX_SCPNE:
assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR);
presult->e_v.e_con =
!(strcmp(leaf1.e_v.e_addr.ea_str,leaf2.e_v.e_addr.ea_str)==0 &&
leaf1.e_v.e_addr.ea_off==leaf2.e_v.e_addr.ea_off);
return;
case EX_RCPNE:
assert(leaf1.e_typ == EV_REG && leaf2.e_typ == EV_REG);
presult->e_v.e_con = leaf1.e_v.e_reg!=leaf2.e_v.e_reg;
return;
case EX_NCPGT:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con>leaf2.e_v.e_con;
return;
case EX_NCPGE:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con>=leaf2.e_v.e_con;
return;
case EX_NCPLT:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con<leaf2.e_v.e_con;
return;
case EX_NCPLE:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con<=leaf2.e_v.e_con;
return;
case EX_OR2:
assert(leaf1.e_typ == EV_INT);
if (leaf1.e_v.e_con==0) {
compute(&enodes[node->ex_rnode], presult);
}
else *presult = leaf1;
return;
case EX_AND2:
assert(leaf1.e_typ == EV_INT);
if (leaf1.e_v.e_con!=0) {
compute(&enodes[node->ex_rnode], presult);
}
else *presult = leaf1;
return;
case EX_PLUS:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con=leaf1.e_v.e_con+leaf2.e_v.e_con;
return;
case EX_CAT:
assert(leaf1.e_typ == EV_ADDR && leaf2.e_typ == EV_ADDR);
presult->e_typ = EV_ADDR;
presult->e_v.e_addr.ea_str = mycat(leaf1.e_v.e_addr.ea_str,leaf2.e_v.e_addr.ea_str);
presult->e_v.e_addr.ea_off = leaf1.e_v.e_addr.ea_off+leaf2.e_v.e_addr.ea_off;
return;
case EX_MINUS:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con - leaf2.e_v.e_con;
return;
case EX_OR:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con | leaf2.e_v.e_con;
return;
case EX_XOR:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con ^ leaf2.e_v.e_con;
return;
case EX_AND:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con & leaf2.e_v.e_con;
return;
case EX_TIMES:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con * leaf2.e_v.e_con;
return;
case EX_DIVIDE:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con / leaf2.e_v.e_con;
return;
case EX_MOD:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con % leaf2.e_v.e_con;
return;
case EX_LSHIFT:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con << leaf2.e_v.e_con;
return;
case EX_RSHIFT:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
presult->e_v.e_con = leaf1.e_v.e_con >> leaf2.e_v.e_con;
return;
case EX_NOT:
assert(leaf1.e_typ == EV_INT);
presult->e_v.e_con = !leaf1.e_v.e_con;
return;
case EX_COMP:
assert(leaf1.e_typ == EV_INT);
presult->e_v.e_con = ~leaf1.e_v.e_con;
return;
case EX_STRING:
presult->e_typ = EV_ADDR;
presult->e_v.e_addr.ea_str = codestrings[node->ex_lnode];
presult->e_v.e_addr.ea_off = 0;
return;
case EX_DEFINED:
presult->e_v.e_con=leaf1.e_typ!=EV_UNDEF;
return;
case EX_SUBREG:
presult->e_typ = EV_REG;
if (node->ex_lnode==0)
if (curtoken) tp = curtoken;
else tp = &fakestack[stackheight-1];
else tp = &fakestack[stackheight-node->ex_lnode];
assert(tp->t_token == -1);
tmpreg= tp->t_att[0].ar;
#if MAXMEMBERS!=0
if (node->ex_rnode)
tmpreg=machregs[tmpreg].r_members[node->ex_rnode-1];
#endif
presult->e_v.e_reg=tmpreg;
return;
case EX_TOSTRING:
assert(leaf1.e_typ == EV_INT);
presult->e_typ = EV_ADDR;
presult->e_v.e_addr.ea_str = "";
presult->e_v.e_addr.ea_off = leaf1.e_v.e_con;
return;
#ifdef REGVARS
case EX_INREG:
assert(leaf1.e_typ == EV_INT);
presult->e_v.e_con = isregtyp((long) leaf1.e_v.e_con);
return;
case EX_REGVAR:
assert(leaf1.e_typ == EV_INT);
i = isregvar_size((long) leaf1.e_v.e_con, node->ex_rnode);
if (i<=0) {
presult->e_typ = EV_UNDEF;
return;
}
presult->e_typ = EV_REG;
presult->e_v.e_reg=i;
return;
#endif /* REGVARS */
case EX_UMINUS:
assert(leaf1.e_typ == EV_INT);
presult->e_v.e_con = -leaf1.e_v.e_con;
return;
#ifdef USE_TES
case EX_TOPELTSIZE: /* Hans, new */
{ register label_p lbl;
lbl = get_label(saveemp[node->ex_lnode].em_u.em_ioper);
if (lbl != (label_p)0) {
presult->e_v.e_con = lbl->lb_height;
} else {
presult->e_v.e_con = 0;
}
return;
}
case EX_FALLTHROUGH: /* Hans, new */
{ register label_p lbl;
lbl = get_label(saveemp[node->ex_lnode].em_u.em_ioper);
if (lbl != (label_p)0) {
presult->e_v.e_con = lbl->lb_fallthrough;
} else presult->e_v.e_con = 0;
return;
}
#endif
}
}