ack/mach/proto/ncg/compute.c

421 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 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));
}
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((long) leaf1.e_v.e_con);
if (i<=0) {
presult->e_typ = EV_UNDEF;
return;
}
presult->e_typ = EV_REG;
presult->e_v.e_reg=i;
return;
#endif
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
}
}